Files
Pulse/pkg/auth/authorizer.go

90 lines
2.6 KiB
Go

package auth
import "context"
// Authorizer defines the interface for making access control decisions.
type Authorizer interface {
// Authorize checks if a subject (from context) can perform an action on a resource.
// Returns true if allowed, false if denied, and an error if the check failed due to a system issue.
Authorize(ctx context.Context, action string, resource string) (bool, error)
}
type contextKey string
const (
contextKeyUser contextKey = "user"
contextKeyAPIToken contextKey = "apiToken"
)
// APITokenInfo is a minimal interface for checking token scopes without circular dependencies.
type APITokenInfo interface {
HasScope(scope string) bool
}
// WithUser adds a username to the context
func WithUser(ctx context.Context, username string) context.Context {
return context.WithValue(ctx, contextKeyUser, username)
}
// GetUser extracts the username from the context
func GetUser(ctx context.Context) string {
if user, ok := ctx.Value(contextKeyUser).(string); ok {
return user
}
return ""
}
// WithAPIToken adds an API token record to the context
func WithAPIToken(ctx context.Context, token APITokenInfo) context.Context {
return context.WithValue(ctx, contextKeyAPIToken, token)
}
// GetAPIToken extracts the API token record from the context
func GetAPIToken(ctx context.Context) APITokenInfo {
if token, ok := ctx.Value(contextKeyAPIToken).(APITokenInfo); ok {
return token
}
return nil
}
// GetAPITokenContextKey returns the context key used for API tokens (for testing purposes)
func GetAPITokenContextKey() any {
return contextKeyAPIToken
}
// DefaultAuthorizer is a pass-through implementation that allows everything.
// Used in OSS version and when enterprise features are disabled.
type DefaultAuthorizer struct{}
func (d *DefaultAuthorizer) Authorize(ctx context.Context, action string, resource string) (bool, error) {
return true, nil
}
var globalAuthorizer Authorizer = &DefaultAuthorizer{}
// SetAuthorizer sets the global authorizer instance.
// This is used by pulse-enterprise to register the real RBAC implementation.
func SetAuthorizer(auth Authorizer) {
globalAuthorizer = auth
}
// AdminConfigurable is an optional interface for authorizers that can have an admin user set.
type AdminConfigurable interface {
SetAdminUser(username string)
}
// SetAdminUser sets the admin user on the global authorizer if it supports it.
func SetAdminUser(username string) {
if username == "" {
return
}
if configurable, ok := globalAuthorizer.(AdminConfigurable); ok {
configurable.SetAdminUser(username)
}
}
// GetAuthorizer returns the global authorizer instance.
func GetAuthorizer() Authorizer {
return globalAuthorizer
}