Files
grafana/pkg/services/authz/zanzana/common/translations.go
Alexander Zobnin 3fca7cf952 Zanzana: Refactor basic role write APIs (#113397)
* Zanzana: Refactor basic role write APIs

* Fix updates

* fix linter
2025-11-04 16:29:56 +01:00

166 lines
4.5 KiB
Go

package common
import (
"slices"
authlib "github.com/grafana/authlib/types"
dashboards "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
const (
roleGrafanaAdmin = "Grafana Admin"
roleAdmin = "Admin"
roleEditor = "Editor"
roleViewer = "Viewer"
roleNone = "None"
)
var basicRolesTranslations = map[string]string{
roleGrafanaAdmin: "basic_grafana_admin",
roleAdmin: "basic_admin",
roleEditor: "basic_editor",
roleViewer: "basic_viewer",
roleNone: "basic_none",
}
var basicRolesUIDs = []string{
"basic_grafana_admin",
"basic_admin",
"basic_editor",
"basic_viewer",
"basic_none",
}
type resourceTranslation struct {
typ string
group string
resource string
mapping map[string]actionMappig
}
type actionMappig struct {
relation string
group string
resource string
subresource string
}
func newMapping(relation, subresource string) actionMappig {
return newScopedMapping(relation, "", "", subresource)
}
func newScopedMapping(relation, group, resource, subresource string) actionMappig {
return actionMappig{relation, group, resource, subresource}
}
var (
folderGroup = folders.FolderResourceInfo.GroupResource().Group
folderResource = folders.FolderResourceInfo.GroupResource().Resource
dashboardGroup = dashboards.DashboardResourceInfo.GroupResource().Group
dashboardResource = dashboards.DashboardResourceInfo.GroupResource().Resource
)
var resourceTranslations = map[string]resourceTranslation{
KindFolders: {
typ: TypeFolder,
group: folderGroup,
resource: folderResource,
mapping: map[string]actionMappig{
"folders:read": newMapping(RelationGet, ""),
"folders:write": newMapping(RelationUpdate, ""),
"folders:create": newMapping(RelationCreate, ""),
"folders:delete": newMapping(RelationDelete, ""),
"dashboards:read": newScopedMapping(RelationGet, dashboardGroup, dashboardResource, ""),
"dashboards:write": newScopedMapping(RelationUpdate, dashboardGroup, dashboardResource, ""),
"dashboards:create": newScopedMapping(RelationCreate, dashboardGroup, dashboardResource, ""),
"dashboards:delete": newScopedMapping(RelationDelete, dashboardGroup, dashboardResource, ""),
// Action sets
"folders:view": newMapping(RelationSetView, ""),
"folders:edit": newMapping(RelationSetEdit, ""),
"folders:admin": newMapping(RelationSetAdmin, ""),
"dashboards:view": newScopedMapping(RelationSetView, dashboardGroup, dashboardResource, ""),
"dashboards:edit": newScopedMapping(RelationSetEdit, dashboardGroup, dashboardResource, ""),
"dashboards:admin": newScopedMapping(RelationSetAdmin, dashboardGroup, dashboardResource, ""),
},
},
KindDashboards: {
typ: TypeResource,
group: dashboardGroup,
resource: dashboardResource,
mapping: map[string]actionMappig{
"dashboards:read": newMapping(RelationGet, ""),
"dashboards:write": newMapping(RelationUpdate, ""),
"dashboards:create": newMapping(RelationCreate, ""),
"dashboards:delete": newMapping(RelationDelete, ""),
// Action sets
"dashboards:view": newMapping(RelationSetView, ""),
"dashboards:edit": newMapping(RelationSetEdit, ""),
"dashboards:admin": newMapping(RelationSetAdmin, ""),
},
},
}
func TranslateToCheckRequest(namespace, action, kind, name string) (*authlib.CheckRequest, bool) {
translation, ok := resourceTranslations[kind]
if !ok {
return nil, false
}
m, ok := translation.mapping[action]
if !ok {
return nil, false
}
verb, ok := RelationToVerbMapping[m.relation]
if !ok {
return nil, false
}
req := &authlib.CheckRequest{
Namespace: namespace,
Verb: verb,
Group: translation.group,
Resource: translation.resource,
Name: name,
}
return req, true
}
func TranslateToListRequest(namespace, action, kind string) (*authlib.ListRequest, bool) {
translation, ok := resourceTranslations[kind]
if !ok {
return nil, false
}
// FIXME: support different verbs
req := &authlib.ListRequest{
Namespace: namespace,
Group: translation.group,
Resource: translation.resource,
}
return req, true
}
func TranslateToGroupResource(kind string) string {
translation, ok := resourceTranslations[kind]
if !ok {
return ""
}
return FormatGroupResource(translation.group, translation.resource, "")
}
func TranslateBasicRole(name string) string {
return basicRolesTranslations[name]
}
func IsBasicRole(name string) bool {
return slices.Contains(basicRolesUIDs, name)
}