[permissions V2] Fix - filter objects to search (#12803)

In morph relation pickers, we were not taking into account permissions
when computing the list of objects to search for, while we should not
search for objects we don't have read permissions on (permission denied
error)
This commit is contained in:
Marie
2025-06-23 19:35:08 +02:00
committed by GitHub
parent 37b48e2b21
commit 00eb93463c
2 changed files with 35 additions and 3 deletions

View File

@ -5,7 +5,9 @@ import { ActionType } from '@/action-menu/actions/types/ActionType';
import { MAX_SEARCH_RESULTS } from '@/command-menu/constants/MaxSearchResults'; import { MAX_SEARCH_RESULTS } from '@/command-menu/constants/MaxSearchResults';
import { useOpenRecordInCommandMenu } from '@/command-menu/hooks/useOpenRecordInCommandMenu'; import { useOpenRecordInCommandMenu } from '@/command-menu/hooks/useOpenRecordInCommandMenu';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState'; import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
import { AppPath } from '@/types/AppPath'; import { AppPath } from '@/types/AppPath';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
import { useMemo } from 'react'; import { useMemo } from 'react';
@ -19,12 +21,28 @@ export const useCommandMenuSearchRecords = () => {
const commandMenuSearch = useRecoilValue(commandMenuSearchState); const commandMenuSearch = useRecoilValue(commandMenuSearchState);
const [deferredCommandMenuSearch] = useDebounce(commandMenuSearch, 300); const [deferredCommandMenuSearch] = useDebounce(commandMenuSearch, 300);
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const { objectMetadataItems } = useObjectMetadataItems();
const nonReadableObjectMetadataItemsNameSingular = useMemo(() => {
return Object.values(objectMetadataItems)
.filter((objectMetadataItem) => {
const objectPermission =
objectPermissionsByObjectMetadataId[objectMetadataItem.id];
return !objectPermission?.canReadObjectRecords;
})
.map((objectMetadataItem) => objectMetadataItem.nameSingular);
}, [objectMetadataItems, objectPermissionsByObjectMetadataId]);
const { data: searchData, loading } = useSearchQuery({ const { data: searchData, loading } = useSearchQuery({
variables: { variables: {
searchInput: deferredCommandMenuSearch ?? '', searchInput: deferredCommandMenuSearch ?? '',
limit: MAX_SEARCH_RESULTS, limit: MAX_SEARCH_RESULTS,
excludedObjectNameSingulars: ['workspaceMember'], excludedObjectNameSingulars: [
'workspaceMember',
...nonReadableObjectMetadataItemsNameSingular,
],
}, },
}); });

View File

@ -1,5 +1,6 @@
import { SEARCH_QUERY } from '@/command-menu/graphql/queries/search'; import { SEARCH_QUERY } from '@/command-menu/graphql/queries/search';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
import { usePerformCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/usePerformCombinedFindManyRecords'; import { usePerformCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/usePerformCombinedFindManyRecords';
import { multipleRecordPickerIsLoadingComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerIsLoadingComponentState'; import { multipleRecordPickerIsLoadingComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerIsLoadingComponentState';
import { multipleRecordPickerPaginationState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerPaginationState'; import { multipleRecordPickerPaginationState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerPaginationState';
@ -23,6 +24,8 @@ export const useMultipleRecordPickerPerformSearch = () => {
const { performCombinedFindManyRecords } = const { performCombinedFindManyRecords } =
usePerformCombinedFindManyRecords(); usePerformCombinedFindManyRecords();
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const performSearch = useRecoilCallback( const performSearch = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
async ({ async ({
@ -97,6 +100,13 @@ export const useMultipleRecordPickerPerformSearch = () => {
({ isSelected }) => isSelected, ({ isSelected }) => isSelected,
); );
const filteredSearchableObjectMetadataItems =
searchableObjectMetadataItems.filter(
(objectMetadataItem) =>
objectPermissionsByObjectMetadataId[objectMetadataItem.id]
.canReadObjectRecords === true,
);
const [ const [
searchRecordsFilteredOnPickedRecords, searchRecordsFilteredOnPickedRecords,
searchRecordsExcludingPickedRecords, searchRecordsExcludingPickedRecords,
@ -104,7 +114,7 @@ export const useMultipleRecordPickerPerformSearch = () => {
] = await performSearchQueries({ ] = await performSearchQueries({
client, client,
searchFilter, searchFilter,
searchableObjectMetadataItems, searchableObjectMetadataItems: filteredSearchableObjectMetadataItems,
pickedRecordIds: selectedPickableMorphItems.map( pickedRecordIds: selectedPickableMorphItems.map(
({ recordId }) => recordId, ({ recordId }) => recordId,
), ),
@ -357,7 +367,11 @@ export const useMultipleRecordPickerPerformSearch = () => {
false, false,
); );
}, },
[client, performCombinedFindManyRecords], [
client,
performCombinedFindManyRecords,
objectPermissionsByObjectMetadataId,
],
); );
return { performSearch }; return { performSearch };