mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
Chore: remove legacy AC fallback from frontend access control checks (#74385)
* don't use legacy AC fallback for frontend access control checks * extend tests * more test fixes * more test fixes * more test fixes * final test fix * team test fix * finally fix tests
This commit is contained in:
parent
12de22b771
commit
d46208b28a
@ -84,7 +84,7 @@ describe('OldFolderPicker', () => {
|
||||
{ title: 'Dash 2', uid: 'wfTJJL5Wz' } as DashboardSearchHit,
|
||||
]);
|
||||
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
const onChangeFn = jest.fn();
|
||||
render(<OldFolderPicker onChange={onChangeFn} />);
|
||||
@ -105,7 +105,7 @@ describe('OldFolderPicker', () => {
|
||||
{ title: 'Dash 2', uid: 'wfTJJL5Wz' } as DashboardSearchHit,
|
||||
]);
|
||||
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
const onChangeFn = jest.fn();
|
||||
render(<OldFolderPicker onChange={onChangeFn} showRoot={false} />);
|
||||
@ -126,7 +126,7 @@ describe('OldFolderPicker', () => {
|
||||
{ title: 'Dash 2', uid: 'wfTJJL5Wz' } as DashboardSearchHit,
|
||||
]);
|
||||
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
const onChangeFn = jest.fn();
|
||||
render(<OldFolderPicker onChange={onChangeFn} />);
|
||||
@ -148,7 +148,7 @@ describe('OldFolderPicker', () => {
|
||||
].filter((dash) => dash.title.indexOf(query) > -1)
|
||||
);
|
||||
});
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
const onChangeFn = jest.fn();
|
||||
render(<OldFolderPicker onChange={onChangeFn} />);
|
||||
|
||||
|
@ -104,8 +104,8 @@ export function OldFolderPicker(props: Props) {
|
||||
});
|
||||
|
||||
const hasAccess =
|
||||
contextSrv.hasAccess(AccessControlAction.DashboardsWrite, contextSrv.isEditor) ||
|
||||
contextSrv.hasAccess(AccessControlAction.DashboardsCreate, contextSrv.isEditor);
|
||||
contextSrv.hasPermission(AccessControlAction.DashboardsWrite) ||
|
||||
contextSrv.hasPermission(AccessControlAction.DashboardsCreate);
|
||||
|
||||
if (hasAccess && rootName?.toLowerCase().startsWith(query.toLowerCase()) && showRoot) {
|
||||
options.unshift({ label: rootName, value: '' });
|
||||
|
@ -30,6 +30,7 @@ jest.mock('./state/apis', () => ({
|
||||
jest.mock('../../core/services/context_srv', () => ({
|
||||
contextSrv: {
|
||||
hasAccess: () => true,
|
||||
hasPermission: () => true,
|
||||
},
|
||||
}));
|
||||
|
||||
|
@ -15,11 +15,11 @@ export const ServerStats = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const hasAccessToDataSources = contextSrv.hasAccess(AccessControlAction.DataSourcesRead, contextSrv.isGrafanaAdmin);
|
||||
const hasAccessToAdminUsers = contextSrv.hasAccess(AccessControlAction.UsersRead, contextSrv.isGrafanaAdmin);
|
||||
const hasAccessToDataSources = contextSrv.hasPermission(AccessControlAction.DataSourcesRead);
|
||||
const hasAccessToAdminUsers = contextSrv.hasPermission(AccessControlAction.UsersRead);
|
||||
|
||||
useEffect(() => {
|
||||
if (contextSrv.hasAccess(AccessControlAction.ActionServerStatsRead, contextSrv.isGrafanaAdmin)) {
|
||||
if (contextSrv.hasPermission(AccessControlAction.ActionServerStatsRead)) {
|
||||
setIsLoading(true);
|
||||
getServerStats().then((stats) => {
|
||||
setStats(stats);
|
||||
@ -28,7 +28,7 @@ export const ServerStats = () => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!contextSrv.hasAccess(AccessControlAction.ActionServerStatsRead, contextSrv.isGrafanaAdmin)) {
|
||||
if (!contextSrv.hasPermission(AccessControlAction.ActionServerStatsRead)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,6 @@ afterEach(() => {
|
||||
|
||||
describe('Tabs rendering', () => {
|
||||
it('should render All and Org Users tabs when user has permissions to read to org users and is admin', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
renderPage();
|
||||
@ -66,7 +65,6 @@ describe('Tabs rendering', () => {
|
||||
expect(screen.queryByTestId(tabsSelector.publicDashboardsUsers)).not.toBeInTheDocument();
|
||||
});
|
||||
it('should render All, Org and Public dashboard tabs when user has permissions to read org users, is admin and has email sharing enabled', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
enableEmailSharing();
|
||||
@ -77,61 +75,34 @@ describe('Tabs rendering', () => {
|
||||
expect(screen.getByTestId(tabsSelector.publicDashboardsUsers)).toBeInTheDocument();
|
||||
});
|
||||
describe('No permissions to read org users or not admin', () => {
|
||||
[
|
||||
{
|
||||
hasOrgReadPermissions: false,
|
||||
isAdmin: true,
|
||||
},
|
||||
{
|
||||
hasOrgReadPermissions: true,
|
||||
isAdmin: false,
|
||||
},
|
||||
].forEach((scenario) => {
|
||||
it('should render no tabs when user has no permissions to read org users or is not admin', async () => {
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(scenario.hasOrgReadPermissions);
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(scenario.isAdmin);
|
||||
it('should render no tabs when user has no permissions to read org users', async () => {
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
renderPage();
|
||||
renderPage();
|
||||
|
||||
expect(screen.queryByTestId(tabsSelector.allUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.orgUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.publicDashboardsUsers)).not.toBeInTheDocument();
|
||||
});
|
||||
expect(screen.queryByTestId(tabsSelector.allUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.orgUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.publicDashboardsUsers)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
describe('No permissions to read org users or not admin but email sharing enabled', () => {
|
||||
[
|
||||
{
|
||||
title: 'user has no permissions to read org users',
|
||||
hasOrgReadPermissions: false,
|
||||
isAdmin: true,
|
||||
},
|
||||
{
|
||||
title: 'user is not admin',
|
||||
hasOrgReadPermissions: true,
|
||||
isAdmin: false,
|
||||
},
|
||||
].forEach((scenario) => {
|
||||
it(`should render User and Public dashboard tabs when ${scenario.title} but has email sharing enabled`, async () => {
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(scenario.hasOrgReadPermissions);
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(scenario.isAdmin);
|
||||
describe('No permissions to read org users but email sharing enabled', () => {
|
||||
it(`should render User and Public dashboard tabs when no permissions to read org users but has email sharing enabled`, async () => {
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
enableEmailSharing();
|
||||
renderPage();
|
||||
enableEmailSharing();
|
||||
renderPage();
|
||||
|
||||
expect(screen.queryByTestId(tabsSelector.allUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.orgUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.allUsers)).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId(tabsSelector.orgUsers)).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.getByTestId(tabsSelector.users)).toBeInTheDocument();
|
||||
expect(screen.getByTestId(tabsSelector.publicDashboardsUsers)).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByTestId(tabsSelector.users)).toBeInTheDocument();
|
||||
expect(screen.getByTestId(tabsSelector.publicDashboardsUsers)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tables rendering', () => {
|
||||
it('should render UserListAdminPage when user is admin', () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
renderPage();
|
||||
@ -142,7 +113,6 @@ describe('Tables rendering', () => {
|
||||
expect(screen.getByTestId(selectors.UserListAdminPage.container)).toBeInTheDocument();
|
||||
});
|
||||
it('should render UsersListPage when user is admin and has org read permissions', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
renderPage();
|
||||
@ -156,8 +126,7 @@ describe('Tables rendering', () => {
|
||||
expect(screen.getByTestId(selectors.UsersListPage.container)).toBeInTheDocument();
|
||||
});
|
||||
it('should render UsersListPage when user has org read permissions and is not admin', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
renderPage();
|
||||
|
||||
@ -169,8 +138,7 @@ describe('Tables rendering', () => {
|
||||
expect(screen.getByTestId(selectors.UsersListPage.container)).toBeInTheDocument();
|
||||
});
|
||||
it('should render UserListPublicDashboardPage when user has email sharing enabled and is not admin', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
enableEmailSharing();
|
||||
renderPage();
|
||||
@ -186,7 +154,6 @@ describe('Tables rendering', () => {
|
||||
expect(screen.getByTestId(selectors.UsersListPublicDashboardsPage.container)).toBeInTheDocument();
|
||||
});
|
||||
it('should render UsersListPage when user is not admin and does not have nor org read perms neither email sharing enabled', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
renderPage();
|
||||
|
@ -40,7 +40,7 @@ const TAB_PAGE_MAP: Record<TabView, React.ReactElement> = {
|
||||
export default function UserListPage() {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const hasAccessToAdminUsers = contextSrv.hasAccess(AccessControlAction.UsersRead, contextSrv.isGrafanaAdmin);
|
||||
const hasAccessToAdminUsers = contextSrv.hasPermission(AccessControlAction.UsersRead);
|
||||
const hasAccessToOrgUsers = contextSrv.hasPermission(AccessControlAction.OrgUsersRead);
|
||||
const hasEmailSharingEnabled =
|
||||
Boolean(config.featureToggles.publicDashboards) &&
|
||||
|
@ -196,7 +196,6 @@ describe('NotificationPolicies', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
mocks.getAllDataSourcesMock.mockReturnValue(Object.values(dataSources));
|
||||
mocks.contextSrv.hasAccess.mockImplementation(() => true);
|
||||
mocks.contextSrv.hasPermission.mockImplementation(() => true);
|
||||
mocks.contextSrv.evaluatePermission.mockImplementation(() => []);
|
||||
mocks.api.discoverAlertmanagerFeatures.mockResolvedValue({ lazyConfigInit: false });
|
||||
@ -384,7 +383,7 @@ describe('NotificationPolicies', () => {
|
||||
});
|
||||
|
||||
it('hides create and edit button if user does not have permission', async () => {
|
||||
mocks.contextSrv.hasAccess.mockImplementation((action) =>
|
||||
mocks.contextSrv.hasPermission.mockImplementation((action) =>
|
||||
[AccessControlAction.AlertingNotificationsRead, AccessControlAction.AlertingNotificationsRead].includes(
|
||||
action as AccessControlAction
|
||||
)
|
||||
|
@ -12,7 +12,6 @@ import ConditionalWrap from 'app/features/alerting/components/ConditionalWrap';
|
||||
import { RouteWithID, Receiver, ObjectMatcher, AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types';
|
||||
import { ReceiversState } from 'app/types';
|
||||
|
||||
import { isOrgAdmin } from '../../../../plugins/admin/permissions';
|
||||
import { INTEGRATION_ICONS } from '../../types/contact-points';
|
||||
import { getNotificationsPermissions } from '../../utils/access-control';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
@ -75,7 +74,7 @@ const Policy: FC<PolicyComponentProps> = ({
|
||||
const canEditRoutes = contextSrv.hasPermission(permissions.update);
|
||||
const canDeleteRoutes = contextSrv.hasPermission(permissions.delete);
|
||||
const canReadProvisioning =
|
||||
contextSrv.hasAccess(permissions.provisioning.read, isOrgAdmin()) ||
|
||||
contextSrv.hasPermission(permissions.provisioning.read) ||
|
||||
contextSrv.hasPermission(permissions.provisioning.readSecrets);
|
||||
|
||||
const contactPoint = currentRoute.receiver;
|
||||
|
@ -89,7 +89,7 @@ function ViewAction({ permissions, alertManagerName, receiverName }: ActionProps
|
||||
}
|
||||
|
||||
function ExportAction({ permissions, receiverName }: ActionProps) {
|
||||
const canReadSecrets = contextSrv.hasAccess(permissions.provisioning.readSecrets, isOrgAdmin());
|
||||
const canReadSecrets = contextSrv.hasPermission(permissions.provisioning.readSecrets);
|
||||
return (
|
||||
<Authorize actions={[permissions.provisioning.read, permissions.provisioning.readSecrets]}>
|
||||
<ActionIcon
|
||||
@ -308,8 +308,8 @@ export const ReceiversTable = ({ config, alertManagerName }: Props) => {
|
||||
const isGrafanaAM = alertManagerName === GRAFANA_RULES_SOURCE_NAME;
|
||||
const showExport =
|
||||
isGrafanaAM &&
|
||||
(contextSrv.hasAccess(permissions.provisioning.read, isOrgAdmin()) ||
|
||||
contextSrv.hasAccess(permissions.provisioning.readSecrets, isOrgAdmin()));
|
||||
(contextSrv.hasPermission(permissions.provisioning.read) ||
|
||||
contextSrv.hasPermission(permissions.provisioning.readSecrets));
|
||||
|
||||
const onClickDeleteReceiver = (receiverName: string): void => {
|
||||
if (isReceiverUsed(receiverName, config)) {
|
||||
|
@ -14,11 +14,8 @@ import { RuleFormType, RuleFormValues } from '../../../types/rule-form';
|
||||
import { NeedHelpInfo } from '../NeedHelpInfo';
|
||||
|
||||
function getAvailableRuleTypes() {
|
||||
const canCreateGrafanaRules = contextSrv.hasAccess(
|
||||
AccessControlAction.AlertingRuleCreate,
|
||||
contextSrv.hasEditPermissionInFolders
|
||||
);
|
||||
const canCreateCloudRules = contextSrv.hasAccess(AccessControlAction.AlertingRuleExternalWrite, contextSrv.isEditor);
|
||||
const canCreateGrafanaRules = contextSrv.hasPermission(AccessControlAction.AlertingRuleCreate);
|
||||
const canCreateCloudRules = contextSrv.hasPermission(AccessControlAction.AlertingRuleExternalWrite);
|
||||
const defaultRuleType = canCreateGrafanaRules ? RuleFormType.grafana : RuleFormType.cloudAlerting;
|
||||
|
||||
const enabledRuleTypes: RuleFormType[] = [];
|
||||
|
@ -291,7 +291,7 @@ function useCanSilence(rule: CombinedRule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasPermissions = contextSrv.hasAccess(AccessControlAction.AlertingInstanceCreate, contextSrv.isEditor);
|
||||
const hasPermissions = contextSrv.hasPermission(AccessControlAction.AlertingInstanceCreate);
|
||||
|
||||
const interactsOnlyWithExternalAMs = amConfigStatus?.alertmanagersChoice === AlertmanagerChoice.External;
|
||||
const interactsWithAll = amConfigStatus?.alertmanagersChoice === AlertmanagerChoice.All;
|
||||
|
@ -14,7 +14,7 @@ type Props = {
|
||||
export const NoSilencesSplash = ({ alertManagerSourceName }: Props) => {
|
||||
const permissions = getInstancesPermissions(alertManagerSourceName);
|
||||
|
||||
if (contextSrv.hasAccess(permissions.create, contextSrv.isEditor)) {
|
||||
if (contextSrv.hasPermission(permissions.create)) {
|
||||
return (
|
||||
<EmptyListCTA
|
||||
title="You haven't created any silences yet"
|
||||
|
@ -62,8 +62,8 @@ export function useIsRuleEditable(rulesSourceName: string, rule?: RulerRuleDTO):
|
||||
// prom rules are only editable by users with Editor role and only if rules source supports editing
|
||||
const isRulerAvailable =
|
||||
Boolean(dataSources[rulesSourceName]?.result?.rulerConfig) || Boolean(dsFeatures?.rulerConfig);
|
||||
const canEditCloudRules = contextSrv.hasAccess(rulePermission.update, contextSrv.isEditor);
|
||||
const canRemoveCloudRules = contextSrv.hasAccess(rulePermission.delete, contextSrv.isEditor);
|
||||
const canEditCloudRules = contextSrv.hasPermission(rulePermission.update);
|
||||
const canRemoveCloudRules = contextSrv.hasPermission(rulePermission.delete);
|
||||
|
||||
return {
|
||||
isEditable: canEditCloudRules && isRulerAvailable,
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import { isOrgAdmin } from 'app/features/plugins/admin/permissions';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
import { GRAFANA_RULES_SOURCE_NAME, isGrafanaRulesSource } from './datasource';
|
||||
import { isGrafanaRulesSource } from './datasource';
|
||||
|
||||
type RulesSourceType = 'grafana' | 'external';
|
||||
|
||||
@ -116,18 +115,16 @@ export function evaluateAccess(actions: AccessControlAction[], fallBackUserRoles
|
||||
export function getRulesAccess() {
|
||||
return {
|
||||
canCreateGrafanaRules:
|
||||
contextSrv.hasAccess(AccessControlAction.FoldersRead, contextSrv.hasEditPermissionInFolders) &&
|
||||
contextSrv.hasAccess(rulesPermissions.create.grafana, contextSrv.hasEditPermissionInFolders),
|
||||
contextSrv.hasPermission(AccessControlAction.FoldersRead) &&
|
||||
contextSrv.hasPermission(rulesPermissions.create.grafana),
|
||||
canCreateCloudRules:
|
||||
contextSrv.hasAccess(AccessControlAction.DataSourcesRead, contextSrv.isEditor) &&
|
||||
contextSrv.hasAccess(rulesPermissions.create.external, contextSrv.isEditor),
|
||||
contextSrv.hasPermission(AccessControlAction.DataSourcesRead) &&
|
||||
contextSrv.hasPermission(rulesPermissions.create.external),
|
||||
canEditRules: (rulesSourceName: string) => {
|
||||
const permissionFallback =
|
||||
rulesSourceName === GRAFANA_RULES_SOURCE_NAME ? contextSrv.hasEditPermissionInFolders : contextSrv.isEditor;
|
||||
return contextSrv.hasAccess(getRulesPermissions(rulesSourceName).update, permissionFallback);
|
||||
return contextSrv.hasPermission(getRulesPermissions(rulesSourceName).update);
|
||||
},
|
||||
canReadProvisioning:
|
||||
contextSrv.hasAccess(provisioningPermissions.read, isOrgAdmin()) ||
|
||||
contextSrv.hasAccess(provisioningPermissions.readSecrets, isOrgAdmin()),
|
||||
contextSrv.hasPermission(provisioningPermissions.read) ||
|
||||
contextSrv.hasPermission(provisioningPermissions.readSecrets),
|
||||
};
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import { setSearchQuery } from './state/reducers';
|
||||
import { getApiKeys, getApiKeysCount, getIncludeExpired, getIncludeExpiredDisabled } from './state/selectors';
|
||||
|
||||
function mapStateToProps(state: StoreState) {
|
||||
const canCreate = contextSrv.hasAccess(AccessControlAction.ActionAPIKeysCreate, true);
|
||||
const canCreate = contextSrv.hasPermission(AccessControlAction.ActionAPIKeysCreate);
|
||||
return {
|
||||
apiKeys: getApiKeys(state.apiKeys),
|
||||
searchQuery: state.apiKeys.searchQuery,
|
||||
|
@ -66,8 +66,7 @@ export function HelpWizard({ panel, plugin, onClose }: Props) {
|
||||
];
|
||||
|
||||
const hasSupportBundleAccess =
|
||||
config.supportBundlesEnabled &&
|
||||
contextSrv.hasAccess(AccessControlAction.ActionSupportBundlesCreate, contextSrv.isGrafanaAdmin);
|
||||
config.supportBundlesEnabled && contextSrv.hasPermission(AccessControlAction.ActionSupportBundlesCreate);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
|
@ -21,7 +21,6 @@ import { getTimeRange } from 'app/features/dashboard/utils/timeRange';
|
||||
import { contextSrv } from '../../../../../../core/services/context_srv';
|
||||
import { AccessControlAction, useSelector } from '../../../../../../types';
|
||||
import { DeletePublicDashboardButton } from '../../../../../manage-dashboards/components/PublicDashboardListTable/DeletePublicDashboardButton';
|
||||
import { isOrgAdmin } from '../../../../../plugins/admin/permissions';
|
||||
import { useGetPublicDashboardQuery, useUpdatePublicDashboardMutation } from '../../../../api/publicDashboardApi';
|
||||
import { useIsDesktop } from '../../../../utils/screen';
|
||||
import { ShareModal } from '../../ShareModal';
|
||||
@ -55,7 +54,7 @@ const ConfigPublicDashboard = () => {
|
||||
const isDesktop = useIsDesktop();
|
||||
const { showModal, hideModal } = useContext(ModalsContext);
|
||||
|
||||
const hasWritePermissions = contextSrv.hasAccess(AccessControlAction.DashboardsPublicWrite, isOrgAdmin());
|
||||
const hasWritePermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPublicWrite);
|
||||
const hasEmailSharingEnabled =
|
||||
!!config.featureToggles.publicDashboardsEmailSharing && featureEnabled('publicDashboardsEmailSharing');
|
||||
const dashboardState = useSelector((store) => store.dashboard);
|
||||
|
@ -8,7 +8,6 @@ import { Button, Form, Spinner, useStyles2 } from '@grafana/ui/src';
|
||||
|
||||
import { contextSrv } from '../../../../../../core/services/context_srv';
|
||||
import { AccessControlAction, useSelector } from '../../../../../../types';
|
||||
import { isOrgAdmin } from '../../../../../plugins/admin/permissions';
|
||||
import { useCreatePublicDashboardMutation } from '../../../../api/publicDashboardApi';
|
||||
import { trackDashboardSharingActionPerType } from '../../analytics';
|
||||
import { shareDashboardType } from '../../utils';
|
||||
@ -29,7 +28,7 @@ export type SharePublicDashboardAcknowledgmentInputs = {
|
||||
|
||||
const CreatePublicDashboard = ({ isError }: { isError: boolean }) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const hasWritePermissions = contextSrv.hasAccess(AccessControlAction.DashboardsPublicWrite, isOrgAdmin());
|
||||
const hasWritePermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPublicWrite);
|
||||
const dashboardState = useSelector((store) => store.dashboard);
|
||||
const dashboard = dashboardState.getModel()!;
|
||||
const unsupportedDataSources = getUnsupportedDashboardDatasources(dashboard.panels);
|
||||
|
@ -69,7 +69,6 @@ beforeAll(() => {
|
||||
beforeEach(() => {
|
||||
config.featureToggles.publicDashboards = true;
|
||||
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasRole').mockReturnValue(true);
|
||||
});
|
||||
@ -103,7 +102,7 @@ const getErrorPublicDashboardResponse = () =>
|
||||
|
||||
const alertTests = () => {
|
||||
it('when user has no write permissions, warning is shown', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
await renderSharePublicDashboard();
|
||||
expect(screen.queryByTestId(selectors.NoUpsertPermissionsWarningAlert)).toBeInTheDocument();
|
||||
@ -251,7 +250,7 @@ describe('SharePublic - Already persisted', () => {
|
||||
expect(screen.getByTestId(selectors.DeleteButton)).toBeEnabled();
|
||||
});
|
||||
it('inputs and delete button are disabled because of lack of permissions', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
await renderSharePublicDashboard();
|
||||
await userEvent.click(screen.getByText('Settings'));
|
||||
|
||||
|
@ -73,8 +73,8 @@ export function AddToDashboardForm(props: Props): ReactElement {
|
||||
defaultValues: { saveTarget: SaveTarget.NewDashboard },
|
||||
});
|
||||
|
||||
const canCreateDashboard = contextSrv.hasAccess(AccessControlAction.DashboardsCreate, contextSrv.isEditor);
|
||||
const canWriteDashboard = contextSrv.hasAccess(AccessControlAction.DashboardsWrite, contextSrv.isEditor);
|
||||
const canCreateDashboard = contextSrv.hasPermission(AccessControlAction.DashboardsCreate);
|
||||
const canWriteDashboard = contextSrv.hasPermission(AccessControlAction.DashboardsWrite);
|
||||
|
||||
const saveTargets: Array<SelectableValue<SaveTarget>> = [];
|
||||
if (canCreateDashboard) {
|
||||
|
@ -8,22 +8,22 @@ jest.mock('app/core/services/context_srv');
|
||||
const contextSrvMock = jest.mocked(contextSrv);
|
||||
|
||||
describe('getAddToDashboardTitle', () => {
|
||||
beforeEach(() => contextSrvMock.hasAccess.mockReset());
|
||||
beforeEach(() => contextSrvMock.hasPermission.mockReset());
|
||||
|
||||
it('should return title ending with "dashboard" if user has full access', () => {
|
||||
contextSrvMock.hasAccess.mockReturnValue(true);
|
||||
contextSrvMock.hasPermission.mockReturnValue(true);
|
||||
|
||||
expect(getAddToDashboardTitle()).toBe('Add panel to dashboard');
|
||||
});
|
||||
|
||||
it('should return title ending with "dashboard" if user has no access', () => {
|
||||
contextSrvMock.hasAccess.mockReturnValue(false);
|
||||
contextSrvMock.hasPermission.mockReturnValue(false);
|
||||
|
||||
expect(getAddToDashboardTitle()).toBe('Add panel to dashboard');
|
||||
});
|
||||
|
||||
it('should return title ending with "new dashboard" if user only has access to create dashboards', () => {
|
||||
contextSrvMock.hasAccess.mockImplementation((action) => {
|
||||
contextSrvMock.hasPermission.mockImplementation((action) => {
|
||||
return action === AccessControlAction.DashboardsCreate;
|
||||
});
|
||||
|
||||
@ -31,7 +31,7 @@ describe('getAddToDashboardTitle', () => {
|
||||
});
|
||||
|
||||
it('should return title ending with "existing dashboard" if user only has access to edit dashboards', () => {
|
||||
contextSrvMock.hasAccess.mockImplementation((action) => {
|
||||
contextSrvMock.hasPermission.mockImplementation((action) => {
|
||||
return action === AccessControlAction.DashboardsWrite;
|
||||
});
|
||||
|
||||
|
@ -2,8 +2,8 @@ import { contextSrv } from 'app/core/services/context_srv';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
export function getAddToDashboardTitle(): string {
|
||||
const canCreateDashboard = contextSrv.hasAccess(AccessControlAction.DashboardsCreate, contextSrv.isEditor);
|
||||
const canWriteDashboard = contextSrv.hasAccess(AccessControlAction.DashboardsWrite, contextSrv.isEditor);
|
||||
const canCreateDashboard = contextSrv.hasPermission(AccessControlAction.DashboardsCreate);
|
||||
const canWriteDashboard = contextSrv.hasPermission(AccessControlAction.DashboardsWrite);
|
||||
|
||||
if (canCreateDashboard && !canWriteDashboard) {
|
||||
return 'Add panel to new dashboard';
|
||||
|
@ -73,7 +73,7 @@ describe('AddToDashboardButton', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(api, 'setDashboardInLocalStorage').mockReturnValue(addToDashboardResponse);
|
||||
mocks.contextSrv.hasAccess.mockImplementation(() => true);
|
||||
mocks.contextSrv.hasPermission.mockImplementation(() => true);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -283,7 +283,7 @@ describe('AddToDashboardButton', () => {
|
||||
});
|
||||
|
||||
it('Should only show existing dashboard option with no access to create', async () => {
|
||||
mocks.contextSrv.hasAccess.mockImplementation((action) => {
|
||||
mocks.contextSrv.hasPermission.mockImplementation((action) => {
|
||||
if (action === 'dashboards:create') {
|
||||
return false;
|
||||
} else {
|
||||
@ -296,7 +296,7 @@ describe('AddToDashboardButton', () => {
|
||||
});
|
||||
|
||||
it('Should only show new dashboard option with no access to write', async () => {
|
||||
mocks.contextSrv.hasAccess.mockImplementation((action) => {
|
||||
mocks.contextSrv.hasPermission.mockImplementation((action) => {
|
||||
if (action === 'dashboards:write') {
|
||||
return false;
|
||||
} else {
|
||||
@ -311,7 +311,7 @@ describe('AddToDashboardButton', () => {
|
||||
|
||||
describe('Error handling', () => {
|
||||
beforeEach(() => {
|
||||
mocks.contextSrv.hasAccess.mockImplementation(() => true);
|
||||
mocks.contextSrv.hasPermission.mockImplementation(() => true);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -215,7 +215,7 @@ describe('ToolbarExtensionPoint', () => {
|
||||
|
||||
describe('without extension points', () => {
|
||||
beforeAll(() => {
|
||||
contextSrvMock.hasAccess.mockReturnValue(true);
|
||||
contextSrvMock.hasPermission.mockReturnValue(true);
|
||||
getPluginLinkExtensionsMock.mockReturnValue({ extensions: [] });
|
||||
});
|
||||
|
||||
@ -233,7 +233,7 @@ describe('ToolbarExtensionPoint', () => {
|
||||
|
||||
describe('with insufficient permissions', () => {
|
||||
beforeAll(() => {
|
||||
contextSrvMock.hasAccess.mockReturnValue(false);
|
||||
contextSrvMock.hasPermission.mockReturnValue(false);
|
||||
getPluginLinkExtensionsMock.mockReturnValue({ extensions: [] });
|
||||
});
|
||||
|
||||
|
@ -35,8 +35,8 @@ export function ToolbarExtensionPoint(props: Props): ReactElement | null {
|
||||
// adding a query to a dashboard.
|
||||
if (extensions.length <= 1) {
|
||||
const canAddPanelToDashboard =
|
||||
contextSrv.hasAccess(AccessControlAction.DashboardsCreate, contextSrv.isEditor) ||
|
||||
contextSrv.hasAccess(AccessControlAction.DashboardsWrite, contextSrv.isEditor);
|
||||
contextSrv.hasPermission(AccessControlAction.DashboardsCreate) ||
|
||||
contextSrv.hasPermission(AccessControlAction.DashboardsWrite);
|
||||
|
||||
if (!canAddPanelToDashboard) {
|
||||
return null;
|
||||
|
@ -28,10 +28,10 @@ describe('getExploreExtensionConfigs', () => {
|
||||
});
|
||||
|
||||
describe('configure function for "add to dashboard" extension', () => {
|
||||
afterEach(() => contextSrvMock.hasAccess.mockRestore());
|
||||
afterEach(() => contextSrvMock.hasPermission.mockRestore());
|
||||
|
||||
it('should return undefined if insufficient permissions', () => {
|
||||
contextSrvMock.hasAccess.mockReturnValue(false);
|
||||
contextSrvMock.hasPermission.mockReturnValue(false);
|
||||
|
||||
const extensions = getExploreExtensionConfigs();
|
||||
const [extension] = extensions;
|
||||
@ -40,7 +40,7 @@ describe('getExploreExtensionConfigs', () => {
|
||||
});
|
||||
|
||||
it('should return empty object if sufficient permissions', () => {
|
||||
contextSrvMock.hasAccess.mockReturnValue(true);
|
||||
contextSrvMock.hasPermission.mockReturnValue(true);
|
||||
|
||||
const extensions = getExploreExtensionConfigs();
|
||||
const [extension] = extensions;
|
||||
|
@ -21,8 +21,8 @@ export function getExploreExtensionConfigs(): PluginExtensionLinkConfig[] {
|
||||
category: 'Dashboards',
|
||||
configure: () => {
|
||||
const canAddPanelToDashboard =
|
||||
contextSrv.hasAccess(AccessControlAction.DashboardsCreate, contextSrv.isEditor) ||
|
||||
contextSrv.hasAccess(AccessControlAction.DashboardsWrite, contextSrv.isEditor);
|
||||
contextSrv.hasPermission(AccessControlAction.DashboardsCreate) ||
|
||||
contextSrv.hasPermission(AccessControlAction.DashboardsWrite);
|
||||
|
||||
// hide option if user has insufficient permissions
|
||||
if (!canAddPanelToDashboard) {
|
||||
|
@ -128,7 +128,7 @@ describe('Show table', () => {
|
||||
expect(screen.queryAllByRole('listitem')).toHaveLength(0);
|
||||
});
|
||||
it('renders public dashboards in a good way without trashcan', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
await renderPublicDashboardTable(true);
|
||||
publicDashboardListResponse.forEach((pd, idx) => {
|
||||
@ -136,7 +136,7 @@ describe('Show table', () => {
|
||||
});
|
||||
});
|
||||
it('renders public dashboards in a good way with trashcan', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
await renderPublicDashboardTable(true);
|
||||
publicDashboardListResponse.forEach((pd, idx) => {
|
||||
@ -147,13 +147,13 @@ describe('Show table', () => {
|
||||
|
||||
describe('Delete public dashboard', () => {
|
||||
it('when user does not have public dashboard write permissions, then dashboards are listed without delete button', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(false);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
await renderPublicDashboardTable(true);
|
||||
|
||||
expect(screen.queryAllByTestId(selectors.ListItem.trashcanButton)).toHaveLength(0);
|
||||
});
|
||||
it('when user has public dashboard write permissions, then dashboards are listed with delete button', async () => {
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
await renderPublicDashboardTable(true);
|
||||
|
||||
expect(screen.getAllByTestId(selectors.ListItem.trashcanButton)).toHaveLength(publicDashboardListResponse.length);
|
||||
@ -171,7 +171,7 @@ describe('Orphaned public dashboard', () => {
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
})
|
||||
);
|
||||
jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
|
||||
await renderPublicDashboardTable(true);
|
||||
response.publicDashboards.forEach((pd, idx) => {
|
||||
|
@ -27,7 +27,6 @@ import {
|
||||
generatePublicDashboardConfigUrl,
|
||||
generatePublicDashboardUrl,
|
||||
} from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
import { isOrgAdmin } from 'app/features/plugins/admin/permissions';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
import { PublicDashboardListResponse } from '../../types';
|
||||
@ -42,7 +41,7 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
|
||||
const [update, { isLoading: isUpdateLoading }] = useUpdatePublicDashboardMutation();
|
||||
|
||||
const selectors = e2eSelectors.pages.PublicDashboards;
|
||||
const hasWritePermissions = contextSrv.hasAccess(AccessControlAction.DashboardsPublicWrite, isOrgAdmin());
|
||||
const hasWritePermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPublicWrite);
|
||||
const isOrphaned = !pd.dashboardUid;
|
||||
|
||||
const onTogglePause = (pd: PublicDashboardListResponse, isPaused: boolean) => {
|
||||
|
@ -8,7 +8,6 @@ import { contextSrv } from 'app/core/core';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
import { getExternalManageLink } from '../../helpers';
|
||||
import { isGrafanaAdmin } from '../../permissions';
|
||||
import { useIsRemotePluginsAvailable } from '../../state/hooks';
|
||||
import { CatalogPlugin, PluginStatus, Version } from '../../types';
|
||||
|
||||
@ -21,7 +20,7 @@ interface Props {
|
||||
export const InstallControlsWarning = ({ plugin, pluginStatus, latestCompatibleVersion }: Props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const isExternallyManaged = config.pluginAdminExternalManageEnabled;
|
||||
const hasPermission = contextSrv.hasAccess(AccessControlAction.PluginsInstall, isGrafanaAdmin());
|
||||
const hasPermission = contextSrv.hasPermission(AccessControlAction.PluginsInstall);
|
||||
const isRemotePluginsAvailable = useIsRemotePluginsAvailable();
|
||||
const isCompatible = Boolean(latestCompatibleVersion);
|
||||
|
||||
|
@ -5,7 +5,6 @@ import { contextSrv } from 'app/core/core';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
import { isGrafanaAdmin } from './permissions';
|
||||
import { CatalogPlugin, LocalPlugin, RemotePlugin, Version } from './types';
|
||||
|
||||
export function mergeLocalsAndRemotes(
|
||||
@ -283,7 +282,7 @@ export const hasInstallControlWarning = (
|
||||
latestCompatibleVersion?: Version
|
||||
) => {
|
||||
const isExternallyManaged = config.pluginAdminExternalManageEnabled;
|
||||
const hasPermission = contextSrv.hasAccess(AccessControlAction.PluginsInstall, isGrafanaAdmin());
|
||||
const hasPermission = contextSrv.hasPermission(AccessControlAction.PluginsInstall);
|
||||
const isCompatible = Boolean(latestCompatibleVersion);
|
||||
return (
|
||||
plugin.type === PluginType.renderer ||
|
||||
|
@ -53,6 +53,7 @@ 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,
|
||||
},
|
||||
}));
|
||||
|
@ -15,6 +15,7 @@ jest.mock('app/core/services/context_srv', () => {
|
||||
...originMock.context_srv,
|
||||
user: {},
|
||||
hasAccess: jest.fn(() => false),
|
||||
hasPermission: jest.fn(() => false),
|
||||
},
|
||||
};
|
||||
});
|
||||
@ -32,16 +33,19 @@ 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} />));
|
||||
|
||||
expect(screen.getByRole('button', { name: /new/i })).toBeInTheDocument();
|
||||
|
@ -30,11 +30,11 @@ export const ManageDashboardsNew = React.memo(({ folder }: Props) => {
|
||||
const canSave = folder?.canSave;
|
||||
const { isEditor } = contextSrv;
|
||||
const hasEditPermissionInFolders = folder ? canSave : contextSrv.hasEditPermissionInFolders;
|
||||
const canCreateFolders = contextSrv.hasAccess(AccessControlAction.FoldersCreate, isEditor);
|
||||
const canCreateFolders = contextSrv.hasPermission(AccessControlAction.FoldersCreate);
|
||||
const canCreateDashboardsFallback = hasEditPermissionInFolders || !!canSave;
|
||||
const canCreateDashboards = folderUid
|
||||
? contextSrv.hasAccessInMetadata(AccessControlAction.DashboardsCreate, folder, canCreateDashboardsFallback)
|
||||
: contextSrv.hasAccess(AccessControlAction.DashboardsCreate, canCreateDashboardsFallback);
|
||||
: contextSrv.hasPermission(AccessControlAction.DashboardsCreate);
|
||||
const viewActions = (folder === undefined && canCreateFolders) || canCreateDashboards;
|
||||
|
||||
useEffect(() => stateManager.initStateFromUrl(folder?.uid), [folder?.uid, stateManager]);
|
||||
|
@ -52,11 +52,8 @@ const SupportBundlesUnconnected = ({ supportBundles, isLoading, loadBundles, rem
|
||||
}
|
||||
});
|
||||
|
||||
const hasAccess = contextSrv.hasAccess(AccessControlAction.ActionSupportBundlesCreate, contextSrv.isGrafanaAdmin);
|
||||
const hasDeleteAccess = contextSrv.hasAccess(
|
||||
AccessControlAction.ActionSupportBundlesDelete,
|
||||
contextSrv.isGrafanaAdmin
|
||||
);
|
||||
const hasAccess = contextSrv.hasPermission(AccessControlAction.ActionSupportBundlesCreate);
|
||||
const hasDeleteAccess = contextSrv.hasPermission(AccessControlAction.ActionSupportBundlesDelete);
|
||||
|
||||
const actions = hasAccess ? NewBundleButton : undefined;
|
||||
|
||||
|
@ -10,9 +10,11 @@ import { OrgRole, Team } from '../../types';
|
||||
import { Props, TeamList } from './TeamList';
|
||||
import { getMockTeam, getMultipleMockTeams } from './__mocks__/teamMocks';
|
||||
|
||||
jest.mock('app/core/config', () => ({
|
||||
...jest.requireActual('app/core/config'),
|
||||
featureToggles: { accesscontrol: false },
|
||||
jest.mock('app/core/core', () => ({
|
||||
contextSrv: {
|
||||
hasPermission: (action: string) => true,
|
||||
licensedAccessControlEnabled: () => false,
|
||||
},
|
||||
}));
|
||||
|
||||
const setup = (propOverrides?: object) => {
|
||||
@ -51,39 +53,39 @@ describe('TeamList', () => {
|
||||
expect(screen.getAllByRole('row')).toHaveLength(6); // 5 teams plus table header row
|
||||
});
|
||||
|
||||
describe('when feature toggle editorsCanAdmin is turned on', () => {
|
||||
describe('and signed in user is not viewer', () => {
|
||||
it('should enable the new team button', () => {
|
||||
setup({
|
||||
teams: getMultipleMockTeams(1),
|
||||
totalCount: 1,
|
||||
hasFetched: true,
|
||||
editorsCanAdmin: true,
|
||||
signedInUser: {
|
||||
id: 1,
|
||||
orgRole: OrgRole.Editor,
|
||||
} as User,
|
||||
});
|
||||
|
||||
expect(screen.getByRole('link', { name: /new team/i })).not.toHaveStyle('pointer-events: none');
|
||||
describe('when user has access to create a team', () => {
|
||||
it('should enable the new team button', () => {
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
setup({
|
||||
teams: getMultipleMockTeams(1),
|
||||
totalCount: 1,
|
||||
hasFetched: true,
|
||||
editorsCanAdmin: true,
|
||||
signedInUser: {
|
||||
id: 1,
|
||||
orgRole: OrgRole.Editor,
|
||||
} as User,
|
||||
});
|
||||
|
||||
expect(screen.getByRole('link', { name: /new team/i })).not.toHaveStyle('pointer-events: none');
|
||||
});
|
||||
});
|
||||
|
||||
describe('and signed in user is a viewer', () => {
|
||||
it('should disable the new team button', () => {
|
||||
setup({
|
||||
teams: getMultipleMockTeams(1),
|
||||
totalCount: 1,
|
||||
hasFetched: true,
|
||||
editorsCanAdmin: true,
|
||||
signedInUser: {
|
||||
id: 1,
|
||||
orgRole: OrgRole.Viewer,
|
||||
} as User,
|
||||
});
|
||||
|
||||
expect(screen.getByRole('link', { name: /new team/i })).toHaveStyle('pointer-events: none');
|
||||
describe('when user does not have access to create a team', () => {
|
||||
it('should disable the new team button', () => {
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
setup({
|
||||
teams: getMultipleMockTeams(1),
|
||||
totalCount: 1,
|
||||
hasFetched: true,
|
||||
editorsCanAdmin: true,
|
||||
signedInUser: {
|
||||
id: 1,
|
||||
orgRole: OrgRole.Viewer,
|
||||
} as User,
|
||||
});
|
||||
|
||||
expect(screen.getByRole('link', { name: /new team/i })).toHaveStyle('pointer-events: none');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -91,6 +93,7 @@ describe('TeamList', () => {
|
||||
it('should call delete team', async () => {
|
||||
const mockDelete = jest.fn();
|
||||
const mockTeam = getMockTeam();
|
||||
jest.spyOn(contextSrv, 'hasAccessInMetadata').mockReturnValue(true);
|
||||
setup({ deleteTeam: mockDelete, teams: [mockTeam], totalCount: 1, hasFetched: true });
|
||||
await userEvent.click(screen.getByRole('button', { name: `Delete team ${mockTeam.name}` }));
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Delete' }));
|
||||
|
@ -60,7 +60,7 @@ export const TeamList = ({
|
||||
}
|
||||
}, []);
|
||||
|
||||
const canCreate = canCreateTeam(editorsCanAdmin);
|
||||
const canCreate = contextSrv.hasPermission(AccessControlAction.ActionTeamsCreate);
|
||||
const displayRolePicker = shouldDisplayRolePicker();
|
||||
|
||||
return (
|
||||
@ -137,11 +137,6 @@ export const TeamList = ({
|
||||
);
|
||||
};
|
||||
|
||||
function canCreateTeam(editorsCanAdmin: boolean): boolean {
|
||||
const teamAdmin = contextSrv.hasRole('Admin') || (editorsCanAdmin && contextSrv.hasRole('Editor'));
|
||||
return contextSrv.hasAccess(AccessControlAction.ActionTeamsCreate, teamAdmin);
|
||||
}
|
||||
|
||||
function shouldDisplayRolePicker(): boolean {
|
||||
return (
|
||||
contextSrv.licensedAccessControlEnabled() &&
|
||||
|
Loading…
Reference in New Issue
Block a user