From 4caa9853cb0280a425be1e9a774f7cda616b2a9f Mon Sep 17 00:00:00 2001 From: Cory Forseth Date: Tue, 8 Apr 2025 09:15:03 -0500 Subject: [PATCH] Authorization: Add group to role DisplayName to make filtered list more clear (#102950) * add group to role DisplayName to make searching easier * clean up more role names; add filtered display text when fetching * pass filter state into role menu to decide how to display role name * prop name better describes what it does --- pkg/api/accesscontrol.go | 20 +++++++------- .../ossaccesscontrol/dashboard.go | 4 +-- .../accesscontrol/ossaccesscontrol/folder.go | 4 +-- .../ossaccesscontrol/service_account.go | 4 +-- .../accesscontrol/ossaccesscontrol/team.go | 4 +-- pkg/services/accesscontrol/roles.go | 26 +++++++++---------- .../pluginaccesscontrol/accesscontrol.go | 4 +-- pkg/services/serviceaccounts/manager/roles.go | 6 ++--- .../supportbundlesimpl/models.go | 4 +-- .../RolePicker/RoleMenuGroupsSection.tsx | 3 +++ .../components/RolePicker/RoleMenuOption.tsx | 5 ++-- .../core/components/RolePicker/RolePicker.tsx | 2 ++ .../components/RolePicker/RolePickerMenu.tsx | 3 +++ .../RolePicker/RolePickerSubMenu.tsx | 1 + public/app/core/components/RolePicker/api.ts | 8 +++--- .../app/core/components/RolePicker/utils.ts | 6 +++++ .../RolePickerBadges.test.tsx | 1 + public/app/types/accessControl.ts | 1 + 18 files changed, 62 insertions(+), 44 deletions(-) diff --git a/pkg/api/accesscontrol.go b/pkg/api/accesscontrol.go index fba8973eaa3..d7cea857893 100644 --- a/pkg/api/accesscontrol.go +++ b/pkg/api/accesscontrol.go @@ -99,7 +99,7 @@ func (hs *HTTPServer) declareFixedRoles() error { builtInDatasourceReader := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:datasources.builtin:reader", - DisplayName: "Built in reader", + DisplayName: "Built in data source reader", Description: "Read and query Grafana's built in test data sources.", Group: "Data sources", Permissions: []ac.Permission{ @@ -321,7 +321,7 @@ func (hs *HTTPServer) declareFixedRoles() error { dashboardAnnotationsWriterRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:annotations.dashboard:writer", - DisplayName: "Dashboard annotation writer", + DisplayName: "Writer (dashboard)", Description: "Update annotations associated with dashboards.", Group: "Annotations", Permissions: []ac.Permission{ @@ -353,7 +353,7 @@ func (hs *HTTPServer) declareFixedRoles() error { annotationsReaderRole = ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:annotations:reader", - DisplayName: "Organization annotation reader", + DisplayName: "Reader (organization)", Description: "Read organization annotations and annotation tags", Group: "Annotations", Permissions: []ac.Permission{ @@ -370,7 +370,7 @@ func (hs *HTTPServer) declareFixedRoles() error { annotationsWriterRole = ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:annotations:writer", - DisplayName: "Organization annotation writer", + DisplayName: "Writer (organization)", Description: "Update organization annotations.", Group: "Annotations", Permissions: []ac.Permission{ @@ -463,7 +463,7 @@ func (hs *HTTPServer) declareFixedRoles() error { generalFolderReaderRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:folders.general:reader", - DisplayName: "General folder reader", + DisplayName: "Reader (root)", Description: "Access the general (root) folder.", Group: "Folders", Hidden: true, @@ -526,7 +526,7 @@ func (hs *HTTPServer) declareFixedRoles() error { libraryPanelsGeneralReaderRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:library.panels:general.reader", - DisplayName: "General reader", + DisplayName: "Reader (root)", Description: "Read all library panels under the root folder.", Group: "Library panels", Permissions: []ac.Permission{ @@ -554,7 +554,7 @@ func (hs *HTTPServer) declareFixedRoles() error { libraryPanelsGeneralWriterRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:library.panels:general.writer", - DisplayName: "Root level writer", + DisplayName: "Writer (root)", Group: "Library panels", Description: "Create, read, write or delete all library panels and their permissions under the root folder.", Permissions: ac.ConcatPermissions(libraryPanelsGeneralReaderRole.Role.Permissions, []ac.Permission{ @@ -569,7 +569,7 @@ func (hs *HTTPServer) declareFixedRoles() error { publicDashboardsWriterRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:dashboards.public:writer", - DisplayName: "Public Dashboard writer", + DisplayName: "Writer (public)", Description: "Create, write or disable a public dashboard.", Group: "Dashboards", Permissions: []ac.Permission{ @@ -658,7 +658,7 @@ func (hs *HTTPServer) declareFixedRoles() error { allAnnotationsReaderRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:annotations.all:reader", - DisplayName: "Reader", + DisplayName: "Reader (all)", Description: "Read all annotations and tags", Group: "Annotations", Permissions: []ac.Permission{ @@ -672,7 +672,7 @@ func (hs *HTTPServer) declareFixedRoles() error { allAnnotationsWriterRole := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: "fixed:annotations.all:writer", - DisplayName: "Writer", + DisplayName: "Writer (all)", Description: "Update all annotations.", Group: "Annotations", Permissions: []ac.Permission{ diff --git a/pkg/services/accesscontrol/ossaccesscontrol/dashboard.go b/pkg/services/accesscontrol/ossaccesscontrol/dashboard.go index a16e77c1717..a588ac14ce7 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/dashboard.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/dashboard.go @@ -163,8 +163,8 @@ func ProvideDashboardPermissions( "Edit": getDashboardEditActions(features), "Admin": getDashboardAdminActions(features), }, - ReaderRoleName: "Dashboard permission reader", - WriterRoleName: "Dashboard permission writer", + ReaderRoleName: "Permission reader", + WriterRoleName: "Permission writer", RoleGroup: "Dashboards", } diff --git a/pkg/services/accesscontrol/ossaccesscontrol/folder.go b/pkg/services/accesscontrol/ossaccesscontrol/folder.go index 67b73ebe764..f50c7643c4a 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/folder.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/folder.go @@ -126,8 +126,8 @@ func ProvideFolderPermissions( "Edit": append(getDashboardEditActions(features), FolderEditActions...), "Admin": append(getDashboardAdminActions(features), FolderAdminActions...), }, - ReaderRoleName: "Folder permission reader", - WriterRoleName: "Folder permission writer", + ReaderRoleName: "Permission reader", + WriterRoleName: "Permission writer", RoleGroup: "Folders", } srv, err := resourcepermissions.New(cfg, options, features, router, license, accesscontrol, service, sql, teamService, userService, actionSetService) diff --git a/pkg/services/accesscontrol/ossaccesscontrol/service_account.go b/pkg/services/accesscontrol/ossaccesscontrol/service_account.go index 068c8c91544..1097f9b1794 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/service_account.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/service_account.go @@ -67,8 +67,8 @@ func ProvideServiceAccountPermissions( "Edit": ServiceAccountEditActions, "Admin": ServiceAccountAdminActions, }, - ReaderRoleName: "Service account permission reader", - WriterRoleName: "Service account permission writer", + ReaderRoleName: "Permission reader", + WriterRoleName: "Permission writer", RoleGroup: "Service accounts", } diff --git a/pkg/services/accesscontrol/ossaccesscontrol/team.go b/pkg/services/accesscontrol/ossaccesscontrol/team.go index 2cbeb4e0174..3e1f01f36ef 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/team.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/team.go @@ -78,8 +78,8 @@ func ProvideTeamPermissions( "Member": TeamMemberActions, "Admin": TeamAdminActions, }, - ReaderRoleName: "Team permission reader", - WriterRoleName: "Team permission writer", + ReaderRoleName: "Permission reader", + WriterRoleName: "Permission writer", RoleGroup: "Teams", OnSetUser: func(session *db.Session, orgID int64, user accesscontrol.User, resourceID, permission string) error { teamId, err := strconv.ParseInt(resourceID, 10, 64) diff --git a/pkg/services/accesscontrol/roles.go b/pkg/services/accesscontrol/roles.go index a113cfd26f4..6ed0357d9de 100644 --- a/pkg/services/accesscontrol/roles.go +++ b/pkg/services/accesscontrol/roles.go @@ -43,7 +43,7 @@ const ( var ( ldapReaderRole = RoleDTO{ Name: "fixed:ldap:reader", - DisplayName: "LDAP reader", + DisplayName: "Reader", Description: "Read LDAP configuration and status.", Group: "LDAP", Permissions: []Permission{ @@ -58,7 +58,7 @@ var ( ldapWriterRole = RoleDTO{ Name: "fixed:ldap:writer", - DisplayName: "LDAP writer", + DisplayName: "Writer", Description: "Read and update LDAP configuration and read LDAP status.", Group: "LDAP", Permissions: ConcatPermissions(ldapReaderRole.Permissions, []Permission{ @@ -73,9 +73,9 @@ var ( orgUsersWriterRole = RoleDTO{ Name: "fixed:org.users:writer", - DisplayName: "Organization user writer", + DisplayName: "Writer (organizational)", Description: "Within a single organization, add a user, invite a user, read information about a user and their role, remove a user from that organization, or change the role of a user.", - Group: "User administration (organizational)", + Group: "User administration", Permissions: ConcatPermissions(orgUsersReaderRole.Permissions, []Permission{ { Action: ActionOrgUsersAdd, @@ -94,9 +94,9 @@ var ( orgUsersReaderRole = RoleDTO{ Name: "fixed:org.users:reader", - DisplayName: "Organization user reader", + DisplayName: "Reader (organizational)", Description: "Read users within a single organization.", - Group: "User administration (organizational)", + Group: "User administration", Permissions: []Permission{ { Action: ActionOrgUsersRead, @@ -111,7 +111,7 @@ var ( SettingsReaderRole = RoleDTO{ Name: "fixed:settings:reader", - DisplayName: "Setting reader", + DisplayName: "Reader", Description: "Read Grafana instance settings.", Group: "Settings", Permissions: []Permission{ @@ -124,7 +124,7 @@ var ( statsReaderRole = RoleDTO{ Name: "fixed:stats:reader", - DisplayName: "Statistics reader", + DisplayName: "Reader", Description: "Read Grafana instance statistics.", Group: "Statistics", Permissions: []Permission{ @@ -136,9 +136,9 @@ var ( usersReaderRole = RoleDTO{ Name: "fixed:users:reader", - DisplayName: "User reader", + DisplayName: "Reader (global)", Description: "Read all users and their information, such as team memberships, authentication tokens, and quotas.", - Group: "User administration (global)", + Group: "User administration", Permissions: []Permission{ { Action: ActionUsersRead, @@ -157,9 +157,9 @@ var ( usersWriterRole = RoleDTO{ Name: "fixed:users:writer", - DisplayName: "User writer", + DisplayName: "Writer (global)", Description: "Read and update all attributes and settings for all users in Grafana: update user information, read user information, create or enable or disable a user, make a user a Grafana administrator, sign out a user, update a user’s authentication token, or update quotas for all users.", - Group: "User administration (global)", + Group: "User administration", Permissions: ConcatPermissions(usersReaderRole.Permissions, []Permission{ { Action: ActionUsersPasswordUpdate, @@ -295,7 +295,7 @@ var ( usagestatsReaderRole = RoleDTO{ Name: "fixed:usagestats:reader", - DisplayName: "Usage stats report reader", + DisplayName: "Usage report reader", Description: "View usage statistics report", Group: "Statistics", Permissions: []Permission{ diff --git a/pkg/services/pluginsintegration/pluginaccesscontrol/accesscontrol.go b/pkg/services/pluginsintegration/pluginaccesscontrol/accesscontrol.go index 9e9438f44c1..b88a39299db 100644 --- a/pkg/services/pluginsintegration/pluginaccesscontrol/accesscontrol.go +++ b/pkg/services/pluginsintegration/pluginaccesscontrol/accesscontrol.go @@ -60,7 +60,7 @@ func DeclareRBACRoles(service ac.Service, cfg *setting.Cfg, features featuremgmt PluginsWriter := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: ac.FixedRolePrefix + "plugins:writer", - DisplayName: "Plugin Writer", + DisplayName: "Writer", Description: "Enable and disable plugins and edit plugins' settings", Group: "Plugins", Permissions: []ac.Permission{ @@ -72,7 +72,7 @@ func DeclareRBACRoles(service ac.Service, cfg *setting.Cfg, features featuremgmt PluginsMaintainer := ac.RoleRegistration{ Role: ac.RoleDTO{ Name: ac.FixedRolePrefix + "plugins:maintainer", - DisplayName: "Plugin Maintainer", + DisplayName: "Maintainer", Description: "Install, uninstall plugins. Needs to be assigned globally.", Group: "Plugins", Permissions: []ac.Permission{ diff --git a/pkg/services/serviceaccounts/manager/roles.go b/pkg/services/serviceaccounts/manager/roles.go index e78112c0544..9657bd9c268 100644 --- a/pkg/services/serviceaccounts/manager/roles.go +++ b/pkg/services/serviceaccounts/manager/roles.go @@ -10,7 +10,7 @@ func RegisterRoles(service accesscontrol.Service) error { saReader := accesscontrol.RoleRegistration{ Role: accesscontrol.RoleDTO{ Name: "fixed:serviceaccounts:reader", - DisplayName: "Service accounts reader", + DisplayName: "Reader", Description: "Read service accounts and service account tokens.", Group: "Service accounts", Permissions: []accesscontrol.Permission{ @@ -26,7 +26,7 @@ func RegisterRoles(service accesscontrol.Service) error { saCreator := accesscontrol.RoleRegistration{ Role: accesscontrol.RoleDTO{ Name: "fixed:serviceaccounts:creator", - DisplayName: "Service accounts creator", + DisplayName: "Creator", Description: "Create service accounts.", Group: "Service accounts", Permissions: []accesscontrol.Permission{ @@ -41,7 +41,7 @@ func RegisterRoles(service accesscontrol.Service) error { saWriter := accesscontrol.RoleRegistration{ Role: accesscontrol.RoleDTO{ Name: "fixed:serviceaccounts:writer", - DisplayName: "Service accounts writer", + DisplayName: "Writer", Description: "Create, delete and read service accounts, manage service account permissions.", Group: "Service accounts", Permissions: accesscontrol.ConcatPermissions(saReader.Role.Permissions, []accesscontrol.Permission{ diff --git a/pkg/services/supportbundles/supportbundlesimpl/models.go b/pkg/services/supportbundles/supportbundlesimpl/models.go index 797fa9dc095..b677966b794 100644 --- a/pkg/services/supportbundles/supportbundlesimpl/models.go +++ b/pkg/services/supportbundles/supportbundlesimpl/models.go @@ -14,7 +14,7 @@ const ( var ( bundleReaderRole = accesscontrol.RoleDTO{ Name: "fixed:support.bundles:reader", - DisplayName: "Support bundle reader", + DisplayName: "Reader", Description: "List and download support bundles", Group: "Support bundles", Permissions: []accesscontrol.Permission{ @@ -24,7 +24,7 @@ var ( bundleWriterRole = accesscontrol.RoleDTO{ Name: "fixed:support.bundles:writer", - DisplayName: "Support bundle writer", + DisplayName: "Writer", Description: "Create, delete, list and download support bundles", Group: "Support bundles", Permissions: []accesscontrol.Permission{ diff --git a/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx b/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx index bae0a0aeedf..79e44be57e6 100644 --- a/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx +++ b/public/app/core/components/RolePicker/RoleMenuGroupsSection.tsx @@ -11,6 +11,7 @@ import { isNotDelegatable } from './utils'; interface RoleMenuGroupsSectionProps { roles: Role[]; + isFiltered?: boolean; renderedName: string; showGroups?: boolean; optionGroups: Array<{ @@ -33,6 +34,7 @@ export const RoleMenuGroupsSection = forwardRef ( opt.uid === option.uid))} diff --git a/public/app/core/components/RolePicker/RoleMenuOption.tsx b/public/app/core/components/RolePicker/RoleMenuOption.tsx index 6992cc9a03b..13cf118f9a7 100644 --- a/public/app/core/components/RolePicker/RoleMenuOption.tsx +++ b/public/app/core/components/RolePicker/RoleMenuOption.tsx @@ -12,6 +12,7 @@ import { getStyles } from './styles'; interface RoleMenuOptionProps { data: Role; onChange: (value: Role) => void; + useFilteredDisplayName?: boolean; isSelected?: boolean; isFocused?: boolean; disabled?: boolean; @@ -20,7 +21,7 @@ interface RoleMenuOptionProps { } export const RoleMenuOption = forwardRef>( - ({ data, isFocused, isSelected, disabled, mapped, onChange, hideDescription }, ref) => { + ({ data, isFocused, isSelected, useFilteredDisplayName, disabled, mapped, onChange, hideDescription }, ref) => { const theme = useTheme2(); const styles = getSelectStyles(theme); const customStyles = useStyles2(getStyles); @@ -64,7 +65,7 @@ export const RoleMenuOption = forwardRef
- {data.displayName || data.name} + {(useFilteredDisplayName && data.filteredDisplayName) || data.displayName || data.name} {!hideDescription && data.description &&
{data.description}
}
{disabledMessage && ( diff --git a/public/app/core/components/RolePicker/RolePicker.tsx b/public/app/core/components/RolePicker/RolePicker.tsx index e94fb1009d9..6cbf2e0450d 100644 --- a/public/app/core/components/RolePicker/RolePicker.tsx +++ b/public/app/core/components/RolePicker/RolePicker.tsx @@ -173,6 +173,7 @@ export const RolePicker = ({ const options = roleOptions.map((r) => ({ ...r, delegatable: canUpdateRoles && r.delegatable })); if (query && query.trim() !== '') { + // TODO should this filter on `displayName` not (or in addition to) `name`? return options.filter((option) => option.name?.toLowerCase().includes(query.toLowerCase())); } return options; @@ -210,6 +211,7 @@ export const RolePicker = ({
e.stopPropagation()}> ( => { let rolesUrl = '/api/access-control/roles?delegatable=true'; @@ -12,7 +12,7 @@ export const fetchRoleOptions = async (orgId?: number): Promise => { if (!roles || !roles.length) { return []; } - return roles.map(addDisplayNameForFixedRole); + return roles.map(addDisplayNameForFixedRole).map(addFilteredDisplayName); }; export const fetchUserRoles = async (userId: number, orgId?: number): Promise => { @@ -25,7 +25,7 @@ export const fetchUserRoles = async (userId: number, orgId?: number): Promise { } return role; }; + +// Adds a display name for use when the list of roles is filtered +export const addFilteredDisplayName = (role: Role) => { + role.filteredDisplayName = role.group + ':' + role.displayName; + return role; +}; diff --git a/public/app/core/components/RolePickerDrawer/RolePickerBadges.test.tsx b/public/app/core/components/RolePickerDrawer/RolePickerBadges.test.tsx index 6fdcfebabb9..980d881acca 100644 --- a/public/app/core/components/RolePickerDrawer/RolePickerBadges.test.tsx +++ b/public/app/core/components/RolePickerDrawer/RolePickerBadges.test.tsx @@ -22,6 +22,7 @@ const props = { uid: 'uid', name: 'admin', displayName: 'Admin', + filteredDisplayName: 'group:Admin', description: 'description', group: 'group', global: true, diff --git a/public/app/types/accessControl.ts b/public/app/types/accessControl.ts index 87d71e5b4ed..1f86e39ea34 100644 --- a/public/app/types/accessControl.ts +++ b/public/app/types/accessControl.ts @@ -173,6 +173,7 @@ export interface Role { uid: string; name: string; displayName: string; + filteredDisplayName: string; // name to be shown in filtered role list description: string; group: string; global: boolean;