[permissions] Adapt FE to non-readable fields (#13440)

Fixes https://github.com/twentyhq/core-team-issues/issues/1261 and
https://github.com/twentyhq/core-team-issues/issues/1153

In this PR we
- remove fields user do not have read access on from queries (findMany,
findDuplicates, returned fields from create or update etc.)
- remove fields user do not have read access on from views 

This is behind a feature flag
This commit is contained in:
Marie
2025-07-28 18:24:08 +02:00
committed by GitHub
parent 4131be2a68
commit 16ba72edab
52 changed files with 394 additions and 95 deletions
@@ -11,7 +11,9 @@ import { computeDepthOneRecordGqlFieldsFromRecord } from '@/object-record/graphq
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { prefillRecord } from '@/object-record/utils/prefillRecord';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
import { capitalize } from 'twenty-shared/utils';
import { FeatureFlagKey } from '~/generated/graphql';
export const useCreateOneRecordInCache = <T extends ObjectRecord>({
objectMetadataItem,
@@ -25,6 +27,9 @@ export const useCreateOneRecordInCache = <T extends ObjectRecord>({
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const apolloCoreClient = useApolloCoreClient();
const featureFlags = useFeatureFlagsMap();
const isFieldsPermissionsEnabled =
featureFlags[FeatureFlagKey.IS_FIELDS_PERMISSIONS_ENABLED];
return (record: ObjectRecord) => {
const prefilledRecord = prefillRecord({
@@ -46,6 +51,7 @@ export const useCreateOneRecordInCache = <T extends ObjectRecord>({
computeReferences: true,
recordGqlFields,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled,
})}
`;
@@ -7,7 +7,9 @@ import { RecordGqlOperationVariables } from '@/object-record/graphql/types/Recor
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
import { isDefined } from 'twenty-shared/utils';
import { FeatureFlagKey } from '~/generated/graphql';
export const useReadFindManyRecordsQueryInCache = ({
objectMetadataItem,
@@ -20,6 +22,10 @@ export const useReadFindManyRecordsQueryInCache = ({
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const featureFlags = useFeatureFlagsMap();
const isFieldsPermissionsEnabled =
featureFlags[FeatureFlagKey.IS_FIELDS_PERMISSIONS_ENABLED];
const readFindManyRecordsQueryInCache = <
T extends ObjectRecord = ObjectRecord,
>({
@@ -34,6 +40,7 @@ export const useReadFindManyRecordsQueryInCache = ({
objectMetadataItems,
recordGqlFields,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled,
});
const existingRecordsQueryResult =
@@ -8,6 +8,8 @@ import { RecordGqlOperationVariables } from '@/object-record/graphql/types/Recor
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
import { FeatureFlagKey } from '~/generated/graphql';
export const useUpsertFindManyRecordsQueryInCache = ({
objectMetadataItem,
@@ -19,6 +21,10 @@ export const useUpsertFindManyRecordsQueryInCache = ({
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const featureFlags = useFeatureFlagsMap();
const isFieldsPermissionsEnabled =
featureFlags[FeatureFlagKey.IS_FIELDS_PERMISSIONS_ENABLED];
const upsertFindManyRecordsQueryInCache = <
T extends ObjectRecord = ObjectRecord,
>({
@@ -38,6 +44,7 @@ export const useUpsertFindManyRecordsQueryInCache = ({
recordGqlFields,
computeReferences,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled,
});
const newObjectRecordConnection = getRecordConnectionFromRecords({
@@ -7,7 +7,7 @@ import { RecordGqlFields } from '@/object-record/graphql/types/RecordGqlFields';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { capitalize } from 'twenty-shared/utils';
import { ObjectPermission } from '~/generated-metadata/graphql';
import { ObjectPermission } from '~/generated/graphql';
import { isEmptyObject } from '~/utils/isEmptyObject';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
@@ -18,6 +18,7 @@ export type GetRecordFromCacheArgs = {
objectMetadataItem: ObjectMetadataItem;
recordGqlFields?: RecordGqlFields;
objectPermissionsByObjectMetadataId: Record<string, ObjectPermission>;
isFieldsPermissionsEnabled?: boolean;
};
export const getRecordFromCache = <T extends ObjectRecord = ObjectRecord>({
objectMetadataItem,
@@ -26,6 +27,7 @@ export const getRecordFromCache = <T extends ObjectRecord = ObjectRecord>({
recordId,
recordGqlFields,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled = false,
}: GetRecordFromCacheArgs) => {
if (isUndefinedOrNull(objectMetadataItem)) {
return null;
@@ -43,6 +45,7 @@ export const getRecordFromCache = <T extends ObjectRecord = ObjectRecord>({
objectMetadataItem,
recordGqlFields: appliedRecordGqlFields,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled,
},
)}
`;
@@ -7,7 +7,7 @@ import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNo
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { capitalize } from 'twenty-shared/utils';
import { ObjectPermission } from '~/generated-metadata/graphql';
import { ObjectPermission } from '~/generated/graphql';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
export const updateRecordFromCache = <T extends ObjectRecord>({
@@ -17,6 +17,7 @@ export const updateRecordFromCache = <T extends ObjectRecord>({
recordGqlFields,
record,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled,
}: {
objectMetadataItems: ObjectMetadataItem[];
objectMetadataItem: ObjectMetadataItem;
@@ -24,6 +25,7 @@ export const updateRecordFromCache = <T extends ObjectRecord>({
recordGqlFields: Record<string, boolean>;
record: T;
objectPermissionsByObjectMetadataId: Record<string, ObjectPermission>;
isFieldsPermissionsEnabled?: boolean;
}) => {
if (isUndefinedOrNull(objectMetadataItem)) {
return null;
@@ -39,6 +41,7 @@ export const updateRecordFromCache = <T extends ObjectRecord>({
computeReferences: true,
recordGqlFields,
objectPermissionsByObjectMetadataId,
isFieldsPermissionsEnabled,
},
)}
`;