grafana/pkg/services/accesscontrol/scope.go
Gabriel MABILLE 6a3ce8bd38
AccessControl: tidy scope resolution (#40677)
* AccessControl: tidy scope resolution
2021-10-20 17:11:22 +02:00

70 lines
2.0 KiB
Go

package accesscontrol
import (
"fmt"
"strings"
"github.com/grafana/grafana/pkg/models"
)
// Scope builds scope from parts
// e.g. Scope("users", "*") return "users:*"
func Scope(parts ...string) string {
b := strings.Builder{}
for i, c := range parts {
if i != 0 {
b.WriteRune(':')
}
b.WriteString(c)
}
return b.String()
}
// Parameter returns injectable scope part, based on URL parameters.
// e.g. Scope("users", Parameter(":id")) or "users:" + Parameter(":id")
func Parameter(key string) string {
return fmt.Sprintf(`{{ index .URLParams "%s" }}`, key)
}
// Field returns an injectable scope part for selected fields from the request's context available in accesscontrol.ScopeParams.
// e.g. Scope("orgs", Parameter("OrgID")) or "orgs:" + Parameter("OrgID")
func Field(key string) string {
return fmt.Sprintf(`{{ .%s }}`, key)
}
type KeywordScopeResolveFunc func(*models.SignedInUser) (string, error)
// ScopeResolver contains a map of functions to resolve scope keywords such as `self` or `current` into `id` based scopes
type ScopeResolver struct {
keywordResolvers map[string]KeywordScopeResolveFunc
}
func NewScopeResolver() ScopeResolver {
return ScopeResolver{
keywordResolvers: map[string]KeywordScopeResolveFunc{
"orgs:current": resolveCurrentOrg,
"users:self": resolveUserSelf,
},
}
}
func resolveCurrentOrg(u *models.SignedInUser) (string, error) {
return Scope("orgs", "id", fmt.Sprintf("%v", u.OrgId)), nil
}
func resolveUserSelf(u *models.SignedInUser) (string, error) {
return Scope("users", "id", fmt.Sprintf("%v", u.UserId)), nil
}
// ResolveKeyword resolves scope with keywords such as `self` or `current` into `id` based scopes
func (s *ScopeResolver) ResolveKeyword(user *models.SignedInUser, permission Permission) (*Permission, error) {
if fn, ok := s.keywordResolvers[permission.Scope]; ok {
resolvedScope, err := fn(user)
if err != nil {
return nil, fmt.Errorf("could not resolve %v: %v", permission.Scope, err)
}
permission.Scope = resolvedScope
}
return &permission, nil
}