Row level permissions - POC 1 (#16599)
## Context This PR adds the core structure for RLS implementation: - RLS data model - RLS service layer - RLS WorkspaceMigration and Syncable Entity + cache + Validations - RLS resolver layer - ORM layer with RLS Predicate to ORM WHERE clause conversion with workspaceMember record transposition Tests are missing though <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Establishes core row-level permissions infrastructure and enforcement across the stack. > > - Backend: new `rowLevelPermissionPredicate` and `rowLevelPermissionPredicateGroup` entities, TypeORM migration, feature flag `IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED`, flat-entity maps/cache wiring, services and GraphQL resolvers for CRUD, and inclusion of `workspaceMember` in auth context > - ORM: applies row-level permission predicates to SELECT, DELETE, and SOFT DELETE query builders; propagates context through GlobalWorkspaceOrmManager/EntityManager > - GraphQL: generated schema/types/queries/mutations for creating/updating/deleting/fetching predicates and groups > - Frontend: settings page adds a gated "Record-level" section (placeholder) and metadata error handler labels for new entities > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fe955cc4588a92157afa6795fb574189a4be1e93. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
+1
@@ -6,6 +6,7 @@ interface AuthContextWithDefinedWorkspaceProperties {
|
||||
workspace: NonNullable<AuthContext['workspace']>;
|
||||
workspaceMetadataVersion?: string;
|
||||
workspaceMemberId: AuthContext['workspaceMemberId'];
|
||||
workspaceMember: AuthContext['workspaceMember'];
|
||||
userWorkspaceId: AuthContext['userWorkspaceId'];
|
||||
apiKey: AuthContext['apiKey'];
|
||||
}
|
||||
|
||||
+2
@@ -19,6 +19,7 @@ export const createQueryRunnerContext = ({
|
||||
userWorkspace,
|
||||
authProvider,
|
||||
impersonationContext,
|
||||
workspaceMember,
|
||||
} = request;
|
||||
|
||||
return {
|
||||
@@ -32,6 +33,7 @@ export const createQueryRunnerContext = ({
|
||||
userWorkspace,
|
||||
authProvider,
|
||||
impersonationContext,
|
||||
workspaceMember,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
+36
-2
@@ -23,6 +23,8 @@ describe('JwtAuthStrategy', () => {
|
||||
let applicationRepository: any;
|
||||
let jwtWrapperService: any;
|
||||
let permissionsService: any;
|
||||
let globalWorkspaceOrmManager: any;
|
||||
let workspaceMemberRepository: any;
|
||||
|
||||
const jwt = {
|
||||
sub: 'sub-default',
|
||||
@@ -57,6 +59,20 @@ describe('JwtAuthStrategy', () => {
|
||||
permissionsService = {
|
||||
userHasWorkspaceSettingPermission: jest.fn(),
|
||||
};
|
||||
|
||||
workspaceMemberRepository = {
|
||||
findOne: jest.fn(),
|
||||
};
|
||||
workspaceMemberRepository.findOne.mockResolvedValue({
|
||||
id: 'workspace-member-id',
|
||||
});
|
||||
|
||||
globalWorkspaceOrmManager = {
|
||||
executeInWorkspaceContext: jest.fn(async (_authContext, callback) => {
|
||||
return await callback();
|
||||
}),
|
||||
getRepository: jest.fn(async () => workspaceMemberRepository),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -80,6 +96,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -111,6 +128,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -145,6 +163,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -179,6 +198,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
const result = await strategy.validate(payload as JwtPayload);
|
||||
@@ -220,10 +240,11 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
new AuthException('UserWorkspaceEntity not found', expect.any(String), {
|
||||
new AuthException('User not found', expect.any(String), {
|
||||
userFriendlyMessage: msg`User does not have access to this workspace.`,
|
||||
}),
|
||||
);
|
||||
@@ -231,7 +252,7 @@ describe('JwtAuthStrategy', () => {
|
||||
try {
|
||||
await strategy.validate(payload as JwtPayload);
|
||||
} catch (e) {
|
||||
expect(e.code).toBe(AuthExceptionCode.USER_WORKSPACE_NOT_FOUND);
|
||||
expect(e.code).toBe(AuthExceptionCode.USER_NOT_FOUND);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -261,6 +282,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -306,6 +328,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
const user = await strategy.validate(payload as JwtPayload);
|
||||
@@ -339,6 +362,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -392,6 +416,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -438,6 +463,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -486,6 +512,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -545,6 +572,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -599,6 +627,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -670,6 +699,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -740,6 +770,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -811,6 +842,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
await expect(strategy.validate(payload as JwtPayload)).rejects.toThrow(
|
||||
@@ -875,6 +907,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
const result = await strategy.validate(payload as JwtPayload);
|
||||
@@ -941,6 +974,7 @@ describe('JwtAuthStrategy', () => {
|
||||
userWorkspaceRepository,
|
||||
apiKeyRepository,
|
||||
permissionsService,
|
||||
globalWorkspaceOrmManager,
|
||||
);
|
||||
|
||||
const result = await strategy.validate(payload as JwtPayload);
|
||||
|
||||
+59
-4
@@ -4,11 +4,13 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { Strategy } from 'passport-jwt';
|
||||
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
@@ -29,7 +31,9 @@ import { UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { userValidator } from 'src/engine/core-modules/user/user.validate';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
|
||||
@@ -46,6 +50,7 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
|
||||
@InjectRepository(ApiKeyEntity)
|
||||
private readonly apiKeyRepository: Repository<ApiKeyEntity>,
|
||||
private readonly permissionsService: PermissionsService,
|
||||
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
) {
|
||||
const jwtFromRequestFunction = jwtWrapperService.extractJwtFromRequest();
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
@@ -146,6 +151,13 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
|
||||
where: { id: userId },
|
||||
});
|
||||
|
||||
if (!isDefined(user)) {
|
||||
throw new AuthException(
|
||||
'User not found',
|
||||
AuthExceptionCode.USER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
if (!payload.userWorkspaceId) {
|
||||
throw new AuthException(
|
||||
'UserWorkspaceEntity not found',
|
||||
@@ -179,7 +191,50 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
|
||||
workspaceMemberId: payload.workspaceMemberId,
|
||||
};
|
||||
|
||||
return context;
|
||||
if (
|
||||
workspace.activationStatus ===
|
||||
WorkspaceActivationStatus.PENDING_CREATION ||
|
||||
workspace.activationStatus === WorkspaceActivationStatus.ONGOING_CREATION
|
||||
) {
|
||||
return context;
|
||||
}
|
||||
|
||||
const workspaceMember =
|
||||
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
buildSystemAuthContext(workspace.id),
|
||||
async () => {
|
||||
const workspaceMemberRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOne({
|
||||
where: {
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
assertIsDefinedOrThrow(
|
||||
workspaceMember,
|
||||
new AuthException(
|
||||
'User is not a member of the workspace',
|
||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||
{
|
||||
userFriendlyMessage: msg`User is not a member of the workspace.`,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return workspaceMember;
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
...context,
|
||||
workspaceMember,
|
||||
};
|
||||
}
|
||||
|
||||
private async validateImpersonation(payload: AccessTokenJwtPayload) {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { type ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { type AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
export type AuthContext = {
|
||||
user?: UserEntity | null | undefined;
|
||||
apiKey?: ApiKeyEntity | null | undefined;
|
||||
workspaceMemberId?: string;
|
||||
workspaceMember?: WorkspaceMemberWorkspaceEntity;
|
||||
workspace?: WorkspaceEntity;
|
||||
application?: ApplicationEntity | null | undefined;
|
||||
userWorkspaceId?: string;
|
||||
|
||||
@@ -60,6 +60,7 @@ import { AiModelsModule } from 'src/engine/metadata-modules/ai/ai-models/ai-mode
|
||||
import { FlatPageLayoutTabModule } from 'src/engine/metadata-modules/flat-page-layout-tab/flat-page-layout-tab.module';
|
||||
import { PageLayoutModule } from 'src/engine/metadata-modules/page-layout/page-layout.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { RowLevelPermissionModule } from 'src/engine/metadata-modules/row-level-permission-predicate/row-level-permission.module';
|
||||
import { SubscriptionsModule } from 'src/engine/subscriptions/subscriptions.module';
|
||||
import { TrashCleanupModule } from 'src/engine/trash-cleanup/trash-cleanup.module';
|
||||
import { WorkspaceEventEmitterModule } from 'src/engine/workspace-event-emitter/workspace-event-emitter.module';
|
||||
@@ -81,6 +82,7 @@ import { FileModule } from './file/file.module';
|
||||
ClientConfigModule,
|
||||
FeatureFlagModule,
|
||||
FileModule,
|
||||
RowLevelPermissionModule,
|
||||
OpenApiModule,
|
||||
ApplicationModule,
|
||||
ApplicationSyncModule,
|
||||
@@ -150,6 +152,7 @@ import { FileModule } from './file/file.module';
|
||||
ImpersonationModule,
|
||||
TrashCleanupModule,
|
||||
DashboardModule,
|
||||
RowLevelPermissionModule,
|
||||
],
|
||||
exports: [
|
||||
AuditModule,
|
||||
|
||||
+1
@@ -14,5 +14,6 @@ export enum FeatureFlagKey {
|
||||
IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED',
|
||||
IS_TIMELINE_ACTIVITY_MIGRATED = 'IS_TIMELINE_ACTIVITY_MIGRATED',
|
||||
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED = 'IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED',
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED',
|
||||
IS_WORKSPACE_CREATION_V2_ENABLED = 'IS_WORKSPACE_CREATION_V2_ENABLED',
|
||||
}
|
||||
|
||||
+16
@@ -11,6 +11,8 @@ import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata
|
||||
import { FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout/constants/flat-page-layout-editable-properties.constant';
|
||||
import { FLAT_ROLE_TARGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role-target/constants/flat-role-target-editable-properties.constant';
|
||||
import { FLAT_ROLE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role/constants/flat-role-editable-properties.constant';
|
||||
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
|
||||
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-editable-properties.constant';
|
||||
import { FLAT_VIEW_FIELD_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-editable-properties.constant';
|
||||
import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant';
|
||||
import { FLAT_VIEW_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-group/constants/flat-view-group-editable-properties.constant';
|
||||
@@ -132,6 +134,20 @@ export const ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY = {
|
||||
],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
rowLevelPermissionPredicate: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: ['value'],
|
||||
},
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
propertiesToCompare: [
|
||||
...FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES,
|
||||
'deletedAt',
|
||||
],
|
||||
propertiesToStringify: [],
|
||||
},
|
||||
} as const satisfies {
|
||||
[P in AllMetadataName]: OneFlatEntityConfiguration<P>;
|
||||
};
|
||||
|
||||
+2
@@ -122,4 +122,6 @@ export const ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY = {
|
||||
flatEntityForeignKeyAggregator: 'tabIds',
|
||||
},
|
||||
},
|
||||
rowLevelPermissionPredicate: {},
|
||||
rowLevelPermissionPredicateGroup: {},
|
||||
} as const satisfies MetadataNameAndRelations;
|
||||
|
||||
+17
@@ -126,6 +126,23 @@ export const ALL_METADATA_RELATION_PROPERTIES = {
|
||||
objectMetadata: true,
|
||||
application: true,
|
||||
},
|
||||
rowLevelPermissionPredicate: {
|
||||
workspace: true,
|
||||
role: true,
|
||||
fieldMetadata: true,
|
||||
workspaceMemberFieldMetadata: true,
|
||||
objectMetadata: true,
|
||||
rowLevelPermissionPredicateGroup: true,
|
||||
application: true,
|
||||
},
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
workspace: true,
|
||||
role: true,
|
||||
parentRowLevelPermissionPredicateGroup: true,
|
||||
childRowLevelPermissionPredicateGroups: true,
|
||||
rowLevelPermissionPredicates: true,
|
||||
application: true,
|
||||
},
|
||||
} as const satisfies {
|
||||
[TName in AllMetadataName]: {
|
||||
[P in ExtractEntityRelatedEntityProperties<MetadataEntity<TName>>]: true;
|
||||
|
||||
+9
@@ -64,4 +64,13 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
|
||||
pageLayoutWidget: {
|
||||
pageLayoutTab: true,
|
||||
},
|
||||
rowLevelPermissionPredicate: {
|
||||
fieldMetadata: true,
|
||||
objectMetadata: true,
|
||||
role: true,
|
||||
rowLevelPermissionPredicateGroup: true,
|
||||
},
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
role: true,
|
||||
},
|
||||
} as const satisfies MetadataRequiredForValidation;
|
||||
|
||||
+10
@@ -9,6 +9,8 @@ import { WorkspaceFlatObjectMetadataMapCacheService } from 'src/engine/metadata-
|
||||
import { WorkspaceFlatPageLayoutTabMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-tab/services/workspace-flat-page-layout-tab-map-cache.service';
|
||||
import { WorkspaceFlatPageLayoutWidgetMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service';
|
||||
import { WorkspaceFlatPageLayoutMapCacheService } from 'src/engine/metadata-modules/flat-page-layout/services/workspace-flat-page-layout-map-cache.service';
|
||||
import { WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/services/workspace-flat-row-level-permission-predicate-group-map-cache.service';
|
||||
import { WorkspaceFlatRowLevelPermissionPredicateMapCacheService } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/services/workspace-flat-row-level-permission-predicate-map-cache.service';
|
||||
import { WorkspaceFlatViewFieldMapCacheService } from 'src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service';
|
||||
import { WorkspaceFlatViewFilterMapCacheService } from 'src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service';
|
||||
import { WorkspaceFlatViewGroupMapCacheService } from 'src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service';
|
||||
@@ -19,6 +21,8 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
|
||||
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
|
||||
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
|
||||
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
@@ -40,6 +44,8 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
PageLayoutEntity,
|
||||
PageLayoutTabEntity,
|
||||
PageLayoutWidgetEntity,
|
||||
RowLevelPermissionPredicateEntity,
|
||||
RowLevelPermissionPredicateGroupEntity,
|
||||
]),
|
||||
],
|
||||
providers: [
|
||||
@@ -54,6 +60,8 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
WorkspaceFlatPageLayoutMapCacheService,
|
||||
WorkspaceFlatPageLayoutTabMapCacheService,
|
||||
WorkspaceFlatPageLayoutWidgetMapCacheService,
|
||||
WorkspaceFlatRowLevelPermissionPredicateMapCacheService,
|
||||
WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService,
|
||||
],
|
||||
exports: [
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
@@ -67,6 +75,8 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
WorkspaceFlatPageLayoutMapCacheService,
|
||||
WorkspaceFlatPageLayoutTabMapCacheService,
|
||||
WorkspaceFlatPageLayoutWidgetMapCacheService,
|
||||
WorkspaceFlatRowLevelPermissionPredicateMapCacheService,
|
||||
WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService,
|
||||
],
|
||||
})
|
||||
export class WorkspaceManyOrAllFlatEntityMapsCacheModule {}
|
||||
|
||||
+42
-7
@@ -8,9 +8,9 @@ import { type FlatAgent } from 'src/engine/metadata-modules/flat-agent/types/fla
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
@@ -19,13 +19,17 @@ import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
|
||||
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
|
||||
import { type PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { type RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { type RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { type RouteTriggerEntity } from 'src/engine/metadata-modules/route-trigger/route-trigger.entity';
|
||||
import { type FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger/types/flat-route-trigger.type';
|
||||
import { type RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { type RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
|
||||
import { type ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
@@ -61,11 +65,6 @@ import {
|
||||
type DeleteObjectAction,
|
||||
type UpdateObjectAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/types/workspace-migration-object-action-v2';
|
||||
import {
|
||||
type CreatePageLayoutAction,
|
||||
type DeletePageLayoutAction,
|
||||
type UpdatePageLayoutAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout/types/workspace-migration-page-layout-action-v2.type';
|
||||
import {
|
||||
type CreatePageLayoutTabAction,
|
||||
type DeletePageLayoutTabAction,
|
||||
@@ -76,6 +75,11 @@ import {
|
||||
type DeletePageLayoutWidgetAction,
|
||||
type UpdatePageLayoutWidgetAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action-v2.type';
|
||||
import {
|
||||
type CreatePageLayoutAction,
|
||||
type DeletePageLayoutAction,
|
||||
type UpdatePageLayoutAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout/types/workspace-migration-page-layout-action-v2.type';
|
||||
import {
|
||||
type CreateRoleTargetAction,
|
||||
type DeleteRoleTargetAction,
|
||||
@@ -91,6 +95,17 @@ import {
|
||||
type DeleteRouteTriggerAction,
|
||||
type UpdateRouteTriggerAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/types/workspace-migration-route-trigger-action-v2.type';
|
||||
import {
|
||||
type CreateRowLevelPermissionPredicateGroupAction,
|
||||
type DeleteRowLevelPermissionPredicateGroupAction,
|
||||
type UpdateRowLevelPermissionPredicateGroupAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action-v2.type';
|
||||
import {
|
||||
type CreateRowLevelPermissionPredicateAction,
|
||||
type DeleteRowLevelPermissionPredicateAction,
|
||||
type DestroyRowLevelPermissionPredicateAction,
|
||||
type UpdateRowLevelPermissionPredicateAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action-v2.type';
|
||||
import {
|
||||
type CreateServerlessFunctionAction,
|
||||
type DeleteServerlessFunctionAction,
|
||||
@@ -163,6 +178,26 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
flatEntity: FlatViewGroup;
|
||||
entity: ViewGroupEntity;
|
||||
};
|
||||
rowLevelPermissionPredicate: {
|
||||
actions: {
|
||||
created: CreateRowLevelPermissionPredicateAction;
|
||||
updated: UpdateRowLevelPermissionPredicateAction;
|
||||
deleted:
|
||||
| DeleteRowLevelPermissionPredicateAction
|
||||
| DestroyRowLevelPermissionPredicateAction;
|
||||
};
|
||||
flatEntity: FlatRowLevelPermissionPredicate;
|
||||
entity: RowLevelPermissionPredicateEntity;
|
||||
};
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
actions: {
|
||||
created: CreateRowLevelPermissionPredicateGroupAction;
|
||||
updated: UpdateRowLevelPermissionPredicateGroupAction;
|
||||
deleted: DeleteRowLevelPermissionPredicateGroupAction;
|
||||
};
|
||||
flatEntity: FlatRowLevelPermissionPredicateGroup;
|
||||
entity: RowLevelPermissionPredicateGroupEntity;
|
||||
};
|
||||
index: {
|
||||
actions: {
|
||||
created: CreateIndexAction;
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export const FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES = [
|
||||
'logicalOperator',
|
||||
'positionInRowLevelPermissionPredicateGroup',
|
||||
'parentRowLevelPermissionPredicateGroupId',
|
||||
] as const satisfies (keyof FlatRowLevelPermissionPredicateGroup)[];
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate-group.input';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export const fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate =
|
||||
({
|
||||
createRowLevelPermissionPredicateGroupInput:
|
||||
rawCreateRowLevelPermissionPredicateGroupInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createRowLevelPermissionPredicateGroupInput: CreateRowLevelPermissionPredicateGroupInput;
|
||||
workspaceId: string;
|
||||
}): FlatRowLevelPermissionPredicateGroup => {
|
||||
const sanitizedInput = (
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties as unknown as (
|
||||
input: CreateRowLevelPermissionPredicateGroupInput,
|
||||
keys: string[],
|
||||
) => CreateRowLevelPermissionPredicateGroupInput
|
||||
)(rawCreateRowLevelPermissionPredicateGroupInput, [
|
||||
'roleId',
|
||||
'parentRowLevelPermissionPredicateGroupId',
|
||||
'logicalOperator',
|
||||
]);
|
||||
|
||||
const { roleId, ...createRowLevelPermissionPredicateGroupInput } =
|
||||
sanitizedInput;
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
const predicateGroupId = v4();
|
||||
|
||||
return {
|
||||
id: predicateGroupId,
|
||||
workspaceId,
|
||||
roleId,
|
||||
childRowLevelPermissionPredicateGroupIds: [],
|
||||
rowLevelPermissionPredicateIds: [],
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: predicateGroupId,
|
||||
parentRowLevelPermissionPredicateGroupId:
|
||||
createRowLevelPermissionPredicateGroupInput.parentRowLevelPermissionPredicateGroupId ??
|
||||
null,
|
||||
logicalOperator:
|
||||
createRowLevelPermissionPredicateGroupInput.logicalOperator,
|
||||
positionInRowLevelPermissionPredicateGroup:
|
||||
createRowLevelPermissionPredicateGroupInput.positionInRowLevelPermissionPredicateGroup ??
|
||||
null,
|
||||
applicationId: null,
|
||||
};
|
||||
};
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type DeleteRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate-group.input';
|
||||
import {
|
||||
RowLevelPermissionPredicateGroupException,
|
||||
RowLevelPermissionPredicateGroupExceptionCode,
|
||||
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export const fromDeleteRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow =
|
||||
({
|
||||
deleteRowLevelPermissionPredicateGroupInput:
|
||||
rawDeleteRowLevelPermissionPredicateGroupInput,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
}: {
|
||||
deleteRowLevelPermissionPredicateGroupInput: DeleteRowLevelPermissionPredicateGroupInput;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
}): FlatRowLevelPermissionPredicateGroup => {
|
||||
const { id: predicateGroupId } = extractAndSanitizeObjectStringFields(
|
||||
rawDeleteRowLevelPermissionPredicateGroupInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPredicateGroup =
|
||||
flatRowLevelPermissionPredicateGroupMaps.byId[predicateGroupId];
|
||||
|
||||
if (!isDefined(existingFlatPredicateGroup)) {
|
||||
throw new RowLevelPermissionPredicateGroupException(
|
||||
t`Row level permission predicate group to delete not found`,
|
||||
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatPredicateGroup,
|
||||
deletedAt: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type DestroyRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate-group.input';
|
||||
import {
|
||||
RowLevelPermissionPredicateGroupException,
|
||||
RowLevelPermissionPredicateGroupExceptionCode,
|
||||
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export const fromDestroyRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow =
|
||||
({
|
||||
destroyRowLevelPermissionPredicateGroupInput:
|
||||
rawDestroyRowLevelPermissionPredicateGroupInput,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
}: {
|
||||
destroyRowLevelPermissionPredicateGroupInput: DestroyRowLevelPermissionPredicateGroupInput;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
}): FlatRowLevelPermissionPredicateGroup => {
|
||||
const { id: predicateGroupId } = extractAndSanitizeObjectStringFields(
|
||||
rawDestroyRowLevelPermissionPredicateGroupInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPredicateGroup =
|
||||
flatRowLevelPermissionPredicateGroupMaps.byId[predicateGroupId];
|
||||
|
||||
if (!isDefined(existingFlatPredicateGroup)) {
|
||||
throw new RowLevelPermissionPredicateGroupException(
|
||||
t`Row level permission predicate group to destroy not found`,
|
||||
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatPredicateGroup;
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export const fromFlatRowLevelPermissionPredicateGroupToDto = (
|
||||
flatGroup: FlatRowLevelPermissionPredicateGroup,
|
||||
): RowLevelPermissionPredicateGroupDTO => ({
|
||||
...flatGroup,
|
||||
});
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
|
||||
import { type UpdateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate-group.input';
|
||||
import {
|
||||
RowLevelPermissionPredicateGroupException,
|
||||
RowLevelPermissionPredicateGroupExceptionCode,
|
||||
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
export const fromUpdateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToUpdateOrThrow =
|
||||
({
|
||||
updateRowLevelPermissionPredicateGroupInput:
|
||||
rawUpdateRowLevelPermissionPredicateGroupInput,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
}: {
|
||||
updateRowLevelPermissionPredicateGroupInput: UpdateRowLevelPermissionPredicateGroupInput;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
}): FlatRowLevelPermissionPredicateGroup => {
|
||||
const { id: predicateGroupId } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawUpdateRowLevelPermissionPredicateGroupInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPredicateGroup =
|
||||
flatRowLevelPermissionPredicateGroupMaps.byId[predicateGroupId];
|
||||
|
||||
if (!isDefined(existingFlatPredicateGroup)) {
|
||||
throw new RowLevelPermissionPredicateGroupException(
|
||||
t`Row level permission predicate group to update not found`,
|
||||
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const sanitizedUpdate = extractAndSanitizeObjectStringFields(
|
||||
rawUpdateRowLevelPermissionPredicateGroupInput,
|
||||
FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
existing: existingFlatPredicateGroup,
|
||||
properties: FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES,
|
||||
update: sanitizedUpdate,
|
||||
});
|
||||
};
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export const FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES = [
|
||||
'operand',
|
||||
'value',
|
||||
'rowLevelPermissionPredicateGroupId',
|
||||
'positionInRowLevelPermissionPredicateGroup',
|
||||
'subFieldName',
|
||||
'workspaceMemberFieldMetadataId',
|
||||
'workspaceMemberSubFieldName',
|
||||
] as const satisfies (keyof FlatRowLevelPermissionPredicate)[];
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export const ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES = [
|
||||
'workspace',
|
||||
'role',
|
||||
'fieldMetadata',
|
||||
'workspaceMemberFieldMetadata',
|
||||
'objectMetadata',
|
||||
'rowLevelPermissionPredicateGroup',
|
||||
'application',
|
||||
] as const;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export const ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES = [
|
||||
'workspace',
|
||||
'role',
|
||||
'parentRowLevelPermissionPredicateGroup',
|
||||
'childRowLevelPermissionPredicateGroups',
|
||||
'rowLevelPermissionPredicates',
|
||||
'application',
|
||||
] as const;
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { fromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-row-level-permission-predicate-group-entity-to-flat-row-level-permission-predicate-group.util';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceCache('flatRowLevelPermissionPredicateGroupMaps')
|
||||
export class WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService extends WorkspaceCacheProvider<FlatRowLevelPermissionPredicateGroupMaps> {
|
||||
constructor(
|
||||
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
|
||||
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async computeForCache(
|
||||
workspaceId: string,
|
||||
): Promise<FlatRowLevelPermissionPredicateGroupMaps> {
|
||||
const rowLevelPermissionPredicateGroups =
|
||||
await this.rowLevelPermissionPredicateGroupRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
const flatRowLevelPermissionPredicateGroupMaps =
|
||||
createEmptyFlatEntityMaps();
|
||||
|
||||
for (const rowLevelPermissionPredicateGroupEntity of rowLevelPermissionPredicateGroups) {
|
||||
const flatRowLevelPermissionPredicateGroup =
|
||||
fromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionPredicateGroup(
|
||||
rowLevelPermissionPredicateGroupEntity,
|
||||
);
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: flatRowLevelPermissionPredicateGroup,
|
||||
flatEntityMapsToMutate: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
}
|
||||
|
||||
return flatRowLevelPermissionPredicateGroupMaps;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { fromRowLevelPermissionPredicateEntityToFlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-row-level-permission-predicate-entity-to-flat-row-level-permission-predicate.util';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceCache('flatRowLevelPermissionPredicateMaps')
|
||||
export class WorkspaceFlatRowLevelPermissionPredicateMapCacheService extends WorkspaceCacheProvider<FlatRowLevelPermissionPredicateMaps> {
|
||||
constructor(
|
||||
@InjectRepository(RowLevelPermissionPredicateEntity)
|
||||
private readonly rowLevelPermissionPredicateRepository: Repository<RowLevelPermissionPredicateEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async computeForCache(
|
||||
workspaceId: string,
|
||||
): Promise<FlatRowLevelPermissionPredicateMaps> {
|
||||
const rowLevelPermissionPredicates =
|
||||
await this.rowLevelPermissionPredicateRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
const flatRowLevelPermissionPredicateMaps = createEmptyFlatEntityMaps();
|
||||
|
||||
for (const rowLevelPermissionPredicateEntity of rowLevelPermissionPredicates) {
|
||||
const flatRowLevelPermissionPredicate =
|
||||
fromRowLevelPermissionPredicateEntityToFlatRowLevelPermissionPredicate(
|
||||
rowLevelPermissionPredicateEntity,
|
||||
);
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: flatRowLevelPermissionPredicate,
|
||||
flatEntityMapsToMutate: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
}
|
||||
|
||||
return flatRowLevelPermissionPredicateMaps;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate.input';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export const fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate =
|
||||
({
|
||||
createRowLevelPermissionPredicateInput:
|
||||
rawCreateRowLevelPermissionPredicateInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createRowLevelPermissionPredicateInput: CreateRowLevelPermissionPredicateInput;
|
||||
workspaceId: string;
|
||||
}): FlatRowLevelPermissionPredicate => {
|
||||
const sanitizedInput = (
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties as unknown as (
|
||||
input: CreateRowLevelPermissionPredicateInput,
|
||||
keys: string[],
|
||||
) => CreateRowLevelPermissionPredicateInput
|
||||
)(rawCreateRowLevelPermissionPredicateInput, [
|
||||
'fieldMetadataId',
|
||||
'objectMetadataId',
|
||||
'roleId',
|
||||
'rowLevelPermissionPredicateGroupId',
|
||||
'workspaceMemberFieldMetadataId',
|
||||
'subFieldName',
|
||||
'workspaceMemberSubFieldName',
|
||||
'operand',
|
||||
]);
|
||||
|
||||
const {
|
||||
fieldMetadataId,
|
||||
objectMetadataId,
|
||||
roleId,
|
||||
value,
|
||||
...createRowLevelPermissionPredicateInput
|
||||
} = sanitizedInput;
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
const predicateId = v4();
|
||||
|
||||
return {
|
||||
id: predicateId,
|
||||
fieldMetadataId,
|
||||
objectMetadataId,
|
||||
roleId,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: predicateId,
|
||||
operand: createRowLevelPermissionPredicateInput.operand,
|
||||
value: value,
|
||||
rowLevelPermissionPredicateGroupId:
|
||||
createRowLevelPermissionPredicateInput.rowLevelPermissionPredicateGroupId ??
|
||||
null,
|
||||
positionInRowLevelPermissionPredicateGroup:
|
||||
createRowLevelPermissionPredicateInput.positionInRowLevelPermissionPredicateGroup ??
|
||||
null,
|
||||
subFieldName: createRowLevelPermissionPredicateInput.subFieldName ?? null,
|
||||
workspaceMemberFieldMetadataId:
|
||||
createRowLevelPermissionPredicateInput.workspaceMemberFieldMetadataId ??
|
||||
null,
|
||||
workspaceMemberSubFieldName:
|
||||
createRowLevelPermissionPredicateInput.workspaceMemberSubFieldName ??
|
||||
null,
|
||||
applicationId: null,
|
||||
};
|
||||
};
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type DeleteRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate.input';
|
||||
import {
|
||||
RowLevelPermissionPredicateException,
|
||||
RowLevelPermissionPredicateExceptionCode,
|
||||
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export const fromDeleteRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow =
|
||||
({
|
||||
deleteRowLevelPermissionPredicateInput:
|
||||
rawDeleteRowLevelPermissionPredicateInput,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
}: {
|
||||
deleteRowLevelPermissionPredicateInput: DeleteRowLevelPermissionPredicateInput;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
}): FlatRowLevelPermissionPredicate => {
|
||||
const { id: predicateId } = extractAndSanitizeObjectStringFields(
|
||||
rawDeleteRowLevelPermissionPredicateInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPredicate =
|
||||
flatRowLevelPermissionPredicateMaps.byId[predicateId];
|
||||
|
||||
if (!isDefined(existingFlatPredicate)) {
|
||||
throw new RowLevelPermissionPredicateException(
|
||||
t`Row level permission predicate to delete not found`,
|
||||
RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatPredicate,
|
||||
deletedAt: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type DestroyRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate.input';
|
||||
import {
|
||||
RowLevelPermissionPredicateException,
|
||||
RowLevelPermissionPredicateExceptionCode,
|
||||
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export const fromDestroyRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow =
|
||||
({
|
||||
destroyRowLevelPermissionPredicateInput:
|
||||
rawDestroyRowLevelPermissionPredicateInput,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
}: {
|
||||
destroyRowLevelPermissionPredicateInput: DestroyRowLevelPermissionPredicateInput;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
}): FlatRowLevelPermissionPredicate => {
|
||||
const { id: predicateId } = extractAndSanitizeObjectStringFields(
|
||||
rawDestroyRowLevelPermissionPredicateInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPredicate =
|
||||
flatRowLevelPermissionPredicateMaps.byId[predicateId];
|
||||
|
||||
if (!isDefined(existingFlatPredicate)) {
|
||||
throw new RowLevelPermissionPredicateException(
|
||||
t`Row level permission predicate to destroy not found`,
|
||||
RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatPredicate;
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type RowLevelPermissionPredicateDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate.dto';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export const fromFlatRowLevelPermissionPredicateToDto = (
|
||||
flatPredicate: FlatRowLevelPermissionPredicate,
|
||||
): RowLevelPermissionPredicateDTO => ({
|
||||
...flatPredicate,
|
||||
});
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import { ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/row-level-permission-predicate-entity-relation-properties.constant';
|
||||
import { type RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export const fromRowLevelPermissionPredicateEntityToFlatRowLevelPermissionPredicate =
|
||||
(
|
||||
rowLevelPermissionPredicateEntity: RowLevelPermissionPredicateEntity,
|
||||
): FlatRowLevelPermissionPredicate => {
|
||||
const rowLevelPermissionPredicateEntityWithoutRelations =
|
||||
removePropertiesFromRecord(rowLevelPermissionPredicateEntity, [
|
||||
...ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES,
|
||||
] as (typeof ROW_LEVEL_PERMISSION_PREDICATE_ENTITY_RELATION_PROPERTIES)[number][]);
|
||||
|
||||
return {
|
||||
...rowLevelPermissionPredicateEntityWithoutRelations,
|
||||
createdAt: rowLevelPermissionPredicateEntity.createdAt.toISOString(),
|
||||
updatedAt: rowLevelPermissionPredicateEntity.updatedAt.toISOString(),
|
||||
deletedAt:
|
||||
rowLevelPermissionPredicateEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateEntityWithoutRelations.universalIdentifier ??
|
||||
rowLevelPermissionPredicateEntityWithoutRelations.id,
|
||||
};
|
||||
};
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import { ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/row-level-permission-predicate-group-entity-relation-properties.constant';
|
||||
import { type RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export const fromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionPredicateGroup =
|
||||
(
|
||||
rowLevelPermissionPredicateGroupEntity: RowLevelPermissionPredicateGroupEntity,
|
||||
): FlatRowLevelPermissionPredicateGroup => {
|
||||
const rowLevelPermissionPredicateGroupEntityWithoutRelations =
|
||||
removePropertiesFromRecord(rowLevelPermissionPredicateGroupEntity, [
|
||||
...ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES,
|
||||
] as (typeof ROW_LEVEL_PERMISSION_PREDICATE_GROUP_ENTITY_RELATION_PROPERTIES)[number][]);
|
||||
|
||||
return {
|
||||
...rowLevelPermissionPredicateGroupEntityWithoutRelations,
|
||||
createdAt: rowLevelPermissionPredicateGroupEntity.createdAt.toISOString(),
|
||||
updatedAt: rowLevelPermissionPredicateGroupEntity.updatedAt.toISOString(),
|
||||
deletedAt:
|
||||
rowLevelPermissionPredicateGroupEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateGroupEntityWithoutRelations.universalIdentifier ??
|
||||
rowLevelPermissionPredicateGroupEntityWithoutRelations.id,
|
||||
childRowLevelPermissionPredicateGroupIds:
|
||||
rowLevelPermissionPredicateGroupEntity.childRowLevelPermissionPredicateGroups.map(
|
||||
({ id }) => id,
|
||||
),
|
||||
rowLevelPermissionPredicateIds:
|
||||
rowLevelPermissionPredicateGroupEntity.rowLevelPermissionPredicates.map(
|
||||
({ id }) => id,
|
||||
),
|
||||
};
|
||||
};
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-editable-properties.constant';
|
||||
import { type UpdateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate.input';
|
||||
import {
|
||||
RowLevelPermissionPredicateException,
|
||||
RowLevelPermissionPredicateExceptionCode,
|
||||
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
export const fromUpdateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToUpdateOrThrow =
|
||||
({
|
||||
updateRowLevelPermissionPredicateInput:
|
||||
rawUpdateRowLevelPermissionPredicateInput,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
}: {
|
||||
updateRowLevelPermissionPredicateInput: UpdateRowLevelPermissionPredicateInput;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
}): FlatRowLevelPermissionPredicate => {
|
||||
const { id: predicateId } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawUpdateRowLevelPermissionPredicateInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPredicate =
|
||||
flatRowLevelPermissionPredicateMaps.byId[predicateId];
|
||||
|
||||
if (!isDefined(existingFlatPredicate)) {
|
||||
throw new RowLevelPermissionPredicateException(
|
||||
t`Row level permission predicate to update not found`,
|
||||
RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const sanitizedUpdate = extractAndSanitizeObjectStringFields(
|
||||
rawUpdateRowLevelPermissionPredicateInput,
|
||||
FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
existing: existingFlatPredicate,
|
||||
properties: FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES,
|
||||
update: sanitizedUpdate,
|
||||
});
|
||||
};
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
|
||||
|
||||
@InputType()
|
||||
export class CreateRowLevelPermissionPredicateGroupInput {
|
||||
@Field(() => String, { nullable: true })
|
||||
parentRowLevelPermissionPredicateGroupId?: string | null;
|
||||
|
||||
@Field(() => RowLevelPermissionPredicateGroupLogicalOperator)
|
||||
logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
positionInRowLevelPermissionPredicateGroup?: number | null;
|
||||
|
||||
@Field(() => String)
|
||||
roleId: string;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
|
||||
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
|
||||
|
||||
@InputType()
|
||||
export class CreateRowLevelPermissionPredicateInput {
|
||||
@Field(() => String)
|
||||
fieldMetadataId: string;
|
||||
|
||||
@Field(() => String)
|
||||
objectMetadataId: string;
|
||||
|
||||
@Field(() => RowLevelPermissionPredicateOperand)
|
||||
operand: RowLevelPermissionPredicateOperand;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
value: RowLevelPermissionPredicateValue | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
subFieldName?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
workspaceMemberFieldMetadataId?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
workspaceMemberSubFieldName?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
rowLevelPermissionPredicateGroupId?: string | null;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
positionInRowLevelPermissionPredicateGroup?: number | null;
|
||||
|
||||
@Field(() => String)
|
||||
roleId: string;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class DeleteRowLevelPermissionPredicateGroupInput {
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class DeleteRowLevelPermissionPredicateInput {
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@InputType()
|
||||
export class DestroyRowLevelPermissionPredicateGroupInput {
|
||||
@IDField(() => UUIDScalarType, {
|
||||
description:
|
||||
'The id of the row level permission predicate group to destroy.',
|
||||
})
|
||||
@IsUUID()
|
||||
id: string;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@InputType()
|
||||
export class DestroyRowLevelPermissionPredicateInput {
|
||||
@IDField(() => UUIDScalarType, {
|
||||
description: 'The id of the row level permission predicate to destroy.',
|
||||
})
|
||||
@IsUUID()
|
||||
id: string;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
|
||||
|
||||
@InputType()
|
||||
export class UpdateRowLevelPermissionPredicateGroupInput {
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
parentRowLevelPermissionPredicateGroupId?: string | null;
|
||||
|
||||
@Field(() => RowLevelPermissionPredicateGroupLogicalOperator, {
|
||||
nullable: true,
|
||||
})
|
||||
logicalOperator?: RowLevelPermissionPredicateGroupLogicalOperator;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
positionInRowLevelPermissionPredicateGroup?: number | null;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
|
||||
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
|
||||
|
||||
@InputType()
|
||||
export class UpdateRowLevelPermissionPredicateInput {
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
|
||||
@Field(() => RowLevelPermissionPredicateOperand, { nullable: true })
|
||||
operand?: RowLevelPermissionPredicateOperand;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
value?: RowLevelPermissionPredicateValue;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
subFieldName?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
workspaceMemberFieldMetadataId?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
workspaceMemberSubFieldName?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
rowLevelPermissionPredicateGroupId?: string | null;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
positionInRowLevelPermissionPredicateGroup?: number | null;
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
|
||||
|
||||
registerEnumType(RowLevelPermissionPredicateGroupLogicalOperator, {
|
||||
name: 'RowLevelPermissionPredicateGroupLogicalOperator',
|
||||
});
|
||||
@ObjectType('RowLevelPermissionPredicateGroup')
|
||||
export class RowLevelPermissionPredicateGroupDTO {
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
parentRowLevelPermissionPredicateGroupId?: string | null;
|
||||
|
||||
@Field(() => RowLevelPermissionPredicateGroupLogicalOperator)
|
||||
logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
positionInRowLevelPermissionPredicateGroup?: number | null;
|
||||
|
||||
@Field(() => String)
|
||||
roleId: string;
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
|
||||
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
|
||||
|
||||
registerEnumType(RowLevelPermissionPredicateOperand, {
|
||||
name: 'RowLevelPermissionPredicateOperand',
|
||||
});
|
||||
@ObjectType('RowLevelPermissionPredicate')
|
||||
export class RowLevelPermissionPredicateDTO {
|
||||
@Field(() => String)
|
||||
id: string;
|
||||
|
||||
@Field(() => String)
|
||||
fieldMetadataId: string;
|
||||
|
||||
@Field(() => String)
|
||||
objectMetadataId: string;
|
||||
|
||||
@Field(() => RowLevelPermissionPredicateOperand)
|
||||
operand: RowLevelPermissionPredicateOperand;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
subFieldName?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
workspaceMemberFieldMetadataId?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
workspaceMemberSubFieldName?: string | null;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
rowLevelPermissionPredicateGroupId?: string | null;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
positionInRowLevelPermissionPredicateGroup?: number | null;
|
||||
|
||||
@Field(() => String)
|
||||
roleId: string;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
value: RowLevelPermissionPredicateValue | null;
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
Relation,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/types/syncable-entity.interface';
|
||||
|
||||
@Entity({ name: 'rowLevelPermissionPredicateGroup', schema: 'core' })
|
||||
@Index('IDX_RLPPG_WORKSPACE_ID_ROLE_ID', ['workspaceId', 'roleId'])
|
||||
export class RowLevelPermissionPredicateGroupEntity
|
||||
extends SyncableEntity
|
||||
implements Required<RowLevelPermissionPredicateGroupEntity>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
parentRowLevelPermissionPredicateGroupId: string | null;
|
||||
|
||||
@Column({
|
||||
type: 'enum',
|
||||
enum: Object.values(RowLevelPermissionPredicateGroupLogicalOperator),
|
||||
nullable: false,
|
||||
default: RowLevelPermissionPredicateGroupLogicalOperator.AND,
|
||||
})
|
||||
logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator;
|
||||
|
||||
@Column({ nullable: true, type: 'double precision' })
|
||||
positionInRowLevelPermissionPredicateGroup: number | null;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
roleId: string;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt: Date | null;
|
||||
|
||||
@ManyToOne(() => RoleEntity, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'roleId' })
|
||||
role: Relation<RoleEntity>;
|
||||
|
||||
@ManyToOne(
|
||||
() => RowLevelPermissionPredicateGroupEntity,
|
||||
(rowLevelPermissionPredicateGroup) =>
|
||||
rowLevelPermissionPredicateGroup.childRowLevelPermissionPredicateGroups,
|
||||
{ onDelete: 'CASCADE' },
|
||||
)
|
||||
@JoinColumn({ name: 'parentRowLevelPermissionPredicateGroupId' })
|
||||
parentRowLevelPermissionPredicateGroup: Relation<RowLevelPermissionPredicateGroupEntity>;
|
||||
|
||||
@OneToMany(
|
||||
() => RowLevelPermissionPredicateGroupEntity,
|
||||
(rowLevelPermissionPredicateGroup) =>
|
||||
rowLevelPermissionPredicateGroup.parentRowLevelPermissionPredicateGroup,
|
||||
)
|
||||
childRowLevelPermissionPredicateGroups: Relation<RowLevelPermissionPredicateGroupEntity>[];
|
||||
|
||||
@OneToMany(
|
||||
() => RowLevelPermissionPredicateEntity,
|
||||
(predicate) => predicate.rowLevelPermissionPredicateGroup,
|
||||
)
|
||||
rowLevelPermissionPredicates: Relation<RowLevelPermissionPredicateEntity>[];
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
Relation,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
|
||||
import { type RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/types/syncable-entity.interface';
|
||||
|
||||
@Entity({ name: 'rowLevelPermissionPredicate', schema: 'core' })
|
||||
@Index('IDX_RLPP_WORKSPACE_ID_ROLE_ID_OBJECT_METADATA_ID', [
|
||||
'workspaceId',
|
||||
'roleId',
|
||||
'objectMetadataId',
|
||||
])
|
||||
@Index('IDX_RLPP_FIELD_METADATA_ID', ['fieldMetadataId'])
|
||||
@Index('IDX_RLPP_GROUP_ID', ['rowLevelPermissionPredicateGroupId'])
|
||||
export class RowLevelPermissionPredicateEntity
|
||||
extends SyncableEntity
|
||||
implements Required<RowLevelPermissionPredicateEntity>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
fieldMetadataId: string;
|
||||
|
||||
@ManyToOne(() => FieldMetadataEntity, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'fieldMetadataId' })
|
||||
fieldMetadata: Relation<FieldMetadataEntity>;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
objectMetadataId: string;
|
||||
|
||||
@ManyToOne(() => ObjectMetadataEntity, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'objectMetadataId' })
|
||||
objectMetadata: Relation<ObjectMetadataEntity>;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: 'enum',
|
||||
enum: Object.values(RowLevelPermissionPredicateOperand),
|
||||
default: RowLevelPermissionPredicateOperand.CONTAINS,
|
||||
})
|
||||
operand: RowLevelPermissionPredicateOperand;
|
||||
|
||||
@Column({ nullable: true, type: 'jsonb' })
|
||||
value: RowLevelPermissionPredicateValue | null;
|
||||
|
||||
@Column({ nullable: true, type: 'text', default: null })
|
||||
subFieldName: string | null;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
workspaceMemberFieldMetadataId: string | null;
|
||||
|
||||
@Column({ nullable: true, type: 'text', default: null })
|
||||
workspaceMemberSubFieldName: string | null;
|
||||
|
||||
@ManyToOne(() => FieldMetadataEntity, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn({ name: 'workspaceMemberFieldMetadataId' })
|
||||
workspaceMemberFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
rowLevelPermissionPredicateGroupId: string | null;
|
||||
|
||||
@Column({ nullable: true, type: 'double precision' })
|
||||
positionInRowLevelPermissionPredicateGroup: number | null;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
roleId: string;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt: Date | null;
|
||||
|
||||
@ManyToOne(() => RoleEntity, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'roleId' })
|
||||
role: Relation<RoleEntity>;
|
||||
|
||||
@ManyToOne(
|
||||
() => RowLevelPermissionPredicateGroupEntity,
|
||||
(rowLevelPermissionPredicateGroup) =>
|
||||
rowLevelPermissionPredicateGroup.rowLevelPermissionPredicates,
|
||||
{
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'rowLevelPermissionPredicateGroupId' })
|
||||
rowLevelPermissionPredicateGroup: Relation<RowLevelPermissionPredicateGroupEntity>;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export enum RowLevelPermissionPredicateGroupLogicalOperator {
|
||||
AND = 'AND',
|
||||
OR = 'OR',
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export enum RowLevelPermissionPredicateOperand {
|
||||
IS = 'IS',
|
||||
IS_NOT_NULL = 'IS_NOT_NULL',
|
||||
IS_NOT = 'IS_NOT',
|
||||
LESS_THAN_OR_EQUAL = 'LESS_THAN_OR_EQUAL',
|
||||
GREATER_THAN_OR_EQUAL = 'GREATER_THAN_OR_EQUAL',
|
||||
IS_BEFORE = 'IS_BEFORE',
|
||||
IS_AFTER = 'IS_AFTER',
|
||||
CONTAINS = 'CONTAINS',
|
||||
DOES_NOT_CONTAIN = 'DOES_NOT_CONTAIN',
|
||||
IS_EMPTY = 'IS_EMPTY',
|
||||
IS_NOT_EMPTY = 'IS_NOT_EMPTY',
|
||||
IS_RELATIVE = 'IS_RELATIVE',
|
||||
IS_IN_PAST = 'IS_IN_PAST',
|
||||
IS_IN_FUTURE = 'IS_IN_FUTURE',
|
||||
IS_TODAY = 'IS_TODAY',
|
||||
VECTOR_SEARCH = 'VECTOR_SEARCH',
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
|
||||
import {
|
||||
appendCommonExceptionCode,
|
||||
CustomException,
|
||||
} from 'src/utils/custom-exception';
|
||||
|
||||
export const RowLevelPermissionPredicateGroupExceptionCode =
|
||||
appendCommonExceptionCode({
|
||||
ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND:
|
||||
'ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND',
|
||||
INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA:
|
||||
'INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA',
|
||||
ROLE_NOT_FOUND: 'ROLE_NOT_FOUND',
|
||||
} as const);
|
||||
|
||||
const rowLevelPermissionPredicateGroupExceptionUserFriendlyMessages: Record<
|
||||
keyof typeof RowLevelPermissionPredicateGroupExceptionCode,
|
||||
MessageDescriptor
|
||||
> = {
|
||||
ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND: msg`Row level permission predicate group not found.`,
|
||||
INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA: msg`Invalid row level permission predicate group data.`,
|
||||
ROLE_NOT_FOUND: msg`Role not found.`,
|
||||
INTERNAL_SERVER_ERROR: msg`An unexpected error occurred.`,
|
||||
};
|
||||
|
||||
export class RowLevelPermissionPredicateGroupException extends CustomException<
|
||||
keyof typeof RowLevelPermissionPredicateGroupExceptionCode
|
||||
> {
|
||||
constructor(
|
||||
message: string,
|
||||
code: keyof typeof RowLevelPermissionPredicateGroupExceptionCode,
|
||||
{ userFriendlyMessage }: { userFriendlyMessage?: MessageDescriptor } = {},
|
||||
) {
|
||||
super(message, code, {
|
||||
userFriendlyMessage:
|
||||
userFriendlyMessage ??
|
||||
rowLevelPermissionPredicateGroupExceptionUserFriendlyMessages[code],
|
||||
});
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
|
||||
import {
|
||||
appendCommonExceptionCode,
|
||||
CustomException,
|
||||
} from 'src/utils/custom-exception';
|
||||
|
||||
export const RowLevelPermissionPredicateExceptionCode =
|
||||
appendCommonExceptionCode({
|
||||
ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND:
|
||||
'ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND',
|
||||
INVALID_ROW_LEVEL_PERMISSION_PREDICATE_DATA:
|
||||
'INVALID_ROW_LEVEL_PERMISSION_PREDICATE_DATA',
|
||||
FIELD_METADATA_NOT_FOUND: 'FIELD_METADATA_NOT_FOUND',
|
||||
OBJECT_METADATA_NOT_FOUND: 'OBJECT_METADATA_NOT_FOUND',
|
||||
ROLE_NOT_FOUND: 'ROLE_NOT_FOUND',
|
||||
} as const);
|
||||
|
||||
const rowLevelPermissionPredicateExceptionUserFriendlyMessages: Record<
|
||||
keyof typeof RowLevelPermissionPredicateExceptionCode,
|
||||
MessageDescriptor
|
||||
> = {
|
||||
ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND: msg`Row level permission predicate not found.`,
|
||||
INVALID_ROW_LEVEL_PERMISSION_PREDICATE_DATA: msg`Invalid row level permission predicate data.`,
|
||||
FIELD_METADATA_NOT_FOUND: msg`Field metadata not found.`,
|
||||
OBJECT_METADATA_NOT_FOUND: msg`Object metadata not found.`,
|
||||
ROLE_NOT_FOUND: msg`Role not found.`,
|
||||
INTERNAL_SERVER_ERROR: msg`An unexpected error occurred.`,
|
||||
};
|
||||
|
||||
export class RowLevelPermissionPredicateException extends CustomException<
|
||||
keyof typeof RowLevelPermissionPredicateExceptionCode
|
||||
> {
|
||||
constructor(
|
||||
message: string,
|
||||
code: keyof typeof RowLevelPermissionPredicateExceptionCode,
|
||||
{ userFriendlyMessage }: { userFriendlyMessage?: MessageDescriptor } = {},
|
||||
) {
|
||||
super(message, code, {
|
||||
userFriendlyMessage:
|
||||
userFriendlyMessage ??
|
||||
rowLevelPermissionPredicateExceptionUserFriendlyMessages[code],
|
||||
});
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate-group.input';
|
||||
import { DeleteRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate-group.input';
|
||||
import { UpdateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate-group.input';
|
||||
import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
|
||||
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
|
||||
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
|
||||
|
||||
@Resolver(() => RowLevelPermissionPredicateGroupDTO)
|
||||
@UseGuards(WorkspaceAuthGuard, NoPermissionGuard)
|
||||
export class RowLevelPermissionPredicateGroupResolver {
|
||||
constructor(
|
||||
private readonly predicateGroupService: RowLevelPermissionPredicateGroupService,
|
||||
) {}
|
||||
|
||||
@Query(() => [RowLevelPermissionPredicateGroupDTO])
|
||||
async getRowLevelPermissionPredicateGroups(
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('roleId', { type: () => String, nullable: true }) roleId?: string,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO[]> {
|
||||
if (roleId) {
|
||||
return this.predicateGroupService.findByRole(workspace.id, roleId);
|
||||
}
|
||||
|
||||
return this.predicateGroupService.findByWorkspaceId(workspace.id);
|
||||
}
|
||||
|
||||
@Mutation(() => RowLevelPermissionPredicateGroupDTO)
|
||||
async createRowLevelPermissionPredicateGroup(
|
||||
@Args('input')
|
||||
input: CreateRowLevelPermissionPredicateGroupInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
return this.predicateGroupService.createOne({
|
||||
createRowLevelPermissionPredicateGroupInput: {
|
||||
...input,
|
||||
logicalOperator:
|
||||
input.logicalOperator as RowLevelPermissionPredicateGroupLogicalOperator,
|
||||
},
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => RowLevelPermissionPredicateGroupDTO)
|
||||
async updateRowLevelPermissionPredicateGroup(
|
||||
@Args('input')
|
||||
input: UpdateRowLevelPermissionPredicateGroupInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
return this.predicateGroupService.updateOne({
|
||||
updateRowLevelPermissionPredicateGroupInput: {
|
||||
...input,
|
||||
logicalOperator:
|
||||
input.logicalOperator as RowLevelPermissionPredicateGroupLogicalOperator,
|
||||
},
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => RowLevelPermissionPredicateGroupDTO)
|
||||
async deleteRowLevelPermissionPredicateGroup(
|
||||
@Args('input')
|
||||
input: DeleteRowLevelPermissionPredicateGroupInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
return this.predicateGroupService.deleteOne({
|
||||
deleteRowLevelPermissionPredicateGroupInput: {
|
||||
...input,
|
||||
},
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate.input';
|
||||
import { DeleteRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate.input';
|
||||
import { UpdateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate.input';
|
||||
import { RowLevelPermissionPredicateDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate.dto';
|
||||
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
|
||||
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
|
||||
|
||||
@Resolver(() => RowLevelPermissionPredicateDTO)
|
||||
@UseGuards(WorkspaceAuthGuard, NoPermissionGuard)
|
||||
export class RowLevelPermissionPredicateResolver {
|
||||
constructor(
|
||||
private readonly predicateService: RowLevelPermissionPredicateService,
|
||||
) {}
|
||||
|
||||
@Query(() => [RowLevelPermissionPredicateDTO])
|
||||
async getRowLevelPermissionPredicates(
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('roleId', { type: () => String, nullable: true }) roleId?: string,
|
||||
@Args('objectMetadataId', { type: () => String, nullable: true })
|
||||
objectMetadataId?: string,
|
||||
): Promise<RowLevelPermissionPredicateDTO[]> {
|
||||
if (roleId && objectMetadataId) {
|
||||
return this.predicateService.findByRoleAndObject(
|
||||
workspace.id,
|
||||
roleId,
|
||||
objectMetadataId,
|
||||
);
|
||||
}
|
||||
|
||||
return this.predicateService.findByWorkspaceId(workspace.id);
|
||||
}
|
||||
|
||||
@Query(() => RowLevelPermissionPredicateDTO, { nullable: true })
|
||||
async getRowLevelPermissionPredicate(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateDTO | null> {
|
||||
return this.predicateService.findById(id, workspace.id);
|
||||
}
|
||||
|
||||
@Mutation(() => RowLevelPermissionPredicateDTO)
|
||||
async createRowLevelPermissionPredicate(
|
||||
@Args('input')
|
||||
input: CreateRowLevelPermissionPredicateInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateDTO> {
|
||||
return this.predicateService.createOne({
|
||||
createRowLevelPermissionPredicateInput: {
|
||||
...input,
|
||||
operand: input.operand as RowLevelPermissionPredicateOperand,
|
||||
value: input.value,
|
||||
},
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => RowLevelPermissionPredicateDTO)
|
||||
async updateRowLevelPermissionPredicate(
|
||||
@Args('input')
|
||||
input: UpdateRowLevelPermissionPredicateInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateDTO> {
|
||||
return this.predicateService.updateOne({
|
||||
updateRowLevelPermissionPredicateInput: {
|
||||
...input,
|
||||
operand: input.operand as RowLevelPermissionPredicateOperand,
|
||||
value: input.value,
|
||||
},
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => RowLevelPermissionPredicateDTO)
|
||||
async deleteRowLevelPermissionPredicate(
|
||||
@Args('input')
|
||||
input: DeleteRowLevelPermissionPredicateInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<RowLevelPermissionPredicateDTO> {
|
||||
return this.predicateService.deleteOne({
|
||||
deleteRowLevelPermissionPredicateInput: {
|
||||
...input,
|
||||
},
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { RowLevelPermissionPredicateGroupResolver } from 'src/engine/metadata-modules/row-level-permission-predicate/resolvers/row-level-permission-predicate-group.resolver';
|
||||
import { RowLevelPermissionPredicateResolver } from 'src/engine/metadata-modules/row-level-permission-predicate/resolvers/row-level-permission-predicate.resolver';
|
||||
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
|
||||
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([
|
||||
RowLevelPermissionPredicateEntity,
|
||||
RowLevelPermissionPredicateGroupEntity,
|
||||
]),
|
||||
WorkspaceCacheModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
],
|
||||
providers: [
|
||||
RowLevelPermissionPredicateService,
|
||||
RowLevelPermissionPredicateGroupService,
|
||||
RowLevelPermissionPredicateResolver,
|
||||
RowLevelPermissionPredicateGroupResolver,
|
||||
],
|
||||
exports: [
|
||||
RowLevelPermissionPredicateService,
|
||||
RowLevelPermissionPredicateGroupService,
|
||||
],
|
||||
})
|
||||
export class RowLevelPermissionModule {}
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-create-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-to-create.util';
|
||||
import { fromDeleteRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-delete-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-or-throw.util';
|
||||
import { fromDestroyRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-destroy-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-or-throw.util';
|
||||
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
|
||||
import { fromUpdateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToUpdateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-update-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-to-update-or-throw.util';
|
||||
import { type CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate-group.input';
|
||||
import { type DeleteRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate-group.input';
|
||||
import { type DestroyRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate-group.input';
|
||||
import { type UpdateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate-group.input';
|
||||
import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
const RLP_CACHE_KEYS = [
|
||||
'flatRowLevelPermissionPredicateMaps',
|
||||
'flatRowLevelPermissionPredicateGroupMaps',
|
||||
] as const;
|
||||
|
||||
@Injectable()
|
||||
export class RowLevelPermissionPredicateGroupService {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
createRowLevelPermissionPredicateGroupInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createRowLevelPermissionPredicateGroupInput: CreateRowLevelPermissionPredicateGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
const flatGroupToCreate =
|
||||
fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate(
|
||||
{
|
||||
createRowLevelPermissionPredicateGroupInput,
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToCreate: [flatGroupToCreate],
|
||||
});
|
||||
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateGroupToDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatGroupToCreate.id,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async updateOne({
|
||||
updateRowLevelPermissionPredicateGroupInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
updateRowLevelPermissionPredicateGroupInput: UpdateRowLevelPermissionPredicateGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatGroupToUpdate =
|
||||
fromUpdateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToUpdateOrThrow(
|
||||
{
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
updateRowLevelPermissionPredicateGroupInput,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToUpdate: [flatGroupToUpdate],
|
||||
});
|
||||
|
||||
const { flatRowLevelPermissionPredicateGroupMaps: recomputedFlatMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateGroupToDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatGroupToUpdate.id,
|
||||
flatEntityMaps: recomputedFlatMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async deleteOne({
|
||||
deleteRowLevelPermissionPredicateGroupInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
deleteRowLevelPermissionPredicateGroupInput: DeleteRowLevelPermissionPredicateGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatGroupWithDeletedAt =
|
||||
fromDeleteRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow(
|
||||
{
|
||||
deleteRowLevelPermissionPredicateGroupInput,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToUpdate: [flatGroupWithDeletedAt],
|
||||
});
|
||||
|
||||
const { flatRowLevelPermissionPredicateGroupMaps: recomputedFlatMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateGroupToDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatGroupWithDeletedAt.id,
|
||||
flatEntityMaps: recomputedFlatMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async destroyOne({
|
||||
destroyRowLevelPermissionPredicateGroupInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
destroyRowLevelPermissionPredicateGroupInput: DestroyRowLevelPermissionPredicateGroupInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateGroupDTO> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatGroupToDelete =
|
||||
fromDestroyRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow(
|
||||
{
|
||||
destroyRowLevelPermissionPredicateGroupInput,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToDelete: [flatGroupToDelete],
|
||||
});
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateGroupToDto(flatGroupToDelete);
|
||||
}
|
||||
|
||||
async findByWorkspaceId(
|
||||
workspaceId: string,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO[]> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatRowLevelPermissionPredicateGroupMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter((group) => group.deletedAt === null)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(a.positionInRowLevelPermissionPredicateGroup ?? 0) -
|
||||
(b.positionInRowLevelPermissionPredicateGroup ?? 0),
|
||||
)
|
||||
.map(fromFlatRowLevelPermissionPredicateGroupToDto);
|
||||
}
|
||||
|
||||
async findByRole(
|
||||
workspaceId: string,
|
||||
roleId: string,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO[]> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatRowLevelPermissionPredicateGroupMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter((group) => group.deletedAt === null && group.roleId === roleId)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(a.positionInRowLevelPermissionPredicateGroup ?? 0) -
|
||||
(b.positionInRowLevelPermissionPredicateGroup ?? 0),
|
||||
)
|
||||
.map(fromFlatRowLevelPermissionPredicateGroupToDto);
|
||||
}
|
||||
|
||||
async findById(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<RowLevelPermissionPredicateGroupDTO | null> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatGroup = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatGroup) || flatGroup.deletedAt !== null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateGroupToDto(flatGroup);
|
||||
}
|
||||
|
||||
private async runMigration({
|
||||
workspaceId,
|
||||
flatEntityToCreate = [],
|
||||
flatEntityToUpdate = [],
|
||||
flatEntityToDelete = [],
|
||||
}: {
|
||||
workspaceId: string;
|
||||
flatEntityToCreate?: FlatRowLevelPermissionPredicateGroup[];
|
||||
flatEntityToUpdate?: FlatRowLevelPermissionPredicateGroup[];
|
||||
flatEntityToDelete?: FlatRowLevelPermissionPredicateGroup[];
|
||||
}): Promise<void> {
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
flatEntityToCreate,
|
||||
flatEntityToDelete,
|
||||
flatEntityToUpdate,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Validation errors occurred while applying row level permission predicate group mutation',
|
||||
);
|
||||
}
|
||||
|
||||
await this.flatEntityMapsCacheService.invalidateFlatEntityMaps({
|
||||
workspaceId,
|
||||
flatMapsKeys: [...RLP_CACHE_KEYS],
|
||||
});
|
||||
}
|
||||
}
|
||||
+304
@@ -0,0 +1,304 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-create-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-to-create.util';
|
||||
import { fromDeleteRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-delete-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-or-throw.util';
|
||||
import { fromDestroyRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-destroy-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-or-throw.util';
|
||||
import { fromFlatRowLevelPermissionPredicateToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-to-dto.util';
|
||||
import { fromUpdateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToUpdateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-update-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-to-update-or-throw.util';
|
||||
import { type CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate.input';
|
||||
import { type DeleteRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate.input';
|
||||
import { type DestroyRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate.input';
|
||||
import { type UpdateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate.input';
|
||||
import { RowLevelPermissionPredicateDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate.dto';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
const RLP_CACHE_KEYS = [
|
||||
'flatRowLevelPermissionPredicateMaps',
|
||||
'flatRowLevelPermissionPredicateGroupMaps',
|
||||
] as const;
|
||||
|
||||
@Injectable()
|
||||
export class RowLevelPermissionPredicateService {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
createRowLevelPermissionPredicateInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createRowLevelPermissionPredicateInput: CreateRowLevelPermissionPredicateInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateDTO> {
|
||||
const flatPredicateToCreate =
|
||||
fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate(
|
||||
{
|
||||
createRowLevelPermissionPredicateInput,
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToCreate: [flatPredicateToCreate],
|
||||
});
|
||||
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateToDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatPredicateToCreate.id,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async updateOne({
|
||||
updateRowLevelPermissionPredicateInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
updateRowLevelPermissionPredicateInput: UpdateRowLevelPermissionPredicateInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateDTO> {
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPredicateToUpdate =
|
||||
fromUpdateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToUpdateOrThrow(
|
||||
{
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
updateRowLevelPermissionPredicateInput,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToUpdate: [flatPredicateToUpdate],
|
||||
});
|
||||
|
||||
const { flatRowLevelPermissionPredicateMaps: recomputedFlatMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateToDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatPredicateToUpdate.id,
|
||||
flatEntityMaps: recomputedFlatMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async deleteOne({
|
||||
deleteRowLevelPermissionPredicateInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
deleteRowLevelPermissionPredicateInput: DeleteRowLevelPermissionPredicateInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateDTO> {
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPredicateWithDeletedAt =
|
||||
fromDeleteRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow(
|
||||
{
|
||||
deleteRowLevelPermissionPredicateInput,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToUpdate: [flatPredicateWithDeletedAt],
|
||||
});
|
||||
|
||||
const { flatRowLevelPermissionPredicateMaps: recomputedFlatMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateToDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatPredicateWithDeletedAt.id,
|
||||
flatEntityMaps: recomputedFlatMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async destroyOne({
|
||||
destroyRowLevelPermissionPredicateInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
destroyRowLevelPermissionPredicateInput: DestroyRowLevelPermissionPredicateInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RowLevelPermissionPredicateDTO> {
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPredicateToDelete =
|
||||
fromDestroyRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow(
|
||||
{
|
||||
destroyRowLevelPermissionPredicateInput,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
},
|
||||
);
|
||||
|
||||
await this.runMigration({
|
||||
workspaceId,
|
||||
flatEntityToDelete: [flatPredicateToDelete],
|
||||
});
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateToDto(flatPredicateToDelete);
|
||||
}
|
||||
|
||||
async findByWorkspaceId(
|
||||
workspaceId: string,
|
||||
): Promise<RowLevelPermissionPredicateDTO[]> {
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatRowLevelPermissionPredicateMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter((predicate) => predicate.deletedAt === null)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(a.positionInRowLevelPermissionPredicateGroup ?? 0) -
|
||||
(b.positionInRowLevelPermissionPredicateGroup ?? 0),
|
||||
)
|
||||
.map(fromFlatRowLevelPermissionPredicateToDto);
|
||||
}
|
||||
|
||||
async findByRoleAndObject(
|
||||
workspaceId: string,
|
||||
roleId: string,
|
||||
objectMetadataId: string,
|
||||
): Promise<RowLevelPermissionPredicateDTO[]> {
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatRowLevelPermissionPredicateMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(predicate) =>
|
||||
predicate.deletedAt === null &&
|
||||
predicate.roleId === roleId &&
|
||||
predicate.objectMetadataId === objectMetadataId,
|
||||
)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(a.positionInRowLevelPermissionPredicateGroup ?? 0) -
|
||||
(b.positionInRowLevelPermissionPredicateGroup ?? 0),
|
||||
)
|
||||
.map(fromFlatRowLevelPermissionPredicateToDto);
|
||||
}
|
||||
|
||||
async findById(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<RowLevelPermissionPredicateDTO | null> {
|
||||
const { flatRowLevelPermissionPredicateMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPredicate = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatPredicate) || flatPredicate.deletedAt !== null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fromFlatRowLevelPermissionPredicateToDto(flatPredicate);
|
||||
}
|
||||
|
||||
private async runMigration({
|
||||
workspaceId,
|
||||
flatEntityToCreate = [],
|
||||
flatEntityToUpdate = [],
|
||||
flatEntityToDelete = [],
|
||||
}: {
|
||||
workspaceId: string;
|
||||
flatEntityToCreate?: FlatRowLevelPermissionPredicate[];
|
||||
flatEntityToUpdate?: FlatRowLevelPermissionPredicate[];
|
||||
flatEntityToDelete?: FlatRowLevelPermissionPredicate[];
|
||||
}): Promise<void> {
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
rowLevelPermissionPredicate: {
|
||||
flatEntityToCreate,
|
||||
flatEntityToDelete,
|
||||
flatEntityToUpdate,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Validation errors occurred while applying row level permission predicate mutation',
|
||||
);
|
||||
}
|
||||
|
||||
await this.flatEntityMapsCacheService.invalidateFlatEntityMaps({
|
||||
workspaceId,
|
||||
flatMapsKeys: [...RLP_CACHE_KEYS],
|
||||
});
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export type FlatRowLevelPermissionPredicateGroupMaps =
|
||||
FlatEntityMaps<FlatRowLevelPermissionPredicateGroup>;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
import { type RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
|
||||
export type FlatRowLevelPermissionPredicateGroup =
|
||||
FlatEntityFrom<RowLevelPermissionPredicateGroupEntity> & {
|
||||
childRowLevelPermissionPredicateGroupIds: string[];
|
||||
rowLevelPermissionPredicateIds: string[];
|
||||
};
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export type FlatRowLevelPermissionPredicateMaps =
|
||||
FlatEntityMaps<FlatRowLevelPermissionPredicate>;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
import { type RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
|
||||
export type FlatRowLevelPermissionPredicate =
|
||||
FlatEntityFrom<RowLevelPermissionPredicateEntity>;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
export type RelationPredicateValue = {
|
||||
isCurrentWorkspaceMemberSelected?: boolean;
|
||||
selectedRecordIds: string[];
|
||||
};
|
||||
|
||||
export type RowLevelPermissionPredicateValue =
|
||||
| string
|
||||
| string[]
|
||||
| boolean
|
||||
| number
|
||||
| RelationPredicateValue
|
||||
| Record<string, unknown>
|
||||
| null
|
||||
| undefined;
|
||||
@@ -14,13 +14,13 @@ import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrap
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { INTERNAL_SERVER_ERROR } from 'src/engine/middlewares/constants/default-error-message.constant';
|
||||
import { bindDataToRequestObject } from 'src/engine/utils/bind-data-to-request-object.util';
|
||||
import {
|
||||
handleException,
|
||||
handleExceptionAndConvertToGraphQLError,
|
||||
} from 'src/engine/utils/global-exception-handler.util';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { type CustomException } from 'src/utils/custom-exception';
|
||||
import { bindDataToRequestObject } from 'src/engine/utils/bind-data-to-request-object.util';
|
||||
|
||||
@Injectable()
|
||||
export class MiddlewareService {
|
||||
|
||||
+17
@@ -193,6 +193,16 @@ describe('WorkspaceEntityManager', () => {
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatRowLevelPermissionPredicateMaps: {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatRowLevelPermissionPredicateGroupMaps: {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
objectIdByNameSingular: {
|
||||
'test-entity': 'test-entity-id',
|
||||
},
|
||||
@@ -213,8 +223,10 @@ describe('WorkspaceEntityManager', () => {
|
||||
IS_DASHBOARD_V2_ENABLED: false,
|
||||
IS_TIMELINE_ACTIVITY_MIGRATED: false,
|
||||
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED: false,
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false,
|
||||
IS_WORKSPACE_CREATION_V2_ENABLED: false,
|
||||
},
|
||||
userWorkspaceRoleMap: {},
|
||||
eventEmitterService: {
|
||||
emitMutationEvent: jest.fn(),
|
||||
emitDatabaseBatchEvent: jest.fn(),
|
||||
@@ -238,6 +250,7 @@ describe('WorkspaceEntityManager', () => {
|
||||
IS_WORKFLOW_RUN_STOPPAGE_ENABLED: false,
|
||||
IS_DASHBOARD_V2_ENABLED: false,
|
||||
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED: false,
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false,
|
||||
},
|
||||
permissionsPerRoleId: {},
|
||||
eventEmitterService: mockInternalContext.eventEmitterService,
|
||||
@@ -269,6 +282,10 @@ describe('WorkspaceEntityManager', () => {
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatIndexMaps: mockInternalContext.flatIndexMaps,
|
||||
flatRowLevelPermissionPredicateMaps:
|
||||
mockInternalContext.flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
mockInternalContext.flatRowLevelPermissionPredicateGroupMaps,
|
||||
objectIdByNameSingular: mockInternalContext.objectIdByNameSingular,
|
||||
featureFlagsMap: mockInternalContext.featureFlagsMap,
|
||||
permissionsPerRoleId: mockDataSource.permissionsPerRoleId,
|
||||
|
||||
+13
-1
@@ -33,6 +33,7 @@ import { PlainObjectToDatabaseEntityTransformer } from 'typeorm/query-builder/tr
|
||||
import { type UpsertOptions } from 'typeorm/repository/UpsertOptions';
|
||||
import { InstanceChecker } from 'typeorm/util/InstanceChecker';
|
||||
|
||||
import { type WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
@@ -87,6 +88,12 @@ export class WorkspaceEntityManager extends EntityManager {
|
||||
return this.connection.eventEmitterService;
|
||||
}
|
||||
|
||||
get authContext(): WorkspaceAuthContext {
|
||||
const context = getWorkspaceContext();
|
||||
|
||||
return context.authContext;
|
||||
}
|
||||
|
||||
get internalContext(): WorkspaceInternalContext {
|
||||
const context = getWorkspaceContext();
|
||||
|
||||
@@ -95,8 +102,13 @@ export class WorkspaceEntityManager extends EntityManager {
|
||||
flatObjectMetadataMaps: context.flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: context.flatFieldMetadataMaps,
|
||||
flatIndexMaps: context.flatIndexMaps,
|
||||
flatRowLevelPermissionPredicateMaps:
|
||||
context.flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
context.flatRowLevelPermissionPredicateGroupMaps,
|
||||
objectIdByNameSingular: context.objectIdByNameSingular,
|
||||
featureFlagsMap: context.featureFlagsMap,
|
||||
userWorkspaceRoleMap: context.userWorkspaceRoleMap,
|
||||
eventEmitterService: this.eventEmitterService,
|
||||
};
|
||||
}
|
||||
@@ -211,7 +223,7 @@ export class WorkspaceEntityManager extends EntityManager {
|
||||
options?.objectRecordsPermissions ?? {},
|
||||
this.internalContext,
|
||||
options?.shouldBypassPermissionChecks ?? false,
|
||||
{},
|
||||
this.authContext,
|
||||
this.getFeatureFlagMap(),
|
||||
);
|
||||
}
|
||||
|
||||
+6
@@ -88,6 +88,8 @@ export class GlobalWorkspaceOrmManager {
|
||||
rolesPermissions: permissionsPerRoleId,
|
||||
ORMEntityMetadatas: entityMetadatas,
|
||||
userWorkspaceRoleMap,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
@@ -96,6 +98,8 @@ export class GlobalWorkspaceOrmManager {
|
||||
'rolesPermissions',
|
||||
'ORMEntityMetadatas',
|
||||
'userWorkspaceRoleMap',
|
||||
'flatRowLevelPermissionPredicateMaps',
|
||||
'flatRowLevelPermissionPredicateGroupMaps',
|
||||
]);
|
||||
|
||||
const { idByNameSingular: objectIdByNameSingular } =
|
||||
@@ -106,6 +110,8 @@ export class GlobalWorkspaceOrmManager {
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatIndexMaps,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
objectIdByNameSingular,
|
||||
featureFlagsMap,
|
||||
permissionsPerRoleId,
|
||||
|
||||
+5
@@ -3,6 +3,8 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
|
||||
export interface WorkspaceInternalContext {
|
||||
@@ -10,7 +12,10 @@ export interface WorkspaceInternalContext {
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
flatIndexMaps: FlatEntityMaps<FlatIndexMetadata>;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
objectIdByNameSingular: Record<string, string>;
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>;
|
||||
userWorkspaceRoleMap: Record<string, string>;
|
||||
eventEmitterService: WorkspaceEventEmitter;
|
||||
}
|
||||
|
||||
+12
-1
@@ -118,8 +118,19 @@ describe('WorkspaceRepository', () => {
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatRowLevelPermissionPredicateMaps: {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatRowLevelPermissionPredicateGroupMaps: {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
objectIdByNameSingular: {},
|
||||
featureFlagsMap: {},
|
||||
featureFlagsMap: {} as FeatureFlagMap,
|
||||
userWorkspaceRoleMap: {},
|
||||
eventEmitterService: {} as unknown,
|
||||
} as unknown as WorkspaceInternalContext;
|
||||
|
||||
|
||||
+26
-1
@@ -23,6 +23,7 @@ import { validateQueryIsPermittedOrThrow } from 'src/engine/twenty-orm/repositor
|
||||
import { type WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
|
||||
import { type WorkspaceSoftDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-soft-delete-query-builder';
|
||||
import { type WorkspaceUpdateQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-update-query-builder';
|
||||
import { applyRowLevelPermissionPredicates } from 'src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util';
|
||||
import { applyTableAliasOnWhereCondition } from 'src/engine/twenty-orm/utils/apply-table-alias-on-where-condition';
|
||||
import { computeEventSelectQueryBuilder } from 'src/engine/twenty-orm/utils/compute-event-select-query-builder.util';
|
||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
@@ -57,7 +58,7 @@ export class WorkspaceDeleteQueryBuilder<
|
||||
override clone(): this {
|
||||
const clonedQueryBuilder = super.clone();
|
||||
|
||||
return new WorkspaceDeleteQueryBuilder(
|
||||
const workspaceDeleteQueryBuilder = new WorkspaceDeleteQueryBuilder(
|
||||
clonedQueryBuilder,
|
||||
this.objectRecordsPermissions,
|
||||
this.internalContext,
|
||||
@@ -65,10 +66,13 @@ export class WorkspaceDeleteQueryBuilder<
|
||||
this.authContext,
|
||||
this.featureFlagMap,
|
||||
) as this;
|
||||
|
||||
return workspaceDeleteQueryBuilder;
|
||||
}
|
||||
|
||||
override async execute(): Promise<DeleteResult & { generatedMaps: T[] }> {
|
||||
try {
|
||||
this.applyRowLevelPermissionPredicates();
|
||||
validateQueryIsPermittedOrThrow({
|
||||
expressionMap: this.expressionMap,
|
||||
objectsPermissions: this.objectRecordsPermissions,
|
||||
@@ -157,6 +161,27 @@ export class WorkspaceDeleteQueryBuilder<
|
||||
return mainAliasTarget;
|
||||
}
|
||||
|
||||
private applyRowLevelPermissionPredicates(): void {
|
||||
if (this.shouldBypassPermissionChecks) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mainAliasTarget = this.getMainAliasTarget();
|
||||
|
||||
const objectMetadata = getObjectMetadataFromEntityTarget(
|
||||
mainAliasTarget,
|
||||
this.internalContext,
|
||||
);
|
||||
|
||||
applyRowLevelPermissionPredicates({
|
||||
queryBuilder: this as unknown as WorkspaceSelectQueryBuilder<T>,
|
||||
objectMetadata,
|
||||
internalContext: this.internalContext,
|
||||
authContext: this.authContext,
|
||||
featureFlagMap: this.featureFlagMap,
|
||||
});
|
||||
}
|
||||
|
||||
override select(): WorkspaceSelectQueryBuilder<T> {
|
||||
throw new TwentyORMException(
|
||||
'This builder cannot morph into a select builder',
|
||||
|
||||
+35
-2
@@ -24,6 +24,7 @@ import { WorkspaceDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/wo
|
||||
import { WorkspaceInsertQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-insert-query-builder';
|
||||
import { WorkspaceSoftDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-soft-delete-query-builder';
|
||||
import { WorkspaceUpdateQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-update-query-builder';
|
||||
import { applyRowLevelPermissionPredicates } from 'src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util';
|
||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
import { getObjectMetadataFromEntityTarget } from 'src/engine/twenty-orm/utils/get-object-metadata-from-entity-target.util';
|
||||
|
||||
@@ -58,7 +59,7 @@ export class WorkspaceSelectQueryBuilder<
|
||||
override clone(): this {
|
||||
const clonedQueryBuilder = super.clone();
|
||||
|
||||
return new WorkspaceSelectQueryBuilder(
|
||||
const workspaceSelectQueryBuilder = new WorkspaceSelectQueryBuilder(
|
||||
clonedQueryBuilder,
|
||||
this.objectRecordsPermissions,
|
||||
this.internalContext,
|
||||
@@ -66,6 +67,8 @@ export class WorkspaceSelectQueryBuilder<
|
||||
this.authContext,
|
||||
this.featureFlagMap,
|
||||
) as this;
|
||||
|
||||
return workspaceSelectQueryBuilder;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -327,6 +330,7 @@ export class WorkspaceSelectQueryBuilder<
|
||||
}
|
||||
|
||||
private validatePermissions(): void {
|
||||
this.applyRowLevelPermissionPredicates();
|
||||
validateQueryIsPermittedOrThrow({
|
||||
expressionMap: this.expressionMap,
|
||||
objectsPermissions: this.objectRecordsPermissions,
|
||||
@@ -338,7 +342,9 @@ export class WorkspaceSelectQueryBuilder<
|
||||
}
|
||||
|
||||
private getMainAliasTarget(): EntityTarget<T> {
|
||||
const mainAliasTarget = this.expressionMap.mainAlias?.target;
|
||||
const mainAlias = this.expressionMap.mainAlias;
|
||||
|
||||
const mainAliasTarget = mainAlias?.target;
|
||||
|
||||
if (!mainAliasTarget) {
|
||||
throw new TwentyORMException(
|
||||
@@ -349,4 +355,31 @@ export class WorkspaceSelectQueryBuilder<
|
||||
|
||||
return mainAliasTarget;
|
||||
}
|
||||
|
||||
private applyRowLevelPermissionPredicates(): void {
|
||||
if (this.shouldBypassPermissionChecks) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Subqueries don't have entity metadata, skip permission predicates
|
||||
// Permissions are already applied on the original entity query
|
||||
if (this.expressionMap.mainAlias?.subQuery) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mainAliasTarget = this.getMainAliasTarget();
|
||||
|
||||
const objectMetadata = getObjectMetadataFromEntityTarget(
|
||||
mainAliasTarget,
|
||||
this.internalContext,
|
||||
);
|
||||
|
||||
applyRowLevelPermissionPredicates({
|
||||
queryBuilder: this,
|
||||
objectMetadata,
|
||||
internalContext: this.internalContext,
|
||||
authContext: this.authContext,
|
||||
featureFlagMap: this.featureFlagMap,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+26
-1
@@ -22,6 +22,7 @@ import { validateQueryIsPermittedOrThrow } from 'src/engine/twenty-orm/repositor
|
||||
import { type WorkspaceDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-delete-query-builder';
|
||||
import { type WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
|
||||
import { type WorkspaceUpdateQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-update-query-builder';
|
||||
import { applyRowLevelPermissionPredicates } from 'src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util';
|
||||
import { applyTableAliasOnWhereCondition } from 'src/engine/twenty-orm/utils/apply-table-alias-on-where-condition';
|
||||
import { computeEventSelectQueryBuilder } from 'src/engine/twenty-orm/utils/compute-event-select-query-builder.util';
|
||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
@@ -57,7 +58,7 @@ export class WorkspaceSoftDeleteQueryBuilder<
|
||||
override clone(): this {
|
||||
const clonedQueryBuilder = super.clone();
|
||||
|
||||
return new WorkspaceSoftDeleteQueryBuilder(
|
||||
const workspaceSoftDeleteQueryBuilder = new WorkspaceSoftDeleteQueryBuilder(
|
||||
clonedQueryBuilder,
|
||||
this.objectRecordsPermissions,
|
||||
this.internalContext,
|
||||
@@ -65,10 +66,13 @@ export class WorkspaceSoftDeleteQueryBuilder<
|
||||
this.authContext,
|
||||
this.featureFlagMap,
|
||||
) as this;
|
||||
|
||||
return workspaceSoftDeleteQueryBuilder;
|
||||
}
|
||||
|
||||
override async execute(): Promise<UpdateResult> {
|
||||
try {
|
||||
this.applyRowLevelPermissionPredicates();
|
||||
validateQueryIsPermittedOrThrow({
|
||||
expressionMap: this.expressionMap,
|
||||
objectsPermissions: this.objectRecordsPermissions,
|
||||
@@ -184,4 +188,25 @@ export class WorkspaceSoftDeleteQueryBuilder<
|
||||
|
||||
return mainAliasTarget;
|
||||
}
|
||||
|
||||
private applyRowLevelPermissionPredicates(): void {
|
||||
if (this.shouldBypassPermissionChecks) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mainAliasTarget = this.getMainAliasTarget();
|
||||
|
||||
const objectMetadata = getObjectMetadataFromEntityTarget(
|
||||
mainAliasTarget,
|
||||
this.internalContext,
|
||||
);
|
||||
|
||||
applyRowLevelPermissionPredicates({
|
||||
queryBuilder: this as unknown as WorkspaceSelectQueryBuilder<T>,
|
||||
objectMetadata,
|
||||
internalContext: this.internalContext,
|
||||
authContext: this.authContext,
|
||||
featureFlagMap: this.featureFlagMap,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+29
-2
@@ -30,6 +30,7 @@ import { validateQueryIsPermittedOrThrow } from 'src/engine/twenty-orm/repositor
|
||||
import { type WorkspaceDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-delete-query-builder';
|
||||
import { WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
|
||||
import { type WorkspaceSoftDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-soft-delete-query-builder';
|
||||
import { applyRowLevelPermissionPredicates } from 'src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util';
|
||||
import { applyTableAliasOnWhereCondition } from 'src/engine/twenty-orm/utils/apply-table-alias-on-where-condition';
|
||||
import { computeEventSelectQueryBuilder } from 'src/engine/twenty-orm/utils/compute-event-select-query-builder.util';
|
||||
import { formatData } from 'src/engine/twenty-orm/utils/format-data.util';
|
||||
@@ -77,7 +78,7 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
override clone(): this {
|
||||
const clonedQueryBuilder = super.clone();
|
||||
|
||||
return new WorkspaceUpdateQueryBuilder(
|
||||
const workspaceUpdateQueryBuilder = new WorkspaceUpdateQueryBuilder(
|
||||
clonedQueryBuilder as UpdateQueryBuilder<T>,
|
||||
this.objectRecordsPermissions,
|
||||
this.internalContext,
|
||||
@@ -85,6 +86,8 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
this.authContext,
|
||||
this.featureFlagMap,
|
||||
) as this;
|
||||
|
||||
return workspaceUpdateQueryBuilder;
|
||||
}
|
||||
|
||||
override async execute(): Promise<UpdateResult> {
|
||||
@@ -92,7 +95,6 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
if (this.manyInputs) {
|
||||
return this.executeMany();
|
||||
}
|
||||
|
||||
validateQueryIsPermittedOrThrow({
|
||||
expressionMap: this.expressionMap,
|
||||
objectsPermissions: this.objectRecordsPermissions,
|
||||
@@ -171,6 +173,8 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
this.internalContext.flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
this.applyRowLevelPermissionPredicates();
|
||||
|
||||
const result = await super.execute();
|
||||
|
||||
const after = await eventSelectQueryBuilder.getMany();
|
||||
@@ -323,6 +327,8 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
this.expressionMap.valuesSet = input.partialEntity;
|
||||
this.where({ id: input.criteria });
|
||||
|
||||
this.applyRowLevelPermissionPredicates();
|
||||
|
||||
const result = await super.execute();
|
||||
|
||||
results.push(result);
|
||||
@@ -494,4 +500,25 @@ export class WorkspaceUpdateQueryBuilder<
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private applyRowLevelPermissionPredicates(): void {
|
||||
if (this.shouldBypassPermissionChecks) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mainAliasTarget = this.getMainAliasTarget();
|
||||
|
||||
const objectMetadata = getObjectMetadataFromEntityTarget(
|
||||
mainAliasTarget,
|
||||
this.internalContext,
|
||||
);
|
||||
|
||||
applyRowLevelPermissionPredicates({
|
||||
queryBuilder: this as unknown as WorkspaceSelectQueryBuilder<T>,
|
||||
objectMetadata,
|
||||
internalContext: this.internalContext,
|
||||
authContext: this.authContext,
|
||||
featureFlagMap: this.featureFlagMap,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
|
||||
export type ORMWorkspaceContext = {
|
||||
authContext: WorkspaceAuthContext;
|
||||
@@ -21,6 +23,8 @@ export type ORMWorkspaceContext = {
|
||||
permissionsPerRoleId: ObjectsPermissionsByRoleId;
|
||||
entityMetadatas: EntityMetadata[];
|
||||
userWorkspaceRoleMap: Record<string, string>;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
};
|
||||
|
||||
export const workspaceContextStorage =
|
||||
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import {
|
||||
Brackets,
|
||||
NotBrackets,
|
||||
type ObjectLiteral,
|
||||
type WhereExpressionBuilder,
|
||||
} from 'typeorm';
|
||||
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { GraphqlQueryFilterFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
|
||||
import { buildRowLevelPermissionRecordFilter } from 'src/engine/twenty-orm/utils/build-row-level-permission-record-filter.util';
|
||||
|
||||
type ApplyRowLevelPermissionPredicatesArgs<T extends ObjectLiteral> = {
|
||||
queryBuilder: WorkspaceSelectQueryBuilder<T>;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
internalContext: WorkspaceInternalContext;
|
||||
authContext: AuthContext;
|
||||
featureFlagMap: FeatureFlagMap;
|
||||
};
|
||||
|
||||
export const applyRowLevelPermissionPredicates = <T extends ObjectLiteral>({
|
||||
queryBuilder,
|
||||
objectMetadata,
|
||||
internalContext,
|
||||
authContext,
|
||||
featureFlagMap,
|
||||
}: ApplyRowLevelPermissionPredicatesArgs<T>): void => {
|
||||
if (
|
||||
featureFlagMap[
|
||||
FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED
|
||||
] !== true
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const roleId = authContext.userWorkspaceId
|
||||
? internalContext.userWorkspaceRoleMap[authContext.userWorkspaceId]
|
||||
: undefined;
|
||||
|
||||
const recordFilter = buildRowLevelPermissionRecordFilter({
|
||||
flatRowLevelPermissionPredicateMaps:
|
||||
internalContext.flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
internalContext.flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatFieldMetadataMaps: internalContext.flatFieldMetadataMaps,
|
||||
objectMetadata,
|
||||
roleId,
|
||||
authContext,
|
||||
});
|
||||
|
||||
if (!recordFilter || Object.keys(recordFilter).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyObjectRecordFilterToQueryBuilder({
|
||||
queryBuilder,
|
||||
objectNameSingular: objectMetadata.nameSingular,
|
||||
recordFilter,
|
||||
fieldParser: new GraphqlQueryFilterFieldParser(
|
||||
objectMetadata,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
const applyObjectRecordFilterToQueryBuilder = <T extends ObjectLiteral>({
|
||||
queryBuilder,
|
||||
objectNameSingular,
|
||||
recordFilter,
|
||||
fieldParser,
|
||||
}: {
|
||||
queryBuilder: WorkspaceSelectQueryBuilder<T>;
|
||||
objectNameSingular: string;
|
||||
recordFilter: Record<string, unknown>;
|
||||
fieldParser: GraphqlQueryFilterFieldParser;
|
||||
}): void => {
|
||||
if (!recordFilter || Object.keys(recordFilter).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const whereCondition = new Brackets((qb) => {
|
||||
Object.entries(recordFilter).forEach(([key, value], index) => {
|
||||
parseKeyFilter({
|
||||
queryBuilder: qb,
|
||||
objectNameSingular,
|
||||
key,
|
||||
value,
|
||||
isFirst: index === 0,
|
||||
fieldParser,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (queryBuilder.expressionMap.wheres.length === 0) {
|
||||
queryBuilder.where(whereCondition);
|
||||
} else {
|
||||
queryBuilder.andWhere(whereCondition);
|
||||
}
|
||||
};
|
||||
|
||||
const parseKeyFilter = ({
|
||||
queryBuilder,
|
||||
objectNameSingular,
|
||||
key,
|
||||
value,
|
||||
isFirst,
|
||||
fieldParser,
|
||||
}: {
|
||||
queryBuilder: WhereExpressionBuilder;
|
||||
objectNameSingular: string;
|
||||
key: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value: any;
|
||||
isFirst: boolean;
|
||||
fieldParser: GraphqlQueryFilterFieldParser;
|
||||
}): void => {
|
||||
switch (key) {
|
||||
case 'and': {
|
||||
const andWhereCondition = new Brackets((qb) => {
|
||||
value.forEach((filter: Record<string, unknown>, index: number) => {
|
||||
const whereCondition = new Brackets((qb2) => {
|
||||
Object.entries(filter).forEach(
|
||||
([subFilterKey, subFilterValue], subIndex) => {
|
||||
parseKeyFilter({
|
||||
queryBuilder: qb2,
|
||||
objectNameSingular,
|
||||
key: subFilterKey,
|
||||
value: subFilterValue,
|
||||
isFirst: subIndex === 0,
|
||||
fieldParser,
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
if (index === 0) {
|
||||
qb.where(whereCondition);
|
||||
} else {
|
||||
qb.andWhere(whereCondition);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (isFirst) {
|
||||
queryBuilder.where(andWhereCondition);
|
||||
} else {
|
||||
queryBuilder.andWhere(andWhereCondition);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'or': {
|
||||
const orWhereCondition = new Brackets((qb) => {
|
||||
value.forEach((filter: Record<string, unknown>, index: number) => {
|
||||
const whereCondition = new Brackets((qb2) => {
|
||||
Object.entries(filter).forEach(
|
||||
([subFilterKey, subFilterValue], subIndex) => {
|
||||
parseKeyFilter({
|
||||
queryBuilder: qb2,
|
||||
objectNameSingular,
|
||||
key: subFilterKey,
|
||||
value: subFilterValue,
|
||||
isFirst: subIndex === 0,
|
||||
fieldParser,
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
if (index === 0) {
|
||||
qb.where(whereCondition);
|
||||
} else {
|
||||
qb.orWhere(whereCondition);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (isFirst) {
|
||||
queryBuilder.where(orWhereCondition);
|
||||
} else {
|
||||
queryBuilder.andWhere(orWhereCondition);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'not': {
|
||||
const notWhereCondition = new NotBrackets((qb) => {
|
||||
Object.entries(value).forEach(
|
||||
([subFilterKey, subFilterValue], subIndex) => {
|
||||
parseKeyFilter({
|
||||
queryBuilder: qb,
|
||||
objectNameSingular,
|
||||
key: subFilterKey,
|
||||
value: subFilterValue,
|
||||
isFirst: subIndex === 0,
|
||||
fieldParser,
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
if (isFirst) {
|
||||
queryBuilder.where(notWhereCondition);
|
||||
} else {
|
||||
queryBuilder.andWhere(notWhereCondition);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fieldParser.parse(queryBuilder, objectNameSingular, key, value, isFirst);
|
||||
break;
|
||||
}
|
||||
};
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import {
|
||||
RecordFilterGroupLogicalOperator,
|
||||
type CompositeFieldSubFieldName,
|
||||
type PartialFieldMetadataItemOption,
|
||||
type RecordGqlOperationFilter,
|
||||
} from 'twenty-shared/types';
|
||||
import {
|
||||
computeRecordGqlOperationFilter,
|
||||
convertViewFilterValueToString,
|
||||
getFilterTypeFromFieldType,
|
||||
isDefined,
|
||||
type RecordFilter,
|
||||
type RecordFilterGroup,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
import { type RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
|
||||
|
||||
type BuildRowLevelPermissionRecordFilterArgs = {
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
roleId: string | undefined;
|
||||
authContext: AuthContext;
|
||||
};
|
||||
|
||||
export const buildRowLevelPermissionRecordFilter = ({
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatFieldMetadataMaps,
|
||||
objectMetadata,
|
||||
roleId,
|
||||
authContext,
|
||||
}: BuildRowLevelPermissionRecordFilterArgs): RecordGqlOperationFilter | null => {
|
||||
if (!isDefined(roleId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const predicates = Object.values(flatRowLevelPermissionPredicateMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(predicate) =>
|
||||
predicate.roleId === roleId &&
|
||||
predicate.objectMetadataId === objectMetadata.id &&
|
||||
!isDefined(predicate.deletedAt),
|
||||
);
|
||||
|
||||
if (predicates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fieldMetadataMapById = flatFieldMetadataMaps.byId;
|
||||
|
||||
const workspaceMember = authContext.workspaceMember;
|
||||
|
||||
const recordFilters = predicates
|
||||
.map((predicate) => {
|
||||
const fieldMetadata = fieldMetadataMapById[predicate.fieldMetadataId];
|
||||
|
||||
if (!isDefined(fieldMetadata)) {
|
||||
throw new PermissionsException(
|
||||
`Field metadata not found for row level predicate ${predicate.id}`,
|
||||
PermissionsExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const workspaceMemberFieldMetadataId =
|
||||
predicate.workspaceMemberFieldMetadataId;
|
||||
let predicateValue: RowLevelPermissionPredicateValue = predicate.value;
|
||||
|
||||
if (isDefined(workspaceMemberFieldMetadataId)) {
|
||||
const workspaceMemberFieldMetadata =
|
||||
fieldMetadataMapById[workspaceMemberFieldMetadataId];
|
||||
|
||||
if (!isDefined(workspaceMemberFieldMetadata)) {
|
||||
throw new PermissionsException(
|
||||
`Workspace member field metadata not found for row level predicate ${predicate.id}`,
|
||||
PermissionsExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(workspaceMember)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rawWorkspaceMemberValue = Object.entries(workspaceMember).find(
|
||||
([key]) => key === workspaceMemberFieldMetadata.name,
|
||||
)?.[1];
|
||||
|
||||
const workspaceMemberSubFieldName =
|
||||
predicate.workspaceMemberSubFieldName;
|
||||
|
||||
if (
|
||||
isDefined(workspaceMemberSubFieldName) &&
|
||||
isDefined(rawWorkspaceMemberValue) &&
|
||||
isCompositeFieldMetadataType(workspaceMemberFieldMetadata.type) &&
|
||||
typeof rawWorkspaceMemberValue === 'object'
|
||||
) {
|
||||
predicateValue = rawWorkspaceMemberValue[workspaceMemberSubFieldName];
|
||||
} else {
|
||||
predicateValue = rawWorkspaceMemberValue;
|
||||
}
|
||||
|
||||
if (!isDefined(predicateValue)) {
|
||||
throw new PermissionsException(
|
||||
`Workspace member data missing for field ${workspaceMemberFieldMetadata.name}`,
|
||||
PermissionsExceptionCode.INVALID_ARG,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const effectiveSubFieldName = predicate.subFieldName as
|
||||
| CompositeFieldSubFieldName
|
||||
| undefined;
|
||||
|
||||
return {
|
||||
id: predicate.id,
|
||||
fieldMetadataId: predicate.fieldMetadataId,
|
||||
value: convertViewFilterValueToString(predicateValue),
|
||||
type: getFilterTypeFromFieldType(fieldMetadata.type),
|
||||
operand: predicate.operand as unknown as RecordFilter['operand'],
|
||||
recordFilterGroupId: predicate.rowLevelPermissionPredicateGroupId,
|
||||
subFieldName: effectiveSubFieldName,
|
||||
} satisfies RecordFilter;
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
const predicateGroupsById = flatRowLevelPermissionPredicateGroupMaps.byId;
|
||||
|
||||
const relevantGroupIds = new Set<string>();
|
||||
|
||||
for (const predicate of predicates) {
|
||||
if (isDefined(predicate.rowLevelPermissionPredicateGroupId)) {
|
||||
relevantGroupIds.add(predicate.rowLevelPermissionPredicateGroupId);
|
||||
|
||||
let parentGroupId =
|
||||
predicateGroupsById[predicate.rowLevelPermissionPredicateGroupId]
|
||||
?.parentRowLevelPermissionPredicateGroupId;
|
||||
|
||||
while (isDefined(parentGroupId) && !relevantGroupIds.has(parentGroupId)) {
|
||||
relevantGroupIds.add(parentGroupId);
|
||||
parentGroupId =
|
||||
predicateGroupsById[parentGroupId]
|
||||
?.parentRowLevelPermissionPredicateGroupId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const recordFilterGroups: RecordFilterGroup[] = [...relevantGroupIds]
|
||||
.map((groupId) => predicateGroupsById[groupId])
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(predicateGroup) =>
|
||||
predicateGroup.roleId === roleId &&
|
||||
!isDefined(predicateGroup.deletedAt),
|
||||
)
|
||||
.map((predicateGroup) => ({
|
||||
id: predicateGroup.id,
|
||||
logicalOperator:
|
||||
predicateGroup.logicalOperator ===
|
||||
RowLevelPermissionPredicateGroupLogicalOperator.OR
|
||||
? RecordFilterGroupLogicalOperator.OR
|
||||
: RecordFilterGroupLogicalOperator.AND,
|
||||
parentRecordFilterGroupId:
|
||||
predicateGroup.parentRowLevelPermissionPredicateGroupId,
|
||||
}));
|
||||
|
||||
const fieldMetadataItems = predicates
|
||||
.map((predicate) => fieldMetadataMapById[predicate.fieldMetadataId])
|
||||
.filter(isDefined)
|
||||
.map((field) => ({
|
||||
id: field.id,
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
label: field.label,
|
||||
options: field.options as PartialFieldMetadataItemOption[],
|
||||
}));
|
||||
|
||||
return computeRecordGqlOperationFilter({
|
||||
recordFilters,
|
||||
recordFilterGroups,
|
||||
fields: fieldMetadataItems,
|
||||
filterValueDependencies: {
|
||||
currentWorkspaceMemberId: authContext.workspaceMemberId,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -16,6 +16,7 @@ export const bindDataToRequestObject = (
|
||||
request.workspaceId = data.workspace?.id;
|
||||
request.workspaceMetadataVersion = metadataVersion;
|
||||
request.workspaceMemberId = data.workspaceMemberId;
|
||||
request.workspaceMember = data.workspaceMember;
|
||||
request.userWorkspaceId = data.userWorkspaceId;
|
||||
request.authProvider = data.authProvider;
|
||||
request.impersonationContext = data.impersonationContext;
|
||||
|
||||
@@ -6,6 +6,8 @@ import { type FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/
|
||||
import { type FlatRoleTargetByAgentIdMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-role-target-by-agent-id-maps.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type UserWorkspaceRoleMap } from 'src/engine/metadata-modules/role-target/services/workspace-user-workspace-role-map-cache.service';
|
||||
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
|
||||
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
|
||||
|
||||
export const WORKSPACE_CACHE_KEYS_V2 = {
|
||||
flatObjectMetadataMaps: 'flat-maps:object-metadata',
|
||||
@@ -32,6 +34,10 @@ export const WORKSPACE_CACHE_KEYS_V2 = {
|
||||
flatPageLayoutMaps: 'flat-maps:page-layout',
|
||||
flatPageLayoutWidgetMaps: 'flat-maps:page-layout-widget',
|
||||
flatPageLayoutTabMaps: 'flat-maps:flatPageLayoutTabMaps',
|
||||
flatRowLevelPermissionPredicateMaps:
|
||||
'flat-maps:row-level-permission-predicate',
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
'flat-maps:row-level-permission-predicate-group',
|
||||
} as const satisfies Record<WorkspaceCacheKeyName, string>;
|
||||
|
||||
export type AdditionalCacheDataMaps = {
|
||||
@@ -42,6 +48,8 @@ export type AdditionalCacheDataMaps = {
|
||||
flatApplicationMaps: FlatApplicationCacheMaps;
|
||||
ORMEntityMetadatas: EntityMetadata[];
|
||||
flatRoleTargetByAgentIdMaps: FlatRoleTargetByAgentIdMaps;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
};
|
||||
|
||||
export type WorkspaceCacheDataMap = AllFlatEntityMaps & AdditionalCacheDataMaps;
|
||||
|
||||
+2
@@ -35,6 +35,8 @@ export const fromWorkspaceMigrationBuilderExceptionToMetadataValidationResponseE
|
||||
invalidPageLayoutWidget: 0,
|
||||
totalErrors: 0,
|
||||
invalidPageLayoutTab: 0,
|
||||
invalidRowLevelPermissionPredicate: 0,
|
||||
invalidRowLevelPermissionPredicateGroup: 0,
|
||||
},
|
||||
errors: translatedReport,
|
||||
};
|
||||
|
||||
+104
@@ -26,6 +26,8 @@ import { WorkspaceMigrationV2PageLayoutActionsBuilderService } from 'src/engine/
|
||||
import { WorkspaceMigrationV2RoleTargetActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/role-target/workspace-migration-v2-role-target-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RoleActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/role/workspace-migration-v2-role-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/workspace-migration-v2-row-level-permission-predicate-group-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/workspace-migration-v2-row-level-permission-predicate-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFilterActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service';
|
||||
@@ -52,6 +54,8 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
private readonly workspaceMigrationV2PageLayoutActionsBuilderService: WorkspaceMigrationV2PageLayoutActionsBuilderService,
|
||||
private readonly workspaceMigrationV2PageLayoutWidgetActionsBuilderService: WorkspaceMigrationV2PageLayoutWidgetActionsBuilderService,
|
||||
private readonly workspaceMigrationV2PageLayoutTabActionsBuilderService: WorkspaceMigrationV2PageLayoutTabActionsBuilderService,
|
||||
private readonly workspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService: WorkspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService,
|
||||
private readonly workspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService: WorkspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService,
|
||||
) {}
|
||||
|
||||
private setupOptimisticCache({
|
||||
@@ -141,6 +145,8 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
flatFieldMetadataMaps,
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
flatRoleTargetMaps,
|
||||
flatAgentMaps,
|
||||
@@ -409,6 +415,86 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatRowLevelPermissionPredicateGroupMaps)) {
|
||||
const {
|
||||
from: fromFlatRowLevelPermissionPredicateGroupMaps,
|
||||
to: toFlatRowLevelPermissionPredicateGroupMaps,
|
||||
} = flatRowLevelPermissionPredicateGroupMaps;
|
||||
const rowLevelPermissionPredicateGroupResult =
|
||||
await this.workspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
additionalCacheDataMaps,
|
||||
from: fromFlatRowLevelPermissionPredicateGroupMaps,
|
||||
to: toFlatRowLevelPermissionPredicateGroupMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: {
|
||||
flatRoleMaps: optimisticAllFlatEntityMaps.flatRoleMaps,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
this.mergeFlatEntityMapsAndRelatedFlatEntityMapsInAllFlatEntityMapsThroughMutation(
|
||||
{
|
||||
allFlatEntityMaps: optimisticAllFlatEntityMaps,
|
||||
flatEntityMapsAndRelatedFlatEntityMaps:
|
||||
rowLevelPermissionPredicateGroupResult.optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
if (rowLevelPermissionPredicateGroupResult.status === 'fail') {
|
||||
orchestratorFailureReport.rowLevelPermissionPredicateGroup.push(
|
||||
...rowLevelPermissionPredicateGroupResult.errors,
|
||||
);
|
||||
} else {
|
||||
orchestratorActionsReport.rowLevelPermissionPredicateGroup =
|
||||
rowLevelPermissionPredicateGroupResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatRowLevelPermissionPredicateMaps)) {
|
||||
const {
|
||||
from: fromFlatRowLevelPermissionPredicateMaps,
|
||||
to: toFlatRowLevelPermissionPredicateMaps,
|
||||
} = flatRowLevelPermissionPredicateMaps;
|
||||
const rowLevelPermissionPredicateResult =
|
||||
await this.workspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
additionalCacheDataMaps,
|
||||
from: fromFlatRowLevelPermissionPredicateMaps,
|
||||
to: toFlatRowLevelPermissionPredicateMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: {
|
||||
flatFieldMetadataMaps:
|
||||
optimisticAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps:
|
||||
optimisticAllFlatEntityMaps.flatObjectMetadataMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
optimisticAllFlatEntityMaps.flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps: optimisticAllFlatEntityMaps.flatRoleMaps,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
this.mergeFlatEntityMapsAndRelatedFlatEntityMapsInAllFlatEntityMapsThroughMutation(
|
||||
{
|
||||
allFlatEntityMaps: optimisticAllFlatEntityMaps,
|
||||
flatEntityMapsAndRelatedFlatEntityMaps:
|
||||
rowLevelPermissionPredicateResult.optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
},
|
||||
);
|
||||
|
||||
if (rowLevelPermissionPredicateResult.status === 'fail') {
|
||||
orchestratorFailureReport.rowLevelPermissionPredicate.push(
|
||||
...rowLevelPermissionPredicateResult.errors,
|
||||
);
|
||||
} else {
|
||||
orchestratorActionsReport.rowLevelPermissionPredicate =
|
||||
rowLevelPermissionPredicateResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatServerlessFunctionMaps)) {
|
||||
const {
|
||||
from: fromFlatServerlessFunctionMaps,
|
||||
@@ -871,6 +957,24 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
...aggregatedOrchestratorActionsReport.pageLayoutWidget.created,
|
||||
...aggregatedOrchestratorActionsReport.pageLayoutWidget.updated,
|
||||
///
|
||||
|
||||
// Row level permission predicates
|
||||
...aggregatedOrchestratorActionsReport.rowLevelPermissionPredicate
|
||||
.deleted,
|
||||
...aggregatedOrchestratorActionsReport.rowLevelPermissionPredicate
|
||||
.created,
|
||||
...aggregatedOrchestratorActionsReport.rowLevelPermissionPredicate
|
||||
.updated,
|
||||
///
|
||||
|
||||
// Row level permission predicate groups
|
||||
...aggregatedOrchestratorActionsReport
|
||||
.rowLevelPermissionPredicateGroup.deleted,
|
||||
...aggregatedOrchestratorActionsReport
|
||||
.rowLevelPermissionPredicateGroup.created,
|
||||
...aggregatedOrchestratorActionsReport
|
||||
.rowLevelPermissionPredicateGroup.updated,
|
||||
///
|
||||
],
|
||||
workspaceId,
|
||||
},
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
|
||||
export type CreateRowLevelPermissionPredicateGroupAction = {
|
||||
type: 'create_row_level_permission_predicate_group';
|
||||
rowLevelPermissionPredicateGroup: FlatRowLevelPermissionPredicateGroup;
|
||||
};
|
||||
|
||||
export type UpdateRowLevelPermissionPredicateGroupAction = {
|
||||
type: 'update_row_level_permission_predicate_group';
|
||||
rowLevelPermissionPredicateGroupId: string;
|
||||
updates: FlatEntityPropertiesUpdates<'rowLevelPermissionPredicateGroup'>;
|
||||
};
|
||||
|
||||
export type DeleteRowLevelPermissionPredicateGroupAction = {
|
||||
type: 'delete_row_level_permission_predicate_group';
|
||||
rowLevelPermissionPredicateGroupId: string;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationRowLevelPermissionPredicateGroupActionV2 =
|
||||
| CreateRowLevelPermissionPredicateGroupAction
|
||||
| UpdateRowLevelPermissionPredicateGroupAction
|
||||
| DeleteRowLevelPermissionPredicateGroupAction;
|
||||
|
||||
export type WorkspaceMigrationRowLevelPermissionPredicateGroupActionTypeV2 =
|
||||
WorkspaceMigrationRowLevelPermissionPredicateGroupActionV2['type'];
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRowLevelPermissionPredicateGroupAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action-v2.type';
|
||||
import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type';
|
||||
import { FlatRowLevelPermissionPredicateGroupValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-row-level-permission-predicate-group-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRowLevelPermissionPredicateGroupValidatorService: FlatRowLevelPermissionPredicateGroupValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.rowLevelPermissionPredicateGroup);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup,
|
||||
'created'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateGroupValidatorService.validateFlatRowLevelPermissionPredicateGroupCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create_row_level_permission_predicate_group',
|
||||
rowLevelPermissionPredicateGroup: flatEntityToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup,
|
||||
'deleted'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateGroupValidatorService.validateFlatRowLevelPermissionPredicateGroupDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
flatEntityToValidate: { id: predicateGroupId },
|
||||
} = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete_row_level_permission_predicate_group',
|
||||
rowLevelPermissionPredicateGroupId: predicateGroupId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup,
|
||||
'updated'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateGroupValidatorService.validateFlatRowLevelPermissionPredicateGroupUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateAction: UpdateRowLevelPermissionPredicateGroupAction = {
|
||||
type: 'update_row_level_permission_predicate_group',
|
||||
rowLevelPermissionPredicateGroupId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
|
||||
export type CreateRowLevelPermissionPredicateAction = {
|
||||
type: 'create_row_level_permission_predicate';
|
||||
rowLevelPermissionPredicate: FlatRowLevelPermissionPredicate;
|
||||
};
|
||||
|
||||
export type UpdateRowLevelPermissionPredicateAction = {
|
||||
type: 'update_row_level_permission_predicate';
|
||||
rowLevelPermissionPredicateId: string;
|
||||
updates: FlatEntityPropertiesUpdates<'rowLevelPermissionPredicate'>;
|
||||
};
|
||||
|
||||
export type DeleteRowLevelPermissionPredicateAction = {
|
||||
type: 'delete_row_level_permission_predicate';
|
||||
rowLevelPermissionPredicateId: string;
|
||||
};
|
||||
|
||||
export type DestroyRowLevelPermissionPredicateAction = {
|
||||
type: 'destroy_row_level_permission_predicate';
|
||||
rowLevelPermissionPredicateId: string;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationRowLevelPermissionPredicateActionV2 =
|
||||
| CreateRowLevelPermissionPredicateAction
|
||||
| UpdateRowLevelPermissionPredicateAction
|
||||
| DeleteRowLevelPermissionPredicateAction
|
||||
| DestroyRowLevelPermissionPredicateAction;
|
||||
|
||||
export type WorkspaceMigrationRowLevelPermissionPredicateActionTypeV2 =
|
||||
WorkspaceMigrationRowLevelPermissionPredicateActionV2['type'];
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { UpdateRowLevelPermissionPredicateAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action-v2.type';
|
||||
import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
|
||||
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type';
|
||||
import { FlatRowLevelPermissionPredicateValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-row-level-permission-predicate-validator.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatRowLevelPermissionPredicateValidatorService: FlatRowLevelPermissionPredicateValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.rowLevelPermissionPredicate);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate,
|
||||
'created'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateValidatorService.validateFlatRowLevelPermissionPredicateCreation(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create_row_level_permission_predicate',
|
||||
rowLevelPermissionPredicate: flatEntityToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate,
|
||||
'deleted'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateValidatorService.validateFlatRowLevelPermissionPredicateDeletion(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
flatEntityToValidate: { id: predicateId },
|
||||
} = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete_row_level_permission_predicate',
|
||||
rowLevelPermissionPredicateId: predicateId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>,
|
||||
): FlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate,
|
||||
'updated'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatRowLevelPermissionPredicateValidatorService.validateFlatRowLevelPermissionPredicateUpdate(
|
||||
args,
|
||||
);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityId, flatEntityUpdates } = args;
|
||||
|
||||
const updateAction: UpdateRowLevelPermissionPredicateAction = {
|
||||
type: 'update_row_level_permission_predicate',
|
||||
rowLevelPermissionPredicateId: flatEntityId,
|
||||
updates: flatEntityUpdates,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { RowLevelPermissionPredicateGroupExceptionCode } from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
|
||||
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
|
||||
import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
|
||||
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
|
||||
|
||||
@Injectable()
|
||||
export class FlatRowLevelPermissionPredicateGroupValidatorService {
|
||||
validateFlatRowLevelPermissionPredicateGroupCreation({
|
||||
flatEntityToValidate: flatPredicateGroupToValidate,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>): FailedFlatEntityValidation<FlatRowLevelPermissionPredicateGroup> {
|
||||
const {
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
optimisticFlatPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
} = optimisticFlatEntityMapsAndRelatedFlatEntityMaps as Partial<{
|
||||
flatRowLevelPermissionPredicateGroupMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateGroupMaps;
|
||||
flatRoleMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRoleMaps;
|
||||
}>;
|
||||
const validationResult: FailedFlatEntityValidation<FlatRowLevelPermissionPredicateGroup> =
|
||||
{
|
||||
type: 'create_row_level_permission_predicate_group',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatPredicateGroupToValidate.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingPredicateGroup =
|
||||
optimisticFlatPredicateGroupMaps?.byId[flatPredicateGroupToValidate.id];
|
||||
|
||||
if (isDefined(existingPredicateGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA,
|
||||
message: t`Row level permission predicate group with this id already exists`,
|
||||
userFriendlyMessage: msg`Row level permission predicate group with this id already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
flatPredicateGroupToValidate.parentRowLevelPermissionPredicateGroupId,
|
||||
) &&
|
||||
optimisticFlatPredicateGroupMaps
|
||||
) {
|
||||
const parentGroup = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId:
|
||||
flatPredicateGroupToValidate.parentRowLevelPermissionPredicateGroupId,
|
||||
flatEntityMaps: optimisticFlatPredicateGroupMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(parentGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA,
|
||||
message: t`Parent row level permission predicate group not found`,
|
||||
userFriendlyMessage: msg`Parent row level permission predicate group not found`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const role = flatRoleMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatPredicateGroupToValidate.roleId,
|
||||
flatEntityMaps: flatRoleMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(role)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.ROLE_NOT_FOUND,
|
||||
message: t`Role not found`,
|
||||
userFriendlyMessage: msg`Role not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatRowLevelPermissionPredicateGroupDeletion({
|
||||
flatEntityToValidate: flatPredicateGroupToDelete,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>): FailedFlatEntityValidation<FlatRowLevelPermissionPredicateGroup> {
|
||||
const {
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
optimisticFlatPredicateGroupMaps,
|
||||
} = optimisticFlatEntityMapsAndRelatedFlatEntityMaps as Partial<{
|
||||
flatRowLevelPermissionPredicateGroupMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateGroupMaps;
|
||||
}>;
|
||||
const validationResult: FailedFlatEntityValidation<FlatRowLevelPermissionPredicateGroup> =
|
||||
{
|
||||
type: 'delete_row_level_permission_predicate_group',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatPredicateGroupToDelete.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingPredicateGroup =
|
||||
optimisticFlatPredicateGroupMaps?.byId[flatPredicateGroupToDelete.id];
|
||||
|
||||
if (!isDefined(existingPredicateGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
|
||||
message: t`Row level permission predicate group to delete not found`,
|
||||
userFriendlyMessage: msg`Row level permission predicate group to delete not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatRowLevelPermissionPredicateGroupUpdate({
|
||||
flatEntityId,
|
||||
flatEntityUpdates,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicateGroup
|
||||
>): FailedFlatEntityValidation<FlatRowLevelPermissionPredicateGroup> {
|
||||
const {
|
||||
flatRowLevelPermissionPredicateGroupMaps:
|
||||
optimisticFlatPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
} = optimisticFlatEntityMapsAndRelatedFlatEntityMaps as Partial<{
|
||||
flatRowLevelPermissionPredicateGroupMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateGroupMaps;
|
||||
flatRoleMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRoleMaps;
|
||||
}>;
|
||||
const validationResult: FailedFlatEntityValidation<FlatRowLevelPermissionPredicateGroup> =
|
||||
{
|
||||
type: 'update_row_level_permission_predicate_group',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatEntityId,
|
||||
},
|
||||
};
|
||||
|
||||
const existingPredicateGroup =
|
||||
optimisticFlatPredicateGroupMaps?.byId[flatEntityId];
|
||||
|
||||
if (!isDefined(existingPredicateGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
|
||||
message: t`Row level permission predicate group to update not found`,
|
||||
userFriendlyMessage: msg`Row level permission predicate group to update not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
const updatedPredicateGroup = {
|
||||
...existingPredicateGroup,
|
||||
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
|
||||
updates: flatEntityUpdates,
|
||||
}),
|
||||
};
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
updatedPredicateGroup.parentRowLevelPermissionPredicateGroupId,
|
||||
) &&
|
||||
optimisticFlatPredicateGroupMaps
|
||||
) {
|
||||
const parentGroup = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId:
|
||||
updatedPredicateGroup.parentRowLevelPermissionPredicateGroupId,
|
||||
flatEntityMaps: optimisticFlatPredicateGroupMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(parentGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA,
|
||||
message: t`Parent row level permission predicate group not found`,
|
||||
userFriendlyMessage: msg`Parent row level permission predicate group not found`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const role = flatRoleMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updatedPredicateGroup.roleId,
|
||||
flatEntityMaps: flatRoleMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(role)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateGroupExceptionCode.ROLE_NOT_FOUND,
|
||||
message: t`Role not found`,
|
||||
userFriendlyMessage: msg`Role not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
}
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { RowLevelPermissionPredicateExceptionCode } from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
|
||||
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
|
||||
import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
|
||||
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
|
||||
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
|
||||
|
||||
@Injectable()
|
||||
export class FlatRowLevelPermissionPredicateValidatorService {
|
||||
validateFlatRowLevelPermissionPredicateCreation({
|
||||
flatEntityToValidate: flatPredicateToValidate,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>): FailedFlatEntityValidation<FlatRowLevelPermissionPredicate> {
|
||||
const {
|
||||
flatRowLevelPermissionPredicateMaps: optimisticFlatPredicateMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
} = optimisticFlatEntityMapsAndRelatedFlatEntityMaps as Partial<{
|
||||
flatRowLevelPermissionPredicateMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateMaps;
|
||||
flatFieldMetadataMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatFieldMetadataMaps;
|
||||
flatObjectMetadataMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatObjectMetadataMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateGroupMaps;
|
||||
flatRoleMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRoleMaps;
|
||||
}>;
|
||||
|
||||
const validationResult: FailedFlatEntityValidation<FlatRowLevelPermissionPredicate> =
|
||||
{
|
||||
type: 'create_row_level_permission_predicate',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatPredicateToValidate.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingPredicate =
|
||||
optimisticFlatPredicateMaps?.byId[flatPredicateToValidate.id];
|
||||
|
||||
if (isDefined(existingPredicate)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.INVALID_ROW_LEVEL_PERMISSION_PREDICATE_DATA,
|
||||
message: t`Row level permission predicate with this id already exists`,
|
||||
userFriendlyMessage: msg`Row level permission predicate with this id already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
const fieldMetadata = flatFieldMetadataMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatPredicateToValidate.fieldMetadataId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(fieldMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
message: t`Field metadata not found`,
|
||||
userFriendlyMessage: msg`Field metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
const objectMetadata = flatObjectMetadataMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatPredicateToValidate.objectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(objectMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
message: t`Object metadata not found`,
|
||||
userFriendlyMessage: msg`Object metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(flatPredicateToValidate.rowLevelPermissionPredicateGroupId) &&
|
||||
flatRowLevelPermissionPredicateGroupMaps
|
||||
) {
|
||||
const predicateGroup = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId:
|
||||
flatPredicateToValidate.rowLevelPermissionPredicateGroupId,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(predicateGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.INVALID_ROW_LEVEL_PERMISSION_PREDICATE_DATA,
|
||||
message: t`Row level permission predicate group not found`,
|
||||
userFriendlyMessage: msg`Row level permission predicate group not found`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const role = flatRoleMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatPredicateToValidate.roleId,
|
||||
flatEntityMaps: flatRoleMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(role)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.ROLE_NOT_FOUND,
|
||||
message: t`Role not found`,
|
||||
userFriendlyMessage: msg`Role not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatRowLevelPermissionPredicateDeletion({
|
||||
flatEntityToValidate: flatPredicateToDelete,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
}: FlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>): FailedFlatEntityValidation<FlatRowLevelPermissionPredicate> {
|
||||
const { flatRowLevelPermissionPredicateMaps: optimisticFlatPredicateMaps } =
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps as Partial<{
|
||||
flatRowLevelPermissionPredicateMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateMaps;
|
||||
}>;
|
||||
const validationResult: FailedFlatEntityValidation<FlatRowLevelPermissionPredicate> =
|
||||
{
|
||||
type: 'delete_row_level_permission_predicate',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatPredicateToDelete.id,
|
||||
},
|
||||
};
|
||||
|
||||
const existingPredicate =
|
||||
optimisticFlatPredicateMaps?.byId[flatPredicateToDelete.id];
|
||||
|
||||
if (!isDefined(existingPredicate)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
|
||||
message: t`Row level permission predicate to delete not found`,
|
||||
userFriendlyMessage: msg`Row level permission predicate to delete not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatRowLevelPermissionPredicateUpdate({
|
||||
flatEntityId,
|
||||
flatEntityUpdates,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.rowLevelPermissionPredicate
|
||||
>): FailedFlatEntityValidation<FlatRowLevelPermissionPredicate> {
|
||||
const {
|
||||
flatRowLevelPermissionPredicateMaps: optimisticFlatPredicateMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
} = optimisticFlatEntityMapsAndRelatedFlatEntityMaps as Partial<{
|
||||
flatRowLevelPermissionPredicateMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateMaps;
|
||||
flatFieldMetadataMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatFieldMetadataMaps;
|
||||
flatObjectMetadataMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatObjectMetadataMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRowLevelPermissionPredicateGroupMaps;
|
||||
flatRoleMaps: typeof optimisticFlatEntityMapsAndRelatedFlatEntityMaps.flatRoleMaps;
|
||||
}>;
|
||||
const validationResult: FailedFlatEntityValidation<FlatRowLevelPermissionPredicate> =
|
||||
{
|
||||
type: 'update_row_level_permission_predicate',
|
||||
errors: [],
|
||||
flatEntityMinimalInformation: {
|
||||
id: flatEntityId,
|
||||
},
|
||||
};
|
||||
|
||||
const existingPredicate = optimisticFlatPredicateMaps?.byId[flatEntityId];
|
||||
|
||||
if (!isDefined(existingPredicate)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
|
||||
message: t`Row level permission predicate to update not found`,
|
||||
userFriendlyMessage: msg`Row level permission predicate to update not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
const updatedPredicate = {
|
||||
...existingPredicate,
|
||||
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
|
||||
updates: flatEntityUpdates,
|
||||
}),
|
||||
};
|
||||
|
||||
const fieldMetadata = flatFieldMetadataMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updatedPredicate.fieldMetadataId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(fieldMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
message: t`Field metadata not found`,
|
||||
userFriendlyMessage: msg`Field metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
const objectMetadata = flatObjectMetadataMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updatedPredicate.objectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(objectMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
message: t`Object metadata not found`,
|
||||
userFriendlyMessage: msg`Object metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(updatedPredicate.rowLevelPermissionPredicateGroupId) &&
|
||||
flatRowLevelPermissionPredicateGroupMaps
|
||||
) {
|
||||
const predicateGroup = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updatedPredicate.rowLevelPermissionPredicateGroupId,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(predicateGroup)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.INVALID_ROW_LEVEL_PERMISSION_PREDICATE_DATA,
|
||||
message: t`Row level permission predicate group not found`,
|
||||
userFriendlyMessage: msg`Row level permission predicate group not found`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const role = flatRoleMaps
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updatedPredicate.roleId,
|
||||
flatEntityMaps: flatRoleMaps,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(role)) {
|
||||
validationResult.errors.push({
|
||||
code: RowLevelPermissionPredicateExceptionCode.ROLE_NOT_FOUND,
|
||||
message: t`Role not found`,
|
||||
userFriendlyMessage: msg`Role not found`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -3,17 +3,19 @@ import { Module } from '@nestjs/common';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service';
|
||||
import { FlatAgentValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-agent-validator.service';
|
||||
import { FlatPageLayoutValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-validator.service';
|
||||
import { FlatCronTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service';
|
||||
import { FlatDatabaseEventTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service';
|
||||
import { FlatFieldMetadataValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service';
|
||||
import { FlatIndexValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-index-metadata-validator.service';
|
||||
import { FlatObjectMetadataValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service';
|
||||
import { FlatPageLayoutTabValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-tab-validator.service';
|
||||
import { FlatPageLayoutValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-validator.service';
|
||||
import { FlatPageLayoutWidgetValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-widget-validator.service';
|
||||
import { FlatRoleTargetValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-role-target-validator.service';
|
||||
import { FlatRoleValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-role-validator.service';
|
||||
import { FlatRouteTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service';
|
||||
import { FlatRowLevelPermissionPredicateGroupValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-row-level-permission-predicate-group-validator.service';
|
||||
import { FlatRowLevelPermissionPredicateValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-row-level-permission-predicate-validator.service';
|
||||
import { FlatServerlessFunctionValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service';
|
||||
import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service';
|
||||
import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service';
|
||||
@@ -41,6 +43,8 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace
|
||||
FlatPageLayoutValidatorService,
|
||||
FlatPageLayoutWidgetValidatorService,
|
||||
FlatPageLayoutTabValidatorService,
|
||||
FlatRowLevelPermissionPredicateValidatorService,
|
||||
FlatRowLevelPermissionPredicateGroupValidatorService,
|
||||
],
|
||||
exports: [
|
||||
FlatViewValidatorService,
|
||||
@@ -61,6 +65,8 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace
|
||||
FlatPageLayoutValidatorService,
|
||||
FlatPageLayoutWidgetValidatorService,
|
||||
FlatPageLayoutTabValidatorService,
|
||||
FlatRowLevelPermissionPredicateValidatorService,
|
||||
FlatRowLevelPermissionPredicateGroupValidatorService,
|
||||
],
|
||||
})
|
||||
export class WorkspaceMigrationBuilderValidatorsModule {}
|
||||
|
||||
+7
-1
@@ -8,12 +8,14 @@ import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 's
|
||||
import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service';
|
||||
import { WorkspaceMigrationV2PageLayoutActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout/workspace-migration-v2-page-layout-actions-builder.service';
|
||||
import { WorkspaceMigrationV2PageLayoutTabActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/workspace-migration-v2-page-layout-tab-actions-builder.service';
|
||||
import { WorkspaceMigrationV2PageLayoutWidgetActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-widget/workspace-migration-v2-page-layout-widget-actions-builder.service';
|
||||
import { WorkspaceMigrationV2PageLayoutActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout/workspace-migration-v2-page-layout-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RoleTargetActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/role-target/workspace-migration-v2-role-target-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RoleActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/role/workspace-migration-v2-role-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/workspace-migration-v2-row-level-permission-predicate-group-actions-builder.service';
|
||||
import { WorkspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/workspace-migration-v2-row-level-permission-predicate-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service';
|
||||
import { WorkspaceMigrationV2ViewFilterActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service';
|
||||
@@ -42,6 +44,8 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationV2PageLayoutActionsBuilderService,
|
||||
WorkspaceMigrationV2PageLayoutWidgetActionsBuilderService,
|
||||
WorkspaceMigrationV2PageLayoutTabActionsBuilderService,
|
||||
WorkspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService,
|
||||
WorkspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService,
|
||||
],
|
||||
exports: [
|
||||
WorkspaceMigrationV2ViewActionsBuilderService,
|
||||
@@ -61,6 +65,8 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationV2PageLayoutActionsBuilderService,
|
||||
WorkspaceMigrationV2PageLayoutWidgetActionsBuilderService,
|
||||
WorkspaceMigrationV2PageLayoutTabActionsBuilderService,
|
||||
WorkspaceMigrationV2RowLevelPermissionPredicateActionsBuilderService,
|
||||
WorkspaceMigrationV2RowLevelPermissionPredicateGroupActionsBuilderService,
|
||||
FlatFieldMetadataTypeValidatorService,
|
||||
],
|
||||
})
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { CreateRowLevelPermissionPredicateGroupAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class CreateRowLevelPermissionPredicateGroupActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'create_row_level_permission_predicate_group',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<CreateRowLevelPermissionPredicateGroupAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } = allFlatEntityMaps;
|
||||
const { rowLevelPermissionPredicateGroup } = action;
|
||||
|
||||
const updatedFlatMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: rowLevelPermissionPredicateGroup,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatRowLevelPermissionPredicateGroupMaps: updatedFlatMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<CreateRowLevelPermissionPredicateGroupAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { rowLevelPermissionPredicateGroup } = action;
|
||||
|
||||
const repository =
|
||||
queryRunner.manager.getRepository<RowLevelPermissionPredicateGroupEntity>(
|
||||
RowLevelPermissionPredicateGroupEntity,
|
||||
);
|
||||
|
||||
await repository.insert({
|
||||
...rowLevelPermissionPredicateGroup,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<CreateRowLevelPermissionPredicateGroupAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { DeleteRowLevelPermissionPredicateGroupAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteRowLevelPermissionPredicateGroupActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete_row_level_permission_predicate_group',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<DeleteRowLevelPermissionPredicateGroupAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } = allFlatEntityMaps;
|
||||
const { rowLevelPermissionPredicateGroupId } = action;
|
||||
|
||||
const updatedFlatMaps = deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
entityToDeleteId: rowLevelPermissionPredicateGroupId,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatRowLevelPermissionPredicateGroupMaps: updatedFlatMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<DeleteRowLevelPermissionPredicateGroupAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { rowLevelPermissionPredicateGroupId } = action;
|
||||
|
||||
const repository =
|
||||
queryRunner.manager.getRepository<RowLevelPermissionPredicateGroupEntity>(
|
||||
RowLevelPermissionPredicateGroupEntity,
|
||||
);
|
||||
|
||||
await repository.delete({
|
||||
id: rowLevelPermissionPredicateGroupId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<DeleteRowLevelPermissionPredicateGroupAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
|
||||
import { UpdateRowLevelPermissionPredicateGroupAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate-group/types/workspace-migration-row-level-permission-predicate-group-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateRowLevelPermissionPredicateGroupActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'update_row_level_permission_predicate_group',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<UpdateRowLevelPermissionPredicateGroupAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatRowLevelPermissionPredicateGroupMaps } = allFlatEntityMaps;
|
||||
const { rowLevelPermissionPredicateGroupId } = action;
|
||||
|
||||
const existingGroup = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: rowLevelPermissionPredicateGroupId,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
const updatedGroup = {
|
||||
...existingGroup,
|
||||
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity(action),
|
||||
};
|
||||
|
||||
const updatedFlatMaps = replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: updatedGroup,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatRowLevelPermissionPredicateGroupMaps: updatedFlatMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UpdateRowLevelPermissionPredicateGroupAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner } = context;
|
||||
const { rowLevelPermissionPredicateGroupId } = action;
|
||||
|
||||
const repository =
|
||||
queryRunner.manager.getRepository<RowLevelPermissionPredicateGroupEntity>(
|
||||
RowLevelPermissionPredicateGroupEntity,
|
||||
);
|
||||
|
||||
const update = fromFlatEntityPropertiesUpdatesToPartialFlatEntity(action);
|
||||
|
||||
await repository.update(rowLevelPermissionPredicateGroupId, update);
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<UpdateRowLevelPermissionPredicateGroupAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { CreateRowLevelPermissionPredicateAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class CreateRowLevelPermissionPredicateActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'create_row_level_permission_predicate',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<CreateRowLevelPermissionPredicateAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatRowLevelPermissionPredicateMaps } = allFlatEntityMaps;
|
||||
const { rowLevelPermissionPredicate } = action;
|
||||
|
||||
const updatedFlatMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: rowLevelPermissionPredicate,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatRowLevelPermissionPredicateMaps: updatedFlatMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<CreateRowLevelPermissionPredicateAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { rowLevelPermissionPredicate } = action;
|
||||
|
||||
const repository =
|
||||
queryRunner.manager.getRepository<RowLevelPermissionPredicateEntity>(
|
||||
RowLevelPermissionPredicateEntity,
|
||||
);
|
||||
|
||||
await repository.insert({
|
||||
...rowLevelPermissionPredicate,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<CreateRowLevelPermissionPredicateAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { DeleteRowLevelPermissionPredicateAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteRowLevelPermissionPredicateActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete_row_level_permission_predicate',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<DeleteRowLevelPermissionPredicateAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatRowLevelPermissionPredicateMaps } = allFlatEntityMaps;
|
||||
const { rowLevelPermissionPredicateId } = action;
|
||||
|
||||
const updatedFlatMaps = deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
entityToDeleteId: rowLevelPermissionPredicateId,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatRowLevelPermissionPredicateMaps: updatedFlatMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<DeleteRowLevelPermissionPredicateAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner, workspaceId } = context;
|
||||
const { rowLevelPermissionPredicateId } = action;
|
||||
|
||||
const repository =
|
||||
queryRunner.manager.getRepository<RowLevelPermissionPredicateEntity>(
|
||||
RowLevelPermissionPredicateEntity,
|
||||
);
|
||||
|
||||
await repository.delete({
|
||||
id: rowLevelPermissionPredicateId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<DeleteRowLevelPermissionPredicateAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
|
||||
import { UpdateRowLevelPermissionPredicateAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/row-level-permission-predicate/types/workspace-migration-row-level-permission-predicate-action-v2.type';
|
||||
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateRowLevelPermissionPredicateActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'update_row_level_permission_predicate',
|
||||
) {
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<UpdateRowLevelPermissionPredicateAction>): Partial<AllFlatEntityMaps> {
|
||||
const { flatRowLevelPermissionPredicateMaps } = allFlatEntityMaps;
|
||||
const { rowLevelPermissionPredicateId } = action;
|
||||
|
||||
const existingPredicate = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: rowLevelPermissionPredicateId,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
|
||||
const updatedPredicate = {
|
||||
...existingPredicate,
|
||||
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity(action),
|
||||
};
|
||||
|
||||
const updatedFlatMaps = replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: updatedPredicate,
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatRowLevelPermissionPredicateMaps: updatedFlatMaps,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UpdateRowLevelPermissionPredicateAction>,
|
||||
): Promise<void> {
|
||||
const { action, queryRunner } = context;
|
||||
const { rowLevelPermissionPredicateId } = action;
|
||||
|
||||
const repository =
|
||||
queryRunner.manager.getRepository<RowLevelPermissionPredicateEntity>(
|
||||
RowLevelPermissionPredicateEntity,
|
||||
);
|
||||
|
||||
const update = fromFlatEntityPropertiesUpdatesToPartialFlatEntity(action);
|
||||
|
||||
await repository.update(rowLevelPermissionPredicateId, update);
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerArgs<UpdateRowLevelPermissionPredicateAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+17
-3
@@ -4,9 +4,6 @@ import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-sc
|
||||
import { CreateAgentActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/agent/services/create-agent-action-handler.service';
|
||||
import { DeleteAgentActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/agent/services/delete-agent-action-handler.service';
|
||||
import { UpdateAgentActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/agent/services/update-agent-action-handler.service';
|
||||
import { CreatePageLayoutActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout/services/create-page-layout-action-handler.service';
|
||||
import { DeletePageLayoutActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout/services/delete-page-layout-action-handler.service';
|
||||
import { UpdatePageLayoutActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout/services/update-page-layout-action-handler.service';
|
||||
import { CreateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service';
|
||||
import { DeleteCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service';
|
||||
import { UpdateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service';
|
||||
@@ -27,6 +24,9 @@ import { UpdatePageLayoutTabActionHandlerService } from 'src/engine/workspace-ma
|
||||
import { CreatePageLayoutWidgetActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout-widget/services/create-page-layout-widget-action-handler.service';
|
||||
import { DeletePageLayoutWidgetActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout-widget/services/delete-page-layout-widget-action-handler.service';
|
||||
import { UpdatePageLayoutWidgetActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout-widget/services/update-page-layout-widget-action-handler.service';
|
||||
import { CreatePageLayoutActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout/services/create-page-layout-action-handler.service';
|
||||
import { DeletePageLayoutActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout/services/delete-page-layout-action-handler.service';
|
||||
import { UpdatePageLayoutActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout/services/update-page-layout-action-handler.service';
|
||||
import { CreateRoleTargetActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/role-target/services/create-role-target-action-handler.service';
|
||||
import { DeleteRoleTargetActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/role-target/services/delete-role-target-action-handler.service';
|
||||
import { UpdateRoleTargetActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/role-target/services/update-role-target-action-handler.service';
|
||||
@@ -36,6 +36,12 @@ import { UpdateRoleActionHandlerService } from 'src/engine/workspace-manager/wor
|
||||
import { CreateRouteTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/route-trigger/services/create-route-trigger-action-handler.service';
|
||||
import { DeleteRouteTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/route-trigger/services/delete-route-trigger-action-handler.service';
|
||||
import { UpdateRouteTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/route-trigger/services/update-route-trigger-action-handler.service';
|
||||
import { CreateRowLevelPermissionPredicateGroupActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/row-level-permission-predicate-group/services/create-row-level-permission-predicate-group-action-handler.service';
|
||||
import { DeleteRowLevelPermissionPredicateGroupActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/row-level-permission-predicate-group/services/delete-row-level-permission-predicate-group-action-handler.service';
|
||||
import { UpdateRowLevelPermissionPredicateGroupActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/row-level-permission-predicate-group/services/update-row-level-permission-predicate-group-action-handler.service';
|
||||
import { CreateRowLevelPermissionPredicateActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/row-level-permission-predicate/services/create-row-level-permission-predicate-action-handler.service';
|
||||
import { DeleteRowLevelPermissionPredicateActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/row-level-permission-predicate/services/delete-row-level-permission-predicate-action-handler.service';
|
||||
import { UpdateRowLevelPermissionPredicateActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/row-level-permission-predicate/services/update-row-level-permission-predicate-action-handler.service';
|
||||
import { CreateServerlessFunctionActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/create-serverless-function-action-handler.service';
|
||||
import { DeleteServerlessFunctionActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/delete-serverless-function-action-handler.service';
|
||||
import { UpdateServerlessFunctionActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/serverless-function/services/update-serverless-function-action-handler.service';
|
||||
@@ -121,6 +127,14 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor
|
||||
CreatePageLayoutTabActionHandlerService,
|
||||
UpdatePageLayoutTabActionHandlerService,
|
||||
DeletePageLayoutTabActionHandlerService,
|
||||
|
||||
CreateRowLevelPermissionPredicateActionHandlerService,
|
||||
UpdateRowLevelPermissionPredicateActionHandlerService,
|
||||
DeleteRowLevelPermissionPredicateActionHandlerService,
|
||||
|
||||
CreateRowLevelPermissionPredicateGroupActionHandlerService,
|
||||
UpdateRowLevelPermissionPredicateGroupActionHandlerService,
|
||||
DeleteRowLevelPermissionPredicateGroupActionHandlerService,
|
||||
],
|
||||
})
|
||||
export class WorkspaceSchemaMigrationRunnerActionHandlersModule {}
|
||||
|
||||
Reference in New Issue
Block a user