package bouncer import ( "context" "time" ) type userKey struct{} // ScopeLimit restricts a principal to the permission patterns of its personal // API token. Nil means unrestricted (a JWT session). Only a token guard sets // Scope, already filtered to scopes whose methods include the request method. // Full is true for framework scopes that act as the owner on every allowed // method ("*") or on GET/HEAD ("admin:read"). Otherwise Scopes holds one // pattern slice per method-allowed scope (D-03 literal reading). type ScopeLimit struct { Full bool Scopes [][]string } // Principal is the authenticated identity stored on the request context. // PreferredLocale empty means no override. TokensValidAfter zero means no cutoff. // IsSuperuser and PermissionGrants are set only for backend-admin principals. // A grant ending in ".*" matches permission codes by prefix. // Scope is set only for personal API token principals. type Principal struct { ID uint MustChangePassword bool PreferredLocale string TokensValidAfter time.Time Backend bool `json:"-"` IsSuperuser bool `json:"-"` PermissionGrants map[string]bool `json:"-"` Scope *ScopeLimit `json:"-"` } // WithUser stores the verified principal on ctx. func WithUser(ctx context.Context, user *Principal) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, userKey{}, user) } // User returns the verified principal from ctx. func User(ctx context.Context) (*Principal, bool) { if ctx == nil { return nil, false } u, ok := ctx.Value(userKey{}).(*Principal) return u, ok && u != nil } type credentialKey struct{} // WithCredential stores the resolved credential (e.g. *ApiToken) on ctx. func WithCredential(ctx context.Context, cred any) context.Context { if ctx == nil { ctx = context.Background() } return context.WithValue(ctx, credentialKey{}, cred) } // Credential returns the resolved credential from ctx. func Credential(ctx context.Context) (any, bool) { if ctx == nil { return nil, false } c := ctx.Value(credentialKey{}) if c == nil { return nil, false } return c, true }