package httpauth import ( "context" "encoding/json" "code.nochebuena.dev/go/rbac" ) type claimsPermissionProvider struct { claimsKey string } // NewClaimsPermissionProvider returns an rbac.PermissionProvider that reads // pre-computed permission masks from JWT claims stored in the request context // by SetTokenData. Expects claims[claimsKey] to be a map[string]any where each // key is a resource name and the value is the bitmask as int64 or float64 // (JSON unmarshaling decodes numbers as float64). // Returns 0 without error if the claim is absent — callers treat 0 as no access. func NewClaimsPermissionProvider(claimsKey string) rbac.PermissionProvider { return &claimsPermissionProvider{claimsKey: claimsKey} } func (p *claimsPermissionProvider) ResolveMask(ctx context.Context, _, resource string) (rbac.PermissionMask, error) { claims, ok := getClaims(ctx) if !ok { return 0, nil } masks, ok := claims[p.claimsKey].(map[string]any) if !ok { return 0, nil } // Check specific resource first, then wildcard fallback. for _, key := range []string{resource, "*"} { switch v := masks[key].(type) { case int64: return rbac.PermissionMask(v), nil case float64: return rbac.PermissionMask(int64(v)), nil case json.Number: n, err := v.Int64() if err != nil { return 0, nil } return rbac.PermissionMask(n), nil } } return 0, nil }