From da2c99a2e12f1660610330af25f2ab598aad7ca0 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Mon, 22 Nov 2021 17:44:03 +0300 Subject: [PATCH] Access control: use delegatable flag to check if role can be granted (#42070) * Access control: use delegatable flag to check if role can be granted or not * Fix naming --- pkg/services/accesscontrol/models.go | 1 + .../app/core/components/RolePicker/RolePickerMenu.tsx | 11 ++++++++++- .../app/core/components/RolePicker/UserRolePicker.tsx | 4 ++-- public/app/types/accessControl.ts | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/services/accesscontrol/models.go b/pkg/services/accesscontrol/models.go index 2e4a0cb1b86..b505adbc5cc 100644 --- a/pkg/services/accesscontrol/models.go +++ b/pkg/services/accesscontrol/models.go @@ -64,6 +64,7 @@ type RoleDTO struct { Description string `json:"description"` Group string `xorm:"group_name" json:"group"` Permissions []Permission `json:"permissions,omitempty"` + Delegatable *bool `json:"delegatable,omitempty"` ID int64 `json:"-" xorm:"pk autoincr 'id'"` OrgID int64 `json:"-" xorm:"org_id"` diff --git a/public/app/core/components/RolePicker/RolePickerMenu.tsx b/public/app/core/components/RolePicker/RolePickerMenu.tsx index 8a8aec3f29b..6fd057806d1 100644 --- a/public/app/core/components/RolePicker/RolePickerMenu.tsx +++ b/public/app/core/components/RolePicker/RolePickerMenu.tsx @@ -194,6 +194,7 @@ export const RolePickerMenu = ({ key={i} isSelected={groupSelected(option.value) || groupPartiallySelected(option.value)} partiallySelected={groupPartiallySelected(option.value)} + disabled={option.options?.every(isNotDelegatable)} onChange={onGroupChange} onOpenSubMenu={onOpenSubMenu} onCloseSubMenu={onCloseSubMenu} @@ -221,6 +222,7 @@ export const RolePickerMenu = ({ data={option} key={i} isSelected={!!(option.uid && !!selectedOptions.find((opt) => opt.uid === option.uid))} + disabled={isNotDelegatable(option)} onChange={onChange} hideDescription /> @@ -237,6 +239,7 @@ export const RolePickerMenu = ({ data={option} key={i} isSelected={!!(option.uid && !!selectedOptions.find((opt) => opt.uid === option.uid))} + disabled={isNotDelegatable(option)} onChange={onChange} hideDescription /> @@ -329,7 +332,9 @@ export const RolePickerSubMenu = ({ disabledOptions?.find((opt) => opt.uid === option.uid)) ) } - disabled={!!(option.uid && disabledOptions?.find((opt) => opt.uid === option.uid))} + disabled={ + !!(option.uid && disabledOptions?.find((opt) => opt.uid === option.uid)) || isNotDelegatable(option) + } onChange={onSelect} hideDescription /> @@ -507,6 +512,10 @@ const capitalize = (s: string): string => { const sortRolesByName = (a: Role, b: Role) => a.name.localeCompare(b.name); +const isNotDelegatable = (role: Role) => { + return role.delegatable !== undefined && !role.delegatable; +}; + export const getStyles = (theme: GrafanaTheme2) => { return { menuWrapper: css` diff --git a/public/app/core/components/RolePicker/UserRolePicker.tsx b/public/app/core/components/RolePicker/UserRolePicker.tsx index 175e6c4dd16..22da13a1413 100644 --- a/public/app/core/components/RolePicker/UserRolePicker.tsx +++ b/public/app/core/components/RolePicker/UserRolePicker.tsx @@ -36,9 +36,9 @@ export const UserRolePicker: FC = ({ }; export const fetchRoleOptions = async (orgId?: number, query?: string): Promise => { - let rolesUrl = '/api/access-control/roles'; + let rolesUrl = '/api/access-control/roles?delegatable=true'; if (orgId) { - rolesUrl += `?targetOrgId=${orgId}`; + rolesUrl += `&targetOrgId=${orgId}`; } const roles = await getBackendSrv().get(rolesUrl); if (!roles || !roles.length) { diff --git a/public/app/types/accessControl.ts b/public/app/types/accessControl.ts index 09c6bc15b18..04da2f7956f 100644 --- a/public/app/types/accessControl.ts +++ b/public/app/types/accessControl.ts @@ -57,6 +57,7 @@ export interface Role { description: string; group: string; global: boolean; + delegatable?: boolean; version: number; created: string; updated: string;