// Package authorization owns the fixed, low-cardinality permission vocabulary // used by HTTP authentication and endpoint handlers. package authorization import ( "errors" "strings" ) const ( All = "*" AdminRead = "admin:read" AdminWrite = "admin:write" DistributionExtract = "distribution:extract" ) var ErrInvalidPermissions = errors.New("invalid permissions") // Validate accepts an omitted permission set for backwards-compatible full // access. An explicit set is strict, finite, duplicate-free, and cannot mix // the global permission with narrower grants. func Validate(permissions []string) error { if len(permissions) == 0 { return nil } seen := make(map[string]struct{}, len(permissions)) for _, permission := range permissions { if strings.TrimSpace(permission) != permission || !known(permission) { return ErrInvalidPermissions } if _, exists := seen[permission]; exists { return ErrInvalidPermissions } seen[permission] = struct{}{} } if _, hasAll := seen[All]; hasAll && len(seen) != 1 { return ErrInvalidPermissions } return nil } // Allows reports whether one authenticated identity can invoke an endpoint. // Empty permissions preserve pre-scope configurations as full access. func Allows(permissions []string, required string) bool { if len(permissions) == 0 { return true } for _, permission := range permissions { if permission == All || permission == required { return true } } return false } func known(permission string) bool { switch permission { case All, AdminRead, AdminWrite, DistributionExtract: return true default: return false } }