Files
RenewCMS/internal/domain/role/roleGrantSet.go
T

115 lines
2.3 KiB
Go

package role
type MissingPermissionError struct {
Key string
}
func (e MissingPermissionError) Error() string {
return ErrMissingPermission.Error() + ": " + e.Key
}
func (e MissingPermissionError) Is(target error) bool {
return target == ErrMissingPermission
}
type GrantSet struct {
scopes map[string]Scope
}
func (r Role) GrantSet() GrantSet {
scopes := make(map[string]Scope, len(r.Grants))
for _, grant := range r.Grants {
permission, err := resolveGrantKey(grant.Key)
if err != nil || permission.OwnerOnly && !r.Locked {
continue
}
scope := effectiveScope(permission.Kind, grant.Scope)
if held, present := scopes[grant.Key]; present {
scope = mostRestrictive(held, scope)
}
scopes[grant.Key] = scope
}
return GrantSet{scopes: scopes}
}
func effectiveScope(kind Kind, scope Scope) Scope {
switch {
case scope == ScopeAll:
return ScopeAll
case scope == ScopeOwn && kind == KindScoped:
return ScopeOwn
default:
return ScopeNone
}
}
func scopeRank(scope Scope) int {
switch scope {
case ScopeAll:
return 2
case ScopeOwn:
return 1
default:
return 0
}
}
func mostRestrictive(left Scope, right Scope) Scope {
if scopeRank(left) <= scopeRank(right) {
return left
}
return right
}
func (g GrantSet) ScopeFor(key string, typeKey string) Scope {
if typeKey == "" {
return g.wildcard(key)
}
composite := key + typeSeparator + typeKey
if _, _, err := ParseTypedKey(composite); err != nil {
return ScopeNone
}
if scope, present := g.scopes[composite]; present {
return scope
}
return g.wildcard(key)
}
func (g GrantSet) wildcard(key string) Scope {
if isTypedKey(key) {
return ScopeNone
}
scope, present := g.scopes[key]
if !present {
return ScopeNone
}
return scope
}
func (g GrantSet) Permits(key string, typeKey string, callerID uint32, createdBy uint32) bool {
return ScopePermits(g.ScopeFor(key, typeKey), callerID, createdBy)
}
func ScopePermits(scope Scope, callerID uint32, createdBy uint32) bool {
switch scope {
case ScopeAll:
return true
case ScopeOwn:
return callerID != 0 && callerID == createdBy
default:
return false
}
}
func (g GrantSet) HoldsFor(key string, typeKey string) bool {
return g.ScopeFor(key, typeKey) != ScopeNone
}
func (g GrantSet) Holds(key string) bool {
return g.HoldsFor(key, "")
}
func (g GrantSet) HoldsAll(key string) bool {
return g.ScopeFor(key, "") == ScopeAll
}