mirror of
https://github.com/grafana/grafana.git
synced 2024-11-28 19:54:10 -06:00
100 lines
2.0 KiB
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
|
|
}
|