Chore: remove hasAccess and hasAcessInMetadata (#76237)

* remove hasAccess and hasAcessInMetadata in favour of hasPermission and hasPermissionInMetadata

* test fixes

* more test fixes
This commit is contained in:
Ieva
2023-10-10 12:04:07 +01:00
committed by GitHub
parent f56cc6fdc0
commit 5e14d93530
23 changed files with 22 additions and 62 deletions

View File

@@ -167,14 +167,6 @@ export class ContextSrv {
return this.hasPermission(AccessControlAction.DataSourcesExplore) && config.exploreEnabled;
}
hasAccess(action: string, fallBack: boolean): boolean {
return this.hasPermission(action);
}
hasAccessInMetadata(action: string, object: WithAccessControlMetadata, fallBack: boolean): boolean {
return this.hasPermissionInMetadata(action, object);
}
// evaluates access control permissions, granting access if the user has any of them
evaluatePermission(actions: string[]) {
if (actions.some((action) => this.hasPermission(action))) {

View File

@@ -29,7 +29,6 @@ jest.mock('./state/apis', () => ({
}));
jest.mock('../../core/services/context_srv', () => ({
contextSrv: {
hasAccess: () => true,
hasPermission: () => true,
},
}));

View File

@@ -272,7 +272,7 @@ const ContactPointHeader = (props: ContactPointHeaderProps) => {
// we make a distinction here becase for "canExport" we show the menu item, if not we hide it
const canExport = isGranaManagedAlertmanager;
const allowedToExport = contextSrv.hasAccess(permissions.provisioning.read, isOrgAdmin());
const allowedToExport = contextSrv.hasPermission(permissions.provisioning.read);
return (
<div className={styles.headerWrapper}>

View File

@@ -47,10 +47,9 @@ export function useIsRuleEditable(rulesSourceName: string, rule?: RulerRuleDTO):
loading,
};
}
const rbacDisabledFallback = folder.canSave;
const canEditGrafanaRules = contextSrv.hasAccessInMetadata(rulePermission.update, folder, rbacDisabledFallback);
const canRemoveGrafanaRules = contextSrv.hasAccessInMetadata(rulePermission.delete, folder, rbacDisabledFallback);
const canEditGrafanaRules = contextSrv.hasPermissionInMetadata(rulePermission.update, folder);
const canRemoveGrafanaRules = contextSrv.hasPermissionInMetadata(rulePermission.delete, folder);
return {
isEditable: canEditGrafanaRules,

View File

@@ -24,7 +24,6 @@ import {
useReshareAccessToRecipientMutation,
useUpdatePublicDashboardMutation,
} from 'app/features/dashboard/api/publicDashboardApi';
import { isOrgAdmin } from 'app/features/plugins/admin/permissions';
import { AccessControlAction, useSelector } from 'app/types';
import { trackDashboardSharingActionPerType } from '../../analytics';
@@ -121,7 +120,7 @@ export const EmailSharingConfiguration = () => {
const [updateShareType] = useUpdatePublicDashboardMutation();
const [addEmail, { isLoading: isAddEmailLoading }] = useAddRecipientMutation();
const hasWritePermissions = contextSrv.hasAccess(AccessControlAction.DashboardsPublicWrite, isOrgAdmin());
const hasWritePermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPublicWrite);
const {
register,

View File

@@ -111,7 +111,7 @@ jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => {
jest.mock('app/core/core', () => ({
contextSrv: {
hasAccess: () => true,
hasPermission: () => true,
getValidIntervals: (defaultIntervals: string[]) => defaultIntervals,
},
}));

View File

@@ -15,7 +15,6 @@ jest.mock('@grafana/runtime', () => ({
jest.mock('app/core/core', () => ({
contextSrv: {
hasAccess: () => true,
hasPermission: () => true,
getValidIntervals: (defaultIntervals: string[]) => defaultIntervals,
},

View File

@@ -17,7 +17,7 @@ jest.mock('@grafana/runtime', () => ({
jest.mock('app/core/core', () => ({
contextSrv: {
hasAccess: () => true,
hasPermission: () => true,
getValidIntervals: (defaultIntervals: string[]) => defaultIntervals,
},
}));

View File

@@ -50,7 +50,6 @@ jest.mock('@grafana/runtime', () => ({
jest.mock('app/core/core', () => ({
contextSrv: {
hasPermission: () => true,
hasAccess: () => true,
isSignedIn: true,
getValidIntervals: (defaultIntervals: string[]) => defaultIntervals,
},

View File

@@ -16,7 +16,6 @@ jest.mock('app/core/core', () => {
return {
contextSrv: {
hasPermission: () => true,
hasAccess: () => true,
getValidIntervals: (defaultIntervals: string[]) => defaultIntervals,
},
};

View File

@@ -7,7 +7,6 @@ import { AccessControlAction } from 'app/types';
import { updatePluginSettings } from '../../api';
import { usePluginConfig } from '../../hooks/usePluginConfig';
import { isOrgAdmin } from '../../permissions';
import { CatalogPlugin } from '../../types';
type Props = {
@@ -22,7 +21,7 @@ export function GetStartedWithApp({ plugin }: Props): React.ReactElement | null
}
// Enforce RBAC
if (!contextSrv.hasAccessInMetadata(AccessControlAction.PluginsWrite, plugin, isOrgAdmin())) {
if (!contextSrv.hasPermissionInMetadata(AccessControlAction.PluginsWrite, plugin)) {
return null;
}

View File

@@ -7,7 +7,6 @@ import { contextSrv } from 'app/core/core';
import { AccessControlAction } from 'app/types';
import { usePluginConfig } from '../hooks/usePluginConfig';
import { isOrgAdmin } from '../permissions';
import { CatalogPlugin, PluginTabIds, PluginTabLabels } from '../types';
type ReturnType = {
@@ -25,8 +24,7 @@ export const usePluginDetailsTabs = (plugin?: CatalogPlugin, pageId?: PluginTabI
const currentPageId = pageId || defaultTab;
const navModelChildren = useMemo(() => {
const canConfigurePlugins =
plugin && contextSrv.hasAccessInMetadata(AccessControlAction.PluginsWrite, plugin, isOrgAdmin());
const canConfigurePlugins = plugin && contextSrv.hasPermissionInMetadata(AccessControlAction.PluginsWrite, plugin);
const navModelChildren: NavModelItem[] = [];
if (isPublished) {
navModelChildren.push({
@@ -122,7 +120,7 @@ function useDefaultPage(plugin: CatalogPlugin | undefined, pluginConfig: Grafana
return PluginTabIds.OVERVIEW;
}
const hasAccess = contextSrv.hasAccessInMetadata(AccessControlAction.PluginsWrite, plugin, isOrgAdmin());
const hasAccess = contextSrv.hasPermissionInMetadata(AccessControlAction.PluginsWrite, plugin);
if (!hasAccess || pluginConfig.meta.type !== PluginType.app) {
return PluginTabIds.OVERVIEW;

View File

@@ -52,9 +52,8 @@ jest.mock('../helpers.ts', () => ({
jest.mock('app/core/core', () => ({
contextSrv: {
hasAccess: (action: string, fallBack: boolean) => true,
hasPermission: (action: string) => true,
hasAccessInMetadata: (action: string, object: WithAccessControlMetadata, fallBack: boolean) => true,
hasPermissionInMetadata: (action: string, object: WithAccessControlMetadata) => true,
},
}));

View File

@@ -14,7 +14,6 @@ jest.mock('app/core/services/context_srv', () => {
contextSrv: {
...originMock.context_srv,
user: {},
hasAccess: jest.fn(() => false),
hasPermission: jest.fn(() => false),
},
};
@@ -32,19 +31,16 @@ jest.spyOn(console, 'error').mockImplementation();
describe('ManageDashboards', () => {
beforeEach(() => {
(contextSrv.hasAccess as jest.Mock).mockClear();
(contextSrv.hasPermission as jest.Mock).mockClear();
});
it("should hide and show dashboard actions based on user's permissions", async () => {
(contextSrv.hasAccess as jest.Mock).mockReturnValue(false);
(contextSrv.hasPermission as jest.Mock).mockReturnValue(false);
const { rerender } = await setup();
expect(screen.queryByRole('button', { name: /new/i })).not.toBeInTheDocument();
(contextSrv.hasAccess as jest.Mock).mockReturnValue(true);
(contextSrv.hasPermission as jest.Mock).mockReturnValue(true);
await waitFor(() => rerender(<ManageDashboardsNew folder={{ canEdit: true } as FolderDTO} />));

View File

@@ -31,9 +31,8 @@ export const ManageDashboardsNew = React.memo(({ folder }: Props) => {
const { isEditor } = contextSrv;
const hasEditPermissionInFolders = folder ? canSave : contextSrv.hasEditPermissionInFolders;
const canCreateFolders = contextSrv.hasPermission(AccessControlAction.FoldersCreate);
const canCreateDashboardsFallback = hasEditPermissionInFolders || !!canSave;
const canCreateDashboards = folderUid
? contextSrv.hasAccessInMetadata(AccessControlAction.DashboardsCreate, folder, canCreateDashboardsFallback)
? contextSrv.hasPermissionInMetadata(AccessControlAction.DashboardsCreate, folder)
: contextSrv.hasPermission(AccessControlAction.DashboardsCreate);
const viewActions = (folder === undefined && canCreateFolders) || canCreateDashboards;

View File

@@ -13,8 +13,7 @@ jest.mock('app/core/core', () => ({
contextSrv: {
licensedAccessControlEnabled: () => false,
hasPermission: () => true,
hasPermissionInMetadata: () => true,
hasAccessInMetadata: () => false,
hasPermissionInMetadata: () => false,
},
}));

View File

@@ -73,10 +73,9 @@ export const ServiceAccountPageUnconnected = ({
!contextSrv.hasPermission(AccessControlAction.ServiceAccountsWrite) || serviceAccount.isDisabled;
const ableToWrite = contextSrv.hasPermission(AccessControlAction.ServiceAccountsWrite);
const canReadPermissions = contextSrv.hasAccessInMetadata(
const canReadPermissions = contextSrv.hasPermissionInMetadata(
AccessControlAction.ServiceAccountsPermissionsRead,
serviceAccount!,
false
serviceAccount!
);
const pageNav: NavModelItem = {

View File

@@ -96,10 +96,9 @@ export const TeamList = ({
id: 'role',
header: 'Role',
cell: ({ cell: { value }, row: { original } }: Cell<'memberCount'>) => {
const canSeeTeamRoles = contextSrv.hasAccessInMetadata(
const canSeeTeamRoles = contextSrv.hasPermissionInMetadata(
AccessControlAction.ActionTeamsRolesList,
original,
false
original
);
return canSeeTeamRoles && <TeamRolePicker teamId={original.id} roleOptions={roleOptions} />;
},

View File

@@ -10,7 +10,6 @@ import { searchQueryChanged } from './state/reducers';
jest.mock('app/core/core', () => ({
contextSrv: {
hasPermission: () => true,
hasAccess: () => true,
},
}));
@@ -20,7 +19,6 @@ const setup = (propOverrides?: object) => {
changeSearchQuery: mockToolkitActionCreator(searchQueryChanged),
onShowInvites: jest.fn(),
pendingInvitesCount: 0,
canInvite: false,
externalUserMngLinkUrl: '',
externalUserMngLinkName: '',
showInvites: false,
@@ -49,9 +47,7 @@ describe('Render', () => {
});
it('should show invite button', () => {
setup({
canInvite: true,
});
setup();
expect(screen.getByRole('link', { name: 'Invite' })).toHaveAttribute('href', 'org/users/invite');
});
@@ -70,9 +66,7 @@ describe('Render', () => {
config.externalUserMngInfo = 'truthy';
config.disableLoginForm = true;
setup({
canInvite: true,
});
setup();
expect(screen.queryByRole('link', { name: 'Invite' })).not.toBeInTheDocument();
// Reset the disableLoginForm mock to its original value
@@ -83,9 +77,7 @@ describe('Render', () => {
config.externalUserMngInfo = '';
config.disableLoginForm = true;
setup({
canInvite: true,
});
setup();
expect(screen.getByRole('link', { name: 'Invite' })).toHaveAttribute('href', 'org/users/invite');
// Reset the disableLoginForm mock to its original value
@@ -96,9 +88,7 @@ describe('Render', () => {
const originalExternalUserMngInfo = config.externalUserMngInfo;
config.externalUserMngInfo = 'truthy';
setup({
canInvite: true,
});
setup();
expect(screen.getByRole('link', { name: 'Invite' })).toHaveAttribute('href', 'org/users/invite');
// Reset the disableLoginForm mock to its original value

View File

@@ -22,7 +22,6 @@ function mapStateToProps(state: StoreState) {
pendingInvitesCount: selectTotal(state.invites),
externalUserMngLinkName: state.users.externalUserMngLinkName,
externalUserMngLinkUrl: state.users.externalUserMngLinkUrl,
canInvite: state.users.canInvite,
};
}
@@ -35,7 +34,6 @@ const connector = connect(mapStateToProps, mapDispatchToProps);
export type Props = ConnectedProps<typeof connector> & OwnProps;
export const UsersActionBarUnconnected = ({
canInvite,
externalUserMngLinkName,
externalUserMngLinkUrl,
searchQuery,
@@ -48,7 +46,7 @@ export const UsersActionBarUnconnected = ({
{ label: 'Users', value: 'users' },
{ label: `Pending Invites (${pendingInvitesCount})`, value: 'invites' },
];
const canAddToOrg: boolean = contextSrv.hasAccess(AccessControlAction.OrgUsersAdd, canInvite);
const canAddToOrg: boolean = contextSrv.hasPermission(AccessControlAction.OrgUsersAdd);
// Show invite button in the following cases:
// 1) the instance is not a hosted Grafana instance (!config.externalUserMngInfo)
// 2) new basic auth users can be created for this instance (!config.disableLoginForm).

View File

@@ -16,7 +16,7 @@ jest.mock('../../core/app_events', () => ({
jest.mock('app/core/core', () => ({
contextSrv: {
user: { orgId: 1 },
hasAccess: () => false,
hasPermission: () => false,
licensedAccessControlEnabled: () => false,
},
}));

View File

@@ -9,7 +9,6 @@ export const initialState: UsersState = {
page: 0,
perPage: 30,
totalPages: 1,
canInvite: !config.externalUserMngLinkName,
externalUserMngInfo: config.externalUserMngInfo,
externalUserMngLinkName: config.externalUserMngLinkName,
externalUserMngLinkUrl: config.externalUserMngLinkUrl,

View File

@@ -72,7 +72,6 @@ export interface Invitee {
export interface UsersState {
users: OrgUser[];
searchQuery: string;
canInvite: boolean;
externalUserMngLinkUrl: string;
externalUserMngLinkName: string;
externalUserMngInfo: string;