grafana/pkg/kinds/accesspolicy/utils.go

100 lines
2.0 KiB
Go

package accesspolicy
import (
"sort"
"github.com/grafana/grafana/pkg/util"
)
const PermissionsTarget = "permissions"
const AllowAll = "*"
const AllowNone = "none"
func ReduceRules(rules []AccessRule) []AccessRule {
type verbs struct {
Verb map[string][]string
Terminal string
}
kinds := make(map[string]*verbs)
for _, rule := range rules {
if rule.Kind == "" || rule.Verb == "" {
continue // invalid
}
// flip write permission to *
if rule.Target != nil && *rule.Target == PermissionsTarget {
if rule.Verb == "write" {
rule.Verb = AllowAll
}
}
kind, ok := kinds[rule.Kind]
if !ok {
kind = &verbs{
Verb: make(map[string][]string),
}
kinds[rule.Kind] = kind
}
terminal := rule.Verb == AllowAll || rule.Verb == AllowNone
if terminal {
if rule.Kind == AllowAll {
return []AccessRule{rule}
}
kind.Terminal = rule.Verb
} else if kind.Terminal == "" {
targets, ok := kind.Verb[rule.Verb]
if !ok {
targets = []string{}
}
if rule.Target != nil && !contains(targets, *rule.Target) {
targets = append(targets, *rule.Target)
sort.Strings(targets)
}
kind.Verb[rule.Verb] = targets
}
}
results := make([]AccessRule, 0)
for _, kind := range getSortedKeys(kinds) {
verb := kinds[kind]
if verb.Terminal != "" {
results = append(results, AccessRule{Kind: kind, Verb: verb.Terminal})
} else {
for _, v := range getSortedKeys(verb.Verb) {
targets := verb.Verb[v]
if len(targets) == 0 {
results = append(results, AccessRule{Kind: kind, Verb: v})
} else {
for _, t := range targets {
results = append(results, AccessRule{
Kind: kind,
Verb: v,
Target: util.Pointer(t),
})
}
}
}
}
}
return results
}
func getSortedKeys[T any](vals map[string]T) []string {
keys := make([]string, 0, len(vals))
for k := range vals {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
func contains[T comparable](s []T, e T) bool {
for _, v := range s {
if v == e {
return true
}
}
return false
}