RBAC: Make access control metadata for folders work with nested folders (#66464)

* remove metadata for single folder listing

* extendTests

* remove ac metadata from dash and folder search results

* remove test

* remove one more test

* put ac metadata back for single folder API responses

* extend tests

* remove ac metadata from folder frontend object

* undo unneeded change

* PR feedback

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>

---------

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
Ieva
2023-04-21 15:05:11 +01:00
committed by GitHub
parent 94294a72c8
commit 5d7433d820
10 changed files with 87 additions and 233 deletions

View File

@@ -6,9 +6,7 @@ import { useFormContext } from 'react-hook-form';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { Stack } from '@grafana/experimental';
import { AsyncSelect, Field, InputControl, Label, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
import { FolderPickerFilter } from 'app/core/components/Select/FolderPicker';
import { contextSrv } from 'app/core/core';
import { DashboardSearchHit } from 'app/features/search/types';
import { AccessControlAction, useDispatch } from 'app/types';
import { useCombinedRuleNamespaces } from '../../hooks/useCombinedRuleNamespaces';
@@ -20,7 +18,7 @@ import { isGrafanaRulerRule } from '../../utils/rules';
import { InfoIcon } from '../InfoIcon';
import { MINUTE } from './AlertRuleForm';
import { containsSlashes, Folder, RuleFolderPicker } from './RuleFolderPicker';
import { Folder, RuleFolderPicker } from './RuleFolderPicker';
import { checkForPathSeparator } from './util';
export const SLICE_GROUP_RESULTS_TO = 1000;
@@ -51,35 +49,6 @@ export const useGetGroupOptionsFromFolder = (folderTitle: string) => {
return { groupOptions, loading: groupfoldersForGrafana?.loading };
};
const useRuleFolderFilter = (existingRuleForm: RuleForm | null) => {
const isSearchHitAvailable = useCallback(
(hit: DashboardSearchHit) => {
const rbacDisabledFallback = contextSrv.hasEditPermissionInFolders;
const canCreateRuleInFolder = contextSrv.hasAccessInMetadata(
AccessControlAction.AlertingRuleCreate,
hit,
rbacDisabledFallback
);
const canUpdateInCurrentFolder =
existingRuleForm &&
hit.folderId === existingRuleForm.id &&
contextSrv.hasAccessInMetadata(AccessControlAction.AlertingRuleUpdate, hit, rbacDisabledFallback);
return canCreateRuleInFolder || canUpdateInCurrentFolder;
},
[existingRuleForm]
);
return useCallback<FolderPickerFilter>(
(folderHits) =>
folderHits
.filter(isSearchHitAvailable)
.filter((value: DashboardSearchHit) => !containsSlashes(value.title ?? '')),
[isSearchHitAvailable]
);
};
export function FolderAndGroup({ initialFolder }: FolderAndGroupProps) {
const {
formState: { errors },
@@ -89,7 +58,6 @@ export function FolderAndGroup({ initialFolder }: FolderAndGroupProps) {
const styles = useStyles2(getStyles);
const dispatch = useDispatch();
const folderFilter = useRuleFolderFilter(initialFolder);
const folder = watch('folder');
const group = watch('group');
@@ -165,7 +133,6 @@ export function FolderAndGroup({ initialFolder }: FolderAndGroupProps) {
{...field}
enableCreateNew={contextSrv.hasPermission(AccessControlAction.FoldersCreate)}
enableReset={true}
filter={folderFilter}
onChange={({ title, uid }) => {
field.onChange({ title, uid });
if (!groupIsInGroupOptions(selectedGroup.value ?? '')) {

View File

@@ -5,7 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { Stack } from '@grafana/experimental';
import { Icon, Tooltip, useStyles2 } from '@grafana/ui';
import { FolderPicker, Props as FolderPickerProps } from 'app/core/components/Select/FolderPicker';
import { PermissionLevelString } from 'app/types';
import { PermissionLevelString, SearchQueryType } from 'app/types';
import { FolderWarning, CustomAdd } from '../../../../../core/components/Select/FolderPicker';
@@ -54,9 +54,9 @@ export function RuleFolderPicker(props: RuleFolderPickerProps) {
allowEmpty={true}
initialTitle={value?.title}
initialFolderUid={value?.uid}
accessControlMetadata
searchQueryType={SearchQueryType.AlertFolder}
{...props}
permissionLevel={PermissionLevelString.View}
permissionLevel={PermissionLevelString.Edit}
customAdd={customAdd}
folderWarning={folderWarning}
/>

View File

@@ -4,7 +4,7 @@ import { notifyApp } from 'app/core/actions';
import { createErrorNotification } from 'app/core/copy/appNotification';
import { SaveDashboardCommand } from 'app/features/dashboard/components/SaveDashboard/types';
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
import { DashboardDTO, FolderInfo, PermissionLevelString, ThunkResult } from 'app/types';
import { DashboardDTO, FolderInfo, PermissionLevelString, SearchQueryType, ThunkResult } from 'app/types';
import { LibraryElementExport } from '../../dashboard/components/DashExportModal/DashboardExporter';
import { getLibraryPanel } from '../../library-panels/state/api';
@@ -316,13 +316,12 @@ export const SLICE_FOLDER_RESULTS_TO = 1000;
export function searchFolders(
query: any,
permission?: PermissionLevelString,
withAccessControl = false
type: SearchQueryType = SearchQueryType.Folder
): Promise<DashboardSearchHit[]> {
return getBackendSrv().get('/api/search', {
query,
type: 'dash-folder',
type: type,
permission,
accesscontrol: withAccessControl,
limit: SLICE_FOLDER_RESULTS_TO,
});
}