[permissions] Deprecate ObjectsPermissionsDeprecated (1/3) (#14306)
We want to update UserWorkspacePermissions from
```
export type UserWorkspacePermissions = {
permissionFlags: Record<PermissionFlagType, boolean>;
objectRecordsPermissions: Record<PermissionsOnAllObjectRecords, boolean>;
objectPermissions: ObjectsPermissionsDeprecated;
};
```
to
```
export type UserWorkspacePermissions = {
permissionFlags: Record<PermissionFlagType, boolean>;
objectsPermissions: ObjectsPermissions;
};
```
`ObjectsPermissionsDeprecated` and `ObjectsPermissions` are actually
very similar, they only have different key names (`canRead` vs
`canReadObjectRecords`)
To avoid brutal breaking changes, we will proceed in multiple steps:
1. This PR: adapt FE so it does not call objectRecordsPermissions
anymore + add the new objectsPermissions to UserWorkspacePermissions
without calling it yet in the FE
2. Remove objectRecordsPermissions in BE + use objectsPermissions in FE
instead of objectPermissions
3. Remove objectPermissions
This commit is contained in:
@@ -4,9 +4,7 @@ import { type UserWorkspace } from '~/generated/graphql';
|
||||
|
||||
export type CurrentUserWorkspace = Pick<
|
||||
UserWorkspace,
|
||||
| 'permissionFlags'
|
||||
| 'twoFactorAuthenticationMethodSummary'
|
||||
| 'objectRecordsPermissions'
|
||||
'permissionFlags' | 'twoFactorAuthenticationMethodSummary'
|
||||
> & {
|
||||
objectPermissions: Array<ObjectPermissions & { objectMetadataId: string }>;
|
||||
};
|
||||
|
||||
+1
@@ -146,6 +146,7 @@ export const RecordDetailRelationSectionDropdownToMany = () => {
|
||||
focusId={dropdownId}
|
||||
componentInstanceId={dropdownId}
|
||||
onCreate={handleCreateNew}
|
||||
objectMetadataItemIdForCreate={relationObjectMetadataItem.id}
|
||||
onChange={updateRelation}
|
||||
onSubmit={() => {
|
||||
closeDropdown(dropdownId);
|
||||
|
||||
+1
@@ -153,6 +153,7 @@ export const RelationFromManyFieldInput = () => {
|
||||
}
|
||||
}}
|
||||
onCreate={canCreateNew ? handleCreateNew : undefined}
|
||||
objectMetadataItemIdForCreate={relationObjectMetadataItem.id}
|
||||
onClickOutside={handleSubmit}
|
||||
layoutDirection={
|
||||
layoutDirection === 'downward'
|
||||
|
||||
+8
-4
@@ -1,3 +1,4 @@
|
||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||
import { MultipleRecordPickerItemsDisplay } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerItemsDisplay';
|
||||
import { MultipleRecordPickerOnClickOutsideEffect } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerOnClickOutsideEffect';
|
||||
import { MultipleRecordPickerSearchInput } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerSearchInput';
|
||||
@@ -7,7 +8,6 @@ import { multipleRecordPickerSearchFilterComponentState } from '@/object-record/
|
||||
import { getMultipleRecordPickerSelectableListId } from '@/object-record/record-picker/multiple-record-picker/utils/getMultipleRecordPickerSelectableListId';
|
||||
import { type RecordPickerLayoutDirection } from '@/object-record/record-picker/types/RecordPickerLayoutDirection';
|
||||
import { type RecordPickerPickableMorphItem } from '@/object-record/record-picker/types/RecordPickerPickableMorphItem';
|
||||
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
|
||||
import { CreateNewButton } from '@/ui/input/relation-picker/components/CreateNewButton';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@@ -28,6 +28,7 @@ type MultipleRecordPickerProps = {
|
||||
componentInstanceId: string;
|
||||
onClickOutside: () => void;
|
||||
focusId: string;
|
||||
objectMetadataItemIdForCreate?: string;
|
||||
};
|
||||
|
||||
export const MultipleRecordPicker = ({
|
||||
@@ -38,6 +39,7 @@ export const MultipleRecordPicker = ({
|
||||
layoutDirection = 'search-bar-on-bottom',
|
||||
componentInstanceId,
|
||||
focusId,
|
||||
objectMetadataItemIdForCreate,
|
||||
}: MultipleRecordPickerProps) => {
|
||||
const selectableListComponentInstanceId =
|
||||
getMultipleRecordPickerSelectableListId(componentInstanceId);
|
||||
@@ -57,8 +59,6 @@ export const MultipleRecordPicker = ({
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission();
|
||||
|
||||
const resetState = useRecoilCallback(
|
||||
({ set }) => {
|
||||
return () => {
|
||||
@@ -106,8 +106,12 @@ export const MultipleRecordPicker = ({
|
||||
[multipleRecordPickerSearchFilterState, onCreate],
|
||||
);
|
||||
|
||||
const hasCreatePermissionOnObjectForCreate = useObjectPermissionsForObject(
|
||||
objectMetadataItemIdForCreate ?? '',
|
||||
).canUpdateObjectRecords;
|
||||
|
||||
const createNewButtonSection =
|
||||
isDefined(onCreate) && !hasObjectReadOnlyPermission ? (
|
||||
isDefined(onCreate) && hasCreatePermissionOnObjectForCreate ? (
|
||||
<DropdownMenuItemsContainer scrollable={false}>
|
||||
<CreateNewButton
|
||||
onClick={handleCreateNewButtonClick}
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { PermissionsOnAllObjectRecords } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useHasObjectReadOnlyPermission = () => {
|
||||
const currentUserWorkspace = useRecoilValue(currentUserWorkspaceState);
|
||||
|
||||
if (!isDefined(currentUserWorkspace?.objectRecordsPermissions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentUserWorkspace?.objectRecordsPermissions.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
currentUserWorkspace?.objectRecordsPermissions.length === 1 &&
|
||||
currentUserWorkspace?.objectRecordsPermissions.includes(
|
||||
PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS,
|
||||
)
|
||||
);
|
||||
};
|
||||
+8
@@ -60,6 +60,10 @@ describe('FieldPermissionService', () => {
|
||||
canUpdate: true,
|
||||
canSoftDelete: false,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: false,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
[fieldRelationMock.objectMetadataId]: {
|
||||
@@ -67,6 +71,10 @@ describe('FieldPermissionService', () => {
|
||||
canUpdate: true,
|
||||
canSoftDelete: false,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: false,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -86,6 +86,7 @@ export class PermissionsService {
|
||||
});
|
||||
|
||||
const objectPermissions = rolesPermissions[roleOfUserWorkspace.id] ?? {};
|
||||
const objectsPermissions = rolesPermissions[roleOfUserWorkspace.id] ?? {};
|
||||
|
||||
const objectRecordsPermissions: UserWorkspacePermissions['objectRecordsPermissions'] =
|
||||
{
|
||||
@@ -103,6 +104,7 @@ export class PermissionsService {
|
||||
permissionFlags,
|
||||
objectRecordsPermissions,
|
||||
objectPermissions,
|
||||
objectsPermissions,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,6 +130,7 @@ export class PermissionsService {
|
||||
[PermissionFlagType.EXPORT_CSV]: false,
|
||||
},
|
||||
objectPermissions: {},
|
||||
objectsPermissions: {},
|
||||
}) as const satisfies UserWorkspacePermissions;
|
||||
|
||||
public async userHasWorkspaceSettingPermission({
|
||||
|
||||
+5
-1
@@ -1,5 +1,8 @@
|
||||
import { type PermissionsOnAllObjectRecords } from 'twenty-shared/constants';
|
||||
import { type ObjectsPermissionsDeprecated } from 'twenty-shared/types';
|
||||
import {
|
||||
type ObjectsPermissions,
|
||||
type ObjectsPermissionsDeprecated,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
|
||||
|
||||
@@ -7,4 +10,5 @@ export type UserWorkspacePermissions = {
|
||||
permissionFlags: Record<PermissionFlagType, boolean>;
|
||||
objectRecordsPermissions: Record<PermissionsOnAllObjectRecords, boolean>;
|
||||
objectPermissions: ObjectsPermissionsDeprecated;
|
||||
objectsPermissions: ObjectsPermissions; // replaces ObjectsPermissionsDeprecated - deprecation ongoing
|
||||
};
|
||||
|
||||
+7
-1
@@ -2,6 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import {
|
||||
ObjectsPermissions,
|
||||
type ObjectsPermissionsByRoleIdDeprecated,
|
||||
type ObjectsPermissionsDeprecated,
|
||||
type RestrictedFieldsPermissions,
|
||||
@@ -190,7 +191,8 @@ export class WorkspacePermissionsCacheService {
|
||||
const permissionsByRoleId: ObjectsPermissionsByRoleIdDeprecated = {};
|
||||
|
||||
for (const role of roles) {
|
||||
const objectRecordsPermissions: ObjectsPermissionsDeprecated = {};
|
||||
const objectRecordsPermissions: ObjectsPermissionsDeprecated &
|
||||
ObjectsPermissions = {};
|
||||
|
||||
for (const objectMetadata of workspaceObjectMetadataCollection) {
|
||||
const { id: objectMetadataId, isSystem, standardId } = objectMetadata;
|
||||
@@ -270,6 +272,10 @@ export class WorkspacePermissionsCacheService {
|
||||
canUpdate,
|
||||
canSoftDelete,
|
||||
canDestroy,
|
||||
canReadObjectRecords: canRead,
|
||||
canUpdateObjectRecords: canUpdate,
|
||||
canSoftDeleteObjectRecords: canSoftDelete,
|
||||
canDestroyObjectRecords: canDestroy,
|
||||
restrictedFields,
|
||||
};
|
||||
|
||||
|
||||
+20
@@ -47,6 +47,10 @@ describe('AgentToolGeneratorService Integration', () => {
|
||||
canUpdate: true,
|
||||
canSoftDelete: true,
|
||||
canDestroy: true,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: true,
|
||||
canDestroyObjectRecords: true,
|
||||
restrictedFields: {},
|
||||
},
|
||||
},
|
||||
@@ -93,6 +97,10 @@ describe('AgentToolGeneratorService Integration', () => {
|
||||
canUpdate: false,
|
||||
canSoftDelete: false,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: false,
|
||||
canSoftDeleteObjectRecords: false,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
},
|
||||
@@ -158,6 +166,10 @@ describe('AgentToolGeneratorService Integration', () => {
|
||||
canUpdate: true,
|
||||
canSoftDelete: true,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: true,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
},
|
||||
@@ -766,6 +778,10 @@ describe('AgentToolGeneratorService Integration', () => {
|
||||
canUpdate: true,
|
||||
canSoftDelete: false,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: false,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
[secondObjectMetadata.id]: {
|
||||
@@ -773,6 +789,10 @@ describe('AgentToolGeneratorService Integration', () => {
|
||||
canUpdate: false,
|
||||
canSoftDelete: true,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: false,
|
||||
canSoftDeleteObjectRecords: true,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
},
|
||||
|
||||
+4
@@ -306,6 +306,10 @@ export const setupBasicPermissions = (context: AgentToolTestContext) => {
|
||||
canUpdate: true,
|
||||
canSoftDelete: true,
|
||||
canDestroy: false,
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: true,
|
||||
canDestroyObjectRecords: false,
|
||||
restrictedFields: {},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { type ObjectsPermissions } from '@/types/ObjectsPermissions';
|
||||
import { type ObjectsPermissionsDeprecated } from './ObjectsPermissionsDeprecated';
|
||||
|
||||
type RoleId = string;
|
||||
@@ -5,5 +6,5 @@ type RoleId = string;
|
||||
// TODO: DEPRECATE THIS
|
||||
export type ObjectsPermissionsByRoleIdDeprecated = Record<
|
||||
RoleId,
|
||||
ObjectsPermissionsDeprecated
|
||||
ObjectsPermissionsDeprecated & ObjectsPermissions
|
||||
>;
|
||||
|
||||
Reference in New Issue
Block a user