mirror of
https://github.com/garethgeorge/backrest.git
synced 2025-12-13 17:25:38 +00:00
138 lines
3.0 KiB
Go
138 lines
3.0 KiB
Go
package permissions
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
v1 "github.com/garethgeorge/backrest/gen/go/v1"
|
|
)
|
|
|
|
type ScopeSet struct {
|
|
plans map[string]struct{}
|
|
repos map[string]struct{}
|
|
|
|
excludedPlans map[string]struct{}
|
|
excludedRepos map[string]struct{}
|
|
|
|
wildcard bool
|
|
}
|
|
|
|
func NewScopeSet(scopes []string) (*ScopeSet, error) {
|
|
scopeSet := &ScopeSet{
|
|
plans: make(map[string]struct{}),
|
|
repos: make(map[string]struct{}),
|
|
excludedPlans: make(map[string]struct{}),
|
|
excludedRepos: make(map[string]struct{}),
|
|
wildcard: false,
|
|
}
|
|
|
|
for _, scope := range scopes {
|
|
if scope == "*" {
|
|
scopeSet.wildcard = true
|
|
} else if len(scope) > 5 && strings.HasPrefix(scope, "repo:") {
|
|
scopeSet.repos[scope[len("repo:"):]] = struct{}{}
|
|
} else if len(scope) > 5 && strings.HasPrefix(scope, "plan:") {
|
|
scopeSet.plans[scope[len("plan:"):]] = struct{}{}
|
|
} else if len(scope) > 6 && strings.HasPrefix(scope, "!repo:") {
|
|
scopeSet.excludedRepos[scope[len("!repo:"):]] = struct{}{}
|
|
} else if len(scope) > 6 && strings.HasPrefix(scope, "!plan:") {
|
|
scopeSet.excludedPlans[scope[len("!plan:"):]] = struct{}{}
|
|
} else {
|
|
return nil, fmt.Errorf("invalid scope format: %s", scope)
|
|
}
|
|
}
|
|
|
|
return scopeSet, nil
|
|
}
|
|
|
|
func (s *ScopeSet) ContainsPlan(planID string) bool {
|
|
if _, ok := s.excludedPlans[planID]; ok {
|
|
return false
|
|
}
|
|
if s.wildcard {
|
|
return true
|
|
}
|
|
if _, ok := s.plans[planID]; ok {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (s *ScopeSet) ContainsRepo(repoID string) bool {
|
|
if _, ok := s.excludedRepos[repoID]; ok {
|
|
return false
|
|
}
|
|
if s.wildcard {
|
|
return true
|
|
}
|
|
if _, ok := s.repos[repoID]; ok {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (s *ScopeSet) Merge(other *ScopeSet) {
|
|
if other.wildcard {
|
|
s.wildcard = true
|
|
return
|
|
}
|
|
|
|
for planID := range other.plans {
|
|
s.plans[planID] = struct{}{}
|
|
}
|
|
for repoID := range other.repos {
|
|
s.repos[repoID] = struct{}{}
|
|
}
|
|
for planID := range other.excludedPlans {
|
|
s.excludedPlans[planID] = struct{}{}
|
|
}
|
|
for repoID := range other.excludedRepos {
|
|
s.excludedRepos[repoID] = struct{}{}
|
|
}
|
|
}
|
|
|
|
type PermissionSet struct {
|
|
perms map[v1.Multihost_Permission_Type]ScopeSet
|
|
}
|
|
|
|
func NewPermissionSet(perms []*v1.Multihost_Permission) (*PermissionSet, error) {
|
|
permSet := &PermissionSet{
|
|
perms: make(map[v1.Multihost_Permission_Type]ScopeSet),
|
|
}
|
|
|
|
for _, perm := range perms {
|
|
if perm.Scopes == nil {
|
|
continue
|
|
}
|
|
scopeSet, err := NewScopeSet(perm.Scopes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
permSet.perms[perm.Type] = *scopeSet
|
|
}
|
|
|
|
return permSet, nil
|
|
}
|
|
|
|
func (p *PermissionSet) CheckPermissionForPlan(planID string, permType ...v1.Multihost_Permission_Type) bool {
|
|
for _, pt := range permType {
|
|
if scopeSet, ok := p.perms[pt]; ok {
|
|
if scopeSet.ContainsPlan(planID) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (p *PermissionSet) CheckPermissionForRepo(repoID string, permType ...v1.Multihost_Permission_Type) bool {
|
|
for _, pt := range permType {
|
|
if scopeSet, ok := p.perms[pt]; ok {
|
|
if scopeSet.ContainsRepo(repoID) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|