Polish permission flag definition foundation
This commit is contained in:
@@ -2847,7 +2847,7 @@ type PermissionFlagDefinition {
|
||||
label: String!
|
||||
description: String
|
||||
iconKey: String
|
||||
category: String!
|
||||
permissionType: String!
|
||||
isRelevantForAgents: Boolean!
|
||||
isRelevantForUsers: Boolean!
|
||||
isRelevantForApiKeys: Boolean!
|
||||
@@ -4232,7 +4232,7 @@ input CreatePermissionFlagDefinitionInput {
|
||||
label: String!
|
||||
description: String
|
||||
iconKey: String
|
||||
category: String!
|
||||
permissionType: String!
|
||||
isRelevantForAgents: Boolean
|
||||
isRelevantForUsers: Boolean
|
||||
isRelevantForApiKeys: Boolean
|
||||
@@ -4250,7 +4250,7 @@ input UpdatePermissionFlagDefinitionInputUpdates {
|
||||
label: String
|
||||
description: String
|
||||
iconKey: String
|
||||
category: String
|
||||
permissionType: String
|
||||
isRelevantForAgents: Boolean
|
||||
isRelevantForUsers: Boolean
|
||||
isRelevantForApiKeys: Boolean
|
||||
|
||||
@@ -2497,7 +2497,7 @@ export interface PermissionFlagDefinition {
|
||||
label: Scalars['String']
|
||||
description?: Scalars['String']
|
||||
iconKey?: Scalars['String']
|
||||
category: Scalars['String']
|
||||
permissionType: Scalars['String']
|
||||
isRelevantForAgents: Scalars['Boolean']
|
||||
isRelevantForUsers: Scalars['Boolean']
|
||||
isRelevantForApiKeys: Scalars['Boolean']
|
||||
@@ -5532,7 +5532,7 @@ export interface PermissionFlagDefinitionGenqlSelection{
|
||||
label?: boolean | number
|
||||
description?: boolean | number
|
||||
iconKey?: boolean | number
|
||||
category?: boolean | number
|
||||
permissionType?: boolean | number
|
||||
isRelevantForAgents?: boolean | number
|
||||
isRelevantForUsers?: boolean | number
|
||||
isRelevantForApiKeys?: boolean | number
|
||||
@@ -6263,7 +6263,7 @@ update: UpdateWebhookInputUpdates}
|
||||
|
||||
export interface UpdateWebhookInputUpdates {targetUrl?: (Scalars['String'] | null),operations?: (Scalars['String'][] | null),description?: (Scalars['String'] | null),secret?: (Scalars['String'] | null)}
|
||||
|
||||
export interface CreatePermissionFlagDefinitionInput {id?: (Scalars['UUID'] | null),universalIdentifier?: (Scalars['UUID'] | null),key: Scalars['String'],label: Scalars['String'],description?: (Scalars['String'] | null),iconKey?: (Scalars['String'] | null),category: Scalars['String'],isRelevantForAgents?: (Scalars['Boolean'] | null),isRelevantForUsers?: (Scalars['Boolean'] | null),isRelevantForApiKeys?: (Scalars['Boolean'] | null)}
|
||||
export interface CreatePermissionFlagDefinitionInput {id?: (Scalars['UUID'] | null),universalIdentifier?: (Scalars['UUID'] | null),key: Scalars['String'],label: Scalars['String'],description?: (Scalars['String'] | null),iconKey?: (Scalars['String'] | null),permissionType: Scalars['String'],isRelevantForAgents?: (Scalars['Boolean'] | null),isRelevantForUsers?: (Scalars['Boolean'] | null),isRelevantForApiKeys?: (Scalars['Boolean'] | null)}
|
||||
|
||||
export interface UpdatePermissionFlagDefinitionInput {
|
||||
/** The id of the permission flag definition to update */
|
||||
@@ -6271,7 +6271,7 @@ id: Scalars['UUID'],
|
||||
/** The fields to update */
|
||||
update: UpdatePermissionFlagDefinitionInputUpdates}
|
||||
|
||||
export interface UpdatePermissionFlagDefinitionInputUpdates {label?: (Scalars['String'] | null),description?: (Scalars['String'] | null),iconKey?: (Scalars['String'] | null),category?: (Scalars['String'] | null),isRelevantForAgents?: (Scalars['Boolean'] | null),isRelevantForUsers?: (Scalars['Boolean'] | null),isRelevantForApiKeys?: (Scalars['Boolean'] | null)}
|
||||
export interface UpdatePermissionFlagDefinitionInputUpdates {label?: (Scalars['String'] | null),description?: (Scalars['String'] | null),iconKey?: (Scalars['String'] | null),permissionType?: (Scalars['String'] | null),isRelevantForAgents?: (Scalars['Boolean'] | null),isRelevantForUsers?: (Scalars['Boolean'] | null),isRelevantForApiKeys?: (Scalars['Boolean'] | null)}
|
||||
|
||||
export interface CreateSkillInput {id?: (Scalars['UUID'] | null),name: Scalars['String'],label: Scalars['String'],icon?: (Scalars['String'] | null),description?: (Scalars['String'] | null),content: Scalars['String']}
|
||||
|
||||
|
||||
@@ -5659,7 +5659,7 @@ export default {
|
||||
"iconKey": [
|
||||
1
|
||||
],
|
||||
"category": [
|
||||
"permissionType": [
|
||||
1
|
||||
],
|
||||
"isRelevantForAgents": [
|
||||
@@ -10751,7 +10751,7 @@ export default {
|
||||
"iconKey": [
|
||||
1
|
||||
],
|
||||
"category": [
|
||||
"permissionType": [
|
||||
1
|
||||
],
|
||||
"isRelevantForAgents": [
|
||||
@@ -10788,7 +10788,7 @@ export default {
|
||||
"iconKey": [
|
||||
1
|
||||
],
|
||||
"category": [
|
||||
"permissionType": [
|
||||
1
|
||||
],
|
||||
"isRelevantForAgents": [
|
||||
|
||||
@@ -1150,7 +1150,6 @@ export type CreatePageLayoutWidgetInput = {
|
||||
};
|
||||
|
||||
export type CreatePermissionFlagDefinitionInput = {
|
||||
category: Scalars['String'];
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
iconKey?: InputMaybe<Scalars['String']>;
|
||||
id?: InputMaybe<Scalars['UUID']>;
|
||||
@@ -1159,6 +1158,7 @@ export type CreatePermissionFlagDefinitionInput = {
|
||||
isRelevantForUsers?: InputMaybe<Scalars['Boolean']>;
|
||||
key: Scalars['String'];
|
||||
label: Scalars['String'];
|
||||
permissionType: Scalars['String'];
|
||||
universalIdentifier?: InputMaybe<Scalars['UUID']>;
|
||||
};
|
||||
|
||||
@@ -3938,7 +3938,6 @@ export type PermissionFlag = {
|
||||
export type PermissionFlagDefinition = {
|
||||
__typename?: 'PermissionFlagDefinition';
|
||||
applicationId: Scalars['UUID'];
|
||||
category: Scalars['String'];
|
||||
createdAt: Scalars['DateTime'];
|
||||
description?: Maybe<Scalars['String']>;
|
||||
iconKey?: Maybe<Scalars['String']>;
|
||||
@@ -3949,6 +3948,7 @@ export type PermissionFlagDefinition = {
|
||||
isRelevantForUsers: Scalars['Boolean'];
|
||||
key: Scalars['String'];
|
||||
label: Scalars['String'];
|
||||
permissionType: Scalars['String'];
|
||||
universalIdentifier: Scalars['UUID'];
|
||||
updatedAt: Scalars['DateTime'];
|
||||
};
|
||||
@@ -5227,13 +5227,13 @@ export type UpdatePermissionFlagDefinitionInput = {
|
||||
};
|
||||
|
||||
export type UpdatePermissionFlagDefinitionInputUpdates = {
|
||||
category?: InputMaybe<Scalars['String']>;
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
iconKey?: InputMaybe<Scalars['String']>;
|
||||
isRelevantForAgents?: InputMaybe<Scalars['Boolean']>;
|
||||
isRelevantForApiKeys?: InputMaybe<Scalars['Boolean']>;
|
||||
isRelevantForUsers?: InputMaybe<Scalars['Boolean']>;
|
||||
label?: InputMaybe<Scalars['String']>;
|
||||
permissionType?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type UpdateRoleInput = {
|
||||
|
||||
+3
-1
@@ -130,7 +130,9 @@ export abstract class WorkspaceCommandRunner<
|
||||
});
|
||||
|
||||
if (report.fail.length > 0) {
|
||||
throw new Error(`Command failed for ${report.fail.length} workspace(s)`);
|
||||
throw new Error(
|
||||
`Command failed for ${report.fail.length} workspace(s)`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.log(chalk.blue('Command completed!'));
|
||||
|
||||
+8
-6
@@ -18,7 +18,7 @@ export class PermissionFlagDefinitionSyncableEntityFastInstanceCommand
|
||||
"label" varchar NOT NULL,
|
||||
"description" text,
|
||||
"iconKey" varchar,
|
||||
"category" varchar NOT NULL,
|
||||
"permissionType" varchar NOT NULL,
|
||||
"isRelevantForAgents" boolean NOT NULL DEFAULT false,
|
||||
"isRelevantForUsers" boolean NOT NULL DEFAULT false,
|
||||
"isRelevantForApiKeys" boolean NOT NULL DEFAULT false,
|
||||
@@ -55,17 +55,19 @@ export class PermissionFlagDefinitionSyncableEntityFastInstanceCommand
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagDefinition" DROP CONSTRAINT "FK_PERMISSION_FLAG_DEFINITION_APPLICATION"`,
|
||||
`ALTER TABLE "core"."permissionFlagDefinition" DROP CONSTRAINT IF EXISTS "FK_PERMISSION_FLAG_DEFINITION_APPLICATION"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."permissionFlagDefinition" DROP CONSTRAINT "FK_PERMISSION_FLAG_DEFINITION_WORKSPACE"`,
|
||||
`ALTER TABLE "core"."permissionFlagDefinition" DROP CONSTRAINT IF EXISTS "FK_PERMISSION_FLAG_DEFINITION_WORKSPACE"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "core"."IDX_PERMISSION_FLAG_DEFINITION_WORKSPACE_UNIVERSAL_IDENTIFIER"`,
|
||||
`DROP INDEX IF EXISTS "core"."IDX_PERMISSION_FLAG_DEFINITION_WORKSPACE_UNIVERSAL_IDENTIFIER"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "core"."IDX_PERMISSION_FLAG_DEFINITION_APPLICATION_ID"`,
|
||||
`DROP INDEX IF EXISTS "core"."IDX_PERMISSION_FLAG_DEFINITION_APPLICATION_ID"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP TABLE IF EXISTS "core"."permissionFlagDefinition"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "core"."permissionFlagDefinition"`);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1224,7 +1224,7 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
category: {
|
||||
permissionType: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ export const FLAT_PERMISSION_FLAG_DEFINITION_EDITABLE_PROPERTIES = [
|
||||
'label',
|
||||
'description',
|
||||
'iconKey',
|
||||
'category',
|
||||
'permissionType',
|
||||
'isRelevantForAgents',
|
||||
'isRelevantForUsers',
|
||||
'isRelevantForApiKeys',
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ export const fromCreatePermissionFlagDefinitionInputToFlatPermissionFlagDefiniti
|
||||
label,
|
||||
description: description ?? null,
|
||||
iconKey: iconKey ?? null,
|
||||
category: createPermissionFlagDefinitionInput.category,
|
||||
permissionType: createPermissionFlagDefinitionInput.permissionType,
|
||||
isRelevantForAgents:
|
||||
createPermissionFlagDefinitionInput.isRelevantForAgents ?? false,
|
||||
isRelevantForUsers:
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ export const fromFlatPermissionFlagDefinitionToPermissionFlagDefinitionDto = (
|
||||
label: flatDefinition.label,
|
||||
description: flatDefinition.description,
|
||||
iconKey: flatDefinition.iconKey,
|
||||
category: flatDefinition.category,
|
||||
permissionType: flatDefinition.permissionType,
|
||||
isRelevantForAgents: flatDefinition.isRelevantForAgents,
|
||||
isRelevantForUsers: flatDefinition.isRelevantForUsers,
|
||||
isRelevantForApiKeys: flatDefinition.isRelevantForApiKeys,
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
export const PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES = [
|
||||
'settings',
|
||||
'tool',
|
||||
] as const;
|
||||
|
||||
export type PermissionFlagDefinitionPermissionType =
|
||||
(typeof PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES)[number];
|
||||
+7
-3
@@ -10,6 +10,10 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import {
|
||||
PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES,
|
||||
type PermissionFlagDefinitionPermissionType,
|
||||
} from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
|
||||
@InputType()
|
||||
export class CreatePermissionFlagDefinitionInput {
|
||||
@@ -43,9 +47,9 @@ export class CreatePermissionFlagDefinitionInput {
|
||||
@Field({ nullable: true })
|
||||
iconKey?: string;
|
||||
|
||||
@IsIn(['settings', 'tool'])
|
||||
@Field()
|
||||
category: 'settings' | 'tool';
|
||||
@IsIn(PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES)
|
||||
@Field(() => String)
|
||||
permissionType: PermissionFlagDefinitionPermissionType;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
|
||||
+7
-3
@@ -11,6 +11,10 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import {
|
||||
PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES,
|
||||
type PermissionFlagDefinitionPermissionType,
|
||||
} from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
|
||||
@ObjectType('PermissionFlagDefinition')
|
||||
export class PermissionFlagDefinitionDTO {
|
||||
@@ -44,9 +48,9 @@ export class PermissionFlagDefinitionDTO {
|
||||
@Field(() => String, { nullable: true })
|
||||
iconKey: string | null;
|
||||
|
||||
@IsIn(['settings', 'tool'])
|
||||
@Field()
|
||||
category: 'settings' | 'tool';
|
||||
@IsIn(PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES)
|
||||
@Field(() => String)
|
||||
permissionType: PermissionFlagDefinitionPermissionType;
|
||||
|
||||
@IsBoolean()
|
||||
@Field()
|
||||
|
||||
+7
-3
@@ -12,6 +12,10 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import {
|
||||
PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES,
|
||||
type PermissionFlagDefinitionPermissionType,
|
||||
} from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
|
||||
@InputType()
|
||||
export class UpdatePermissionFlagDefinitionInputUpdates {
|
||||
@@ -31,9 +35,9 @@ export class UpdatePermissionFlagDefinitionInputUpdates {
|
||||
iconKey?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(['settings', 'tool'])
|
||||
@Field({ nullable: true })
|
||||
category?: 'settings' | 'tool';
|
||||
@IsIn(PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES)
|
||||
@Field(() => String, { nullable: true })
|
||||
permissionType?: PermissionFlagDefinitionPermissionType;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import {
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { type PermissionFlagDefinitionPermissionType } from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
|
||||
@Entity('permissionFlagDefinition')
|
||||
@@ -33,7 +34,7 @@ export class PermissionFlagDefinitionEntity extends SyncableEntity {
|
||||
iconKey: string | null;
|
||||
|
||||
@Column({ nullable: false, type: 'varchar' })
|
||||
category: 'settings' | 'tool';
|
||||
permissionType: PermissionFlagDefinitionPermissionType;
|
||||
|
||||
@Column({ nullable: false, type: 'boolean', default: false })
|
||||
isRelevantForAgents: boolean;
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ export enum PermissionFlagDefinitionExceptionCode {
|
||||
PERMISSION_FLAG_DEFINITION_ALREADY_EXISTS = 'PERMISSION_FLAG_DEFINITION_ALREADY_EXISTS',
|
||||
INVALID_PERMISSION_FLAG_DEFINITION_INPUT = 'INVALID_PERMISSION_FLAG_DEFINITION_INPUT',
|
||||
INVALID_PERMISSION_FLAG_DEFINITION_KEY = 'INVALID_PERMISSION_FLAG_DEFINITION_KEY',
|
||||
INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY = 'INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY',
|
||||
INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE = 'INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE',
|
||||
PERMISSION_FLAG_DEFINITION_KEY_IMMUTABLE = 'PERMISSION_FLAG_DEFINITION_KEY_IMMUTABLE',
|
||||
PERMISSION_FLAG_DEFINITION_APPLICATION_IMMUTABLE = 'PERMISSION_FLAG_DEFINITION_APPLICATION_IMMUTABLE',
|
||||
PERMISSION_FLAG_DEFINITION_IS_STANDARD = 'PERMISSION_FLAG_DEFINITION_IS_STANDARD',
|
||||
@@ -28,8 +28,8 @@ const getPermissionFlagDefinitionExceptionUserFriendlyMessage = (
|
||||
return msg`Invalid permission flag definition input.`;
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_KEY:
|
||||
return msg`Invalid permission flag definition key.`;
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY:
|
||||
return msg`Invalid permission flag definition category.`;
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE:
|
||||
return msg`Invalid permission flag definition permission type.`;
|
||||
case PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_KEY_IMMUTABLE:
|
||||
return msg`Permission flag definition key cannot be changed.`;
|
||||
case PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_APPLICATION_IMMUTABLE:
|
||||
|
||||
-7
@@ -1,11 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { FlatPermissionFlagDefinitionModule } from 'src/engine/metadata-modules/flat-permission-flag-definition/flat-permission-flag-definition.module';
|
||||
import { PermissionFlagDefinitionEntity } from 'src/engine/metadata-modules/permission-flag-definition/entities/permission-flag-definition.entity';
|
||||
import { PermissionFlagDefinitionResolver } from 'src/engine/metadata-modules/permission-flag-definition/permission-flag-definition.resolver';
|
||||
import { PermissionFlagDefinitionService } from 'src/engine/metadata-modules/permission-flag-definition/permission-flag-definition.service';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
@@ -14,10 +11,6 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([
|
||||
ApplicationEntity,
|
||||
PermissionFlagDefinitionEntity,
|
||||
]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
|
||||
+25
-47
@@ -1,60 +1,41 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
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 { fromCreatePermissionFlagDefinitionInputToFlatPermissionFlagDefinitionToCreate } from 'src/engine/metadata-modules/flat-permission-flag-definition/utils/from-create-permission-flag-definition-input-to-flat-permission-flag-definition-to-create.util';
|
||||
import { fromDeletePermissionFlagDefinitionInputToFlatPermissionFlagDefinitionOrThrow } from 'src/engine/metadata-modules/flat-permission-flag-definition/utils/from-delete-permission-flag-definition-input-to-flat-permission-flag-definition-or-throw.util';
|
||||
import { fromFlatPermissionFlagDefinitionToPermissionFlagDefinitionDto } from 'src/engine/metadata-modules/flat-permission-flag-definition/utils/from-flat-permission-flag-definition-to-permission-flag-definition-dto.util';
|
||||
import { fromPermissionFlagDefinitionEntityToFlatPermissionFlagDefinition } from 'src/engine/metadata-modules/flat-permission-flag-definition/utils/from-permission-flag-definition-entity-to-flat-permission-flag-definition.util';
|
||||
import { fromUpdatePermissionFlagDefinitionInputToFlatPermissionFlagDefinitionToUpdateOrThrow } from 'src/engine/metadata-modules/flat-permission-flag-definition/utils/from-update-permission-flag-definition-input-to-flat-permission-flag-definition-to-update-or-throw.util';
|
||||
import { type CreatePermissionFlagDefinitionInput } from 'src/engine/metadata-modules/permission-flag-definition/dtos/create-permission-flag-definition.input';
|
||||
import { type PermissionFlagDefinitionDTO } from 'src/engine/metadata-modules/permission-flag-definition/dtos/permission-flag-definition.dto';
|
||||
import { type UpdatePermissionFlagDefinitionInput } from 'src/engine/metadata-modules/permission-flag-definition/dtos/update-permission-flag-definition.input';
|
||||
import { PermissionFlagDefinitionEntity } from 'src/engine/metadata-modules/permission-flag-definition/entities/permission-flag-definition.entity';
|
||||
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
@Injectable()
|
||||
export class PermissionFlagDefinitionService {
|
||||
constructor(
|
||||
@InjectRepository(PermissionFlagDefinitionEntity)
|
||||
private readonly permissionFlagDefinitionRepository: Repository<PermissionFlagDefinitionEntity>,
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async findAll(workspaceId: string): Promise<PermissionFlagDefinitionDTO[]> {
|
||||
const [definitions, applications] = await Promise.all([
|
||||
this.permissionFlagDefinitionRepository.find({
|
||||
where: { workspaceId },
|
||||
order: { createdAt: 'ASC' },
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
}),
|
||||
]);
|
||||
const { flatPermissionFlagDefinitionMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPermissionFlagDefinitionMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const applicationIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(applications);
|
||||
|
||||
return definitions
|
||||
.map((entity) =>
|
||||
fromPermissionFlagDefinitionEntityToFlatPermissionFlagDefinition({
|
||||
entity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}),
|
||||
)
|
||||
return Object.values(flatPermissionFlagDefinitionMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.sort((a, b) => a.createdAt.localeCompare(b.createdAt))
|
||||
.map(fromFlatPermissionFlagDefinitionToPermissionFlagDefinitionDto);
|
||||
}
|
||||
|
||||
@@ -62,28 +43,25 @@ export class PermissionFlagDefinitionService {
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<PermissionFlagDefinitionDTO | null> {
|
||||
const [definition, applications] = await Promise.all([
|
||||
this.permissionFlagDefinitionRepository.findOne({
|
||||
where: { id, workspaceId },
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
}),
|
||||
]);
|
||||
const { flatPermissionFlagDefinitionMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPermissionFlagDefinitionMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
if (!isDefined(definition)) {
|
||||
const flatPermissionFlagDefinition = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatPermissionFlagDefinitionMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatPermissionFlagDefinition)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const applicationIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(applications);
|
||||
|
||||
return fromFlatPermissionFlagDefinitionToPermissionFlagDefinitionDto(
|
||||
fromPermissionFlagDefinitionEntityToFlatPermissionFlagDefinition({
|
||||
entity: definition,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}),
|
||||
flatPermissionFlagDefinition,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ export const permissionFlagDefinitionGraphqlApiExceptionHandler = (
|
||||
throw new ForbiddenError(error);
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_INPUT:
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_KEY:
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY:
|
||||
case PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE:
|
||||
case PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_KEY_IMMUTABLE:
|
||||
case PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_APPLICATION_IMMUTABLE:
|
||||
case PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_IN_USE:
|
||||
|
||||
+1
-4
@@ -13,10 +13,7 @@ import { permissionFlagDefinitionGraphqlApiExceptionHandler } from 'src/engine/m
|
||||
export class PermissionFlagDefinitionGraphqlApiExceptionFilter
|
||||
implements ExceptionFilter
|
||||
{
|
||||
catch(
|
||||
exception: PermissionFlagDefinitionException,
|
||||
_host: ExecutionContext,
|
||||
) {
|
||||
catch(exception: PermissionFlagDefinitionException, _host: ExecutionContext) {
|
||||
return permissionFlagDefinitionGraphqlApiExceptionHandler(exception);
|
||||
}
|
||||
}
|
||||
|
||||
+28
-26
@@ -1,5 +1,7 @@
|
||||
import { type PermissionFlagType } from 'twenty-shared/constants';
|
||||
|
||||
import { type PermissionFlagDefinitionPermissionType } from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
|
||||
// Each entry maps a PermissionFlagType enum key to a stable universalIdentifier
|
||||
// plus the metadata used to render the flag in the Roles UI. Adding a new
|
||||
// built-in flag requires:
|
||||
@@ -14,7 +16,7 @@ export type StandardPermissionFlagDefinitionMetadata = {
|
||||
label: string;
|
||||
description: string | null;
|
||||
iconKey: string | null;
|
||||
category: 'settings' | 'tool';
|
||||
permissionType: PermissionFlagDefinitionPermissionType;
|
||||
isRelevantForAgents: boolean;
|
||||
isRelevantForUsers: boolean;
|
||||
isRelevantForApiKeys: boolean;
|
||||
@@ -26,7 +28,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'API Keys and Webhooks',
|
||||
description: 'Manage API keys and webhooks',
|
||||
iconKey: 'IconApi',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -36,7 +38,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Workspace',
|
||||
description: 'Manage workspace settings',
|
||||
iconKey: 'IconBuildingSkyscraper',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -46,7 +48,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Workspace Members',
|
||||
description: 'Manage workspace members',
|
||||
iconKey: 'IconUsers',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -56,7 +58,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Roles',
|
||||
description: 'Manage roles and permissions',
|
||||
iconKey: 'IconShieldLock',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -66,7 +68,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Data Model',
|
||||
description: 'Manage objects and fields',
|
||||
iconKey: 'IconHierarchy2',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -76,7 +78,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Security',
|
||||
description: 'Manage security settings',
|
||||
iconKey: 'IconLock',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -86,7 +88,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Workflows',
|
||||
description: 'Manage workflows and logic functions',
|
||||
iconKey: 'IconSettingsAutomation',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -96,7 +98,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Impersonate',
|
||||
description: 'Impersonate other workspace members',
|
||||
iconKey: 'IconUser',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -106,7 +108,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'SSO Bypass',
|
||||
description: 'Bypass single sign-on requirements',
|
||||
iconKey: 'IconKey',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -116,7 +118,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Applications',
|
||||
description: 'Manage installed applications',
|
||||
iconKey: 'IconApps',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -126,7 +128,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Marketplace Apps',
|
||||
description: 'Browse and install marketplace apps',
|
||||
iconKey: 'IconShoppingBag',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -136,7 +138,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Layouts',
|
||||
description: 'Manage page layouts',
|
||||
iconKey: 'IconLayout',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -146,7 +148,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Billing',
|
||||
description: 'Manage billing and subscriptions',
|
||||
iconKey: 'IconCreditCard',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -156,7 +158,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'AI Settings',
|
||||
description: 'Manage AI provider settings',
|
||||
iconKey: 'IconBrain',
|
||||
category: 'settings',
|
||||
permissionType: 'settings',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -166,7 +168,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'AI',
|
||||
description: 'Use AI features',
|
||||
iconKey: 'IconSparkles',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: true,
|
||||
@@ -176,7 +178,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Views',
|
||||
description: 'Read and write views',
|
||||
iconKey: 'IconLayoutGrid',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: true,
|
||||
@@ -186,7 +188,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Upload File',
|
||||
description: 'Upload files to the workspace',
|
||||
iconKey: 'IconUpload',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: true,
|
||||
@@ -196,7 +198,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Download File',
|
||||
description: 'Download files from the workspace',
|
||||
iconKey: 'IconDownload',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: true,
|
||||
@@ -206,7 +208,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Send Email',
|
||||
description: 'Send emails on behalf of users',
|
||||
iconKey: 'IconAt',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: false,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -216,7 +218,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'HTTP Request',
|
||||
description: 'Make outbound HTTP requests',
|
||||
iconKey: 'IconApi',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: false,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -226,7 +228,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Code Interpreter',
|
||||
description: 'Run code to analyze files and data',
|
||||
iconKey: 'IconCode',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -236,7 +238,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Import CSV',
|
||||
description: 'Import records from CSV files',
|
||||
iconKey: 'IconFileImport',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -246,7 +248,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Export CSV',
|
||||
description: 'Export records to CSV files',
|
||||
iconKey: 'IconFileExport',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: false,
|
||||
isRelevantForUsers: true,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -256,7 +258,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Connected Accounts',
|
||||
description: 'Read connected email and calendar accounts',
|
||||
iconKey: 'IconMail',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: false,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -266,7 +268,7 @@ export const STANDARD_PERMISSION_FLAG_DEFINITION = {
|
||||
label: 'Profile Information',
|
||||
description: 'Read profile information',
|
||||
iconKey: 'IconUser',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: false,
|
||||
isRelevantForApiKeys: false,
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ export const createStandardPermissionFlagDefinitionFlatMetadata = ({
|
||||
label: metadata.label,
|
||||
description: metadata.description,
|
||||
iconKey: metadata.iconKey,
|
||||
category: metadata.category,
|
||||
permissionType: metadata.permissionType,
|
||||
isRelevantForAgents: metadata.isRelevantForAgents,
|
||||
isRelevantForUsers: metadata.isRelevantForUsers,
|
||||
isRelevantForApiKeys: metadata.isRelevantForApiKeys,
|
||||
|
||||
+138
-4
@@ -7,6 +7,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatPermissionFlag } from 'src/engine/metadata-modules/flat-permission-flag/types/flat-permission-flag.type';
|
||||
import { type FlatPermissionFlagDefinition } from 'src/engine/metadata-modules/flat-permission-flag-definition/types/flat-permission-flag-definition.type';
|
||||
import { type PermissionFlagDefinitionPermissionType } from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
import { PermissionFlagDefinitionExceptionCode } from 'src/engine/metadata-modules/permission-flag-definition/permission-flag-definition.exception';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { FlatPermissionFlagDefinitionValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-permission-flag-definition-validator.service';
|
||||
@@ -21,7 +22,7 @@ const buildFlatDefinition = (
|
||||
label: 'Test Flag',
|
||||
description: 'A flag for tests',
|
||||
iconKey: 'IconTest',
|
||||
category: 'tool',
|
||||
permissionType: 'tool',
|
||||
isRelevantForAgents: true,
|
||||
isRelevantForUsers: false,
|
||||
isRelevantForApiKeys: false,
|
||||
@@ -100,17 +101,17 @@ describe('FlatPermissionFlagDefinitionValidatorService', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects an unknown category', () => {
|
||||
it('rejects an unknown permission type', () => {
|
||||
const result = service.validateFlatPermissionFlagDefinitionCreation(
|
||||
buildArgs(
|
||||
buildFlatDefinition({
|
||||
category: 'invalid' as 'settings' | 'tool',
|
||||
permissionType: 'invalid' as PermissionFlagDefinitionPermissionType,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
expect(result.errors.map((error) => error.code)).toContain(
|
||||
PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY,
|
||||
PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -131,9 +132,50 @@ describe('FlatPermissionFlagDefinitionValidatorService', () => {
|
||||
PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_ALREADY_EXISTS,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a duplicate universal identifier', () => {
|
||||
const existing = buildFlatDefinition();
|
||||
const optimisticMaps = buildEmptyMaps();
|
||||
optimisticMaps.byUniversalIdentifier[existing.universalIdentifier] =
|
||||
existing;
|
||||
|
||||
const result = service.validateFlatPermissionFlagDefinitionCreation(
|
||||
buildArgs(
|
||||
buildFlatDefinition({
|
||||
id: '00000000-0000-0000-0000-000000000002',
|
||||
key: 'ANOTHER_TEST_FLAG',
|
||||
}),
|
||||
optimisticMaps,
|
||||
),
|
||||
);
|
||||
|
||||
expect(result.errors.map((error) => error.code)).toContain(
|
||||
PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_ALREADY_EXISTS,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateFlatPermissionFlagDefinitionUpdate', () => {
|
||||
it('passes for a valid update', () => {
|
||||
const existing = buildFlatDefinition();
|
||||
const optimisticMaps = buildEmptyMaps();
|
||||
optimisticMaps.byUniversalIdentifier[existing.universalIdentifier] =
|
||||
existing;
|
||||
|
||||
const result = service.validateFlatPermissionFlagDefinitionUpdate({
|
||||
universalIdentifier: existing.universalIdentifier,
|
||||
flatEntityUpdate: { label: 'Updated Label' },
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatPermissionFlagDefinitionMaps: optimisticMaps,
|
||||
},
|
||||
buildOptions: {} as never,
|
||||
} as unknown as Parameters<
|
||||
FlatPermissionFlagDefinitionValidatorService['validateFlatPermissionFlagDefinitionUpdate']
|
||||
>[0]);
|
||||
|
||||
expect(result.errors).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('rejects updating the immutable key field', () => {
|
||||
const existing = buildFlatDefinition({ key: 'ORIGINAL_KEY' });
|
||||
const optimisticMaps = buildEmptyMaps();
|
||||
@@ -172,9 +214,101 @@ describe('FlatPermissionFlagDefinitionValidatorService', () => {
|
||||
PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_NOT_FOUND,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects updating a standard definition from a custom application', () => {
|
||||
const existing = buildFlatDefinition({
|
||||
applicationUniversalIdentifier:
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier,
|
||||
});
|
||||
const optimisticMaps = buildEmptyMaps();
|
||||
optimisticMaps.byUniversalIdentifier[existing.universalIdentifier] =
|
||||
existing;
|
||||
|
||||
const result = service.validateFlatPermissionFlagDefinitionUpdate({
|
||||
universalIdentifier: existing.universalIdentifier,
|
||||
flatEntityUpdate: { label: 'Updated Label' },
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatPermissionFlagDefinitionMaps: optimisticMaps,
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
'00000000-0000-0000-0000-000000000aaa',
|
||||
},
|
||||
} as unknown as Parameters<
|
||||
FlatPermissionFlagDefinitionValidatorService['validateFlatPermissionFlagDefinitionUpdate']
|
||||
>[0]);
|
||||
|
||||
expect(result.errors.map((error) => error.code)).toContain(
|
||||
PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_IS_STANDARD,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects updating to an unknown permission type', () => {
|
||||
const existing = buildFlatDefinition();
|
||||
const optimisticMaps = buildEmptyMaps();
|
||||
optimisticMaps.byUniversalIdentifier[existing.universalIdentifier] =
|
||||
existing;
|
||||
|
||||
const result = service.validateFlatPermissionFlagDefinitionUpdate({
|
||||
universalIdentifier: existing.universalIdentifier,
|
||||
flatEntityUpdate: {
|
||||
permissionType: 'invalid' as PermissionFlagDefinitionPermissionType,
|
||||
},
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatPermissionFlagDefinitionMaps: optimisticMaps,
|
||||
},
|
||||
buildOptions: {} as never,
|
||||
} as unknown as Parameters<
|
||||
FlatPermissionFlagDefinitionValidatorService['validateFlatPermissionFlagDefinitionUpdate']
|
||||
>[0]);
|
||||
|
||||
expect(result.errors.map((error) => error.code)).toContain(
|
||||
PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateFlatPermissionFlagDefinitionDeletion', () => {
|
||||
it('passes for a valid deletion', () => {
|
||||
const existing = buildFlatDefinition();
|
||||
const optimisticMaps = buildEmptyMaps();
|
||||
optimisticMaps.byUniversalIdentifier[existing.universalIdentifier] =
|
||||
existing;
|
||||
|
||||
const result = service.validateFlatPermissionFlagDefinitionDeletion({
|
||||
flatEntityToValidate: existing,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatPermissionFlagDefinitionMaps: optimisticMaps,
|
||||
flatPermissionFlagMaps: buildEmptyPermissionFlagMaps(),
|
||||
},
|
||||
buildOptions: {} as never,
|
||||
} as unknown as Parameters<
|
||||
FlatPermissionFlagDefinitionValidatorService['validateFlatPermissionFlagDefinitionDeletion']
|
||||
>[0]);
|
||||
|
||||
expect(result.errors).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('returns not-found if no existing definition matches the universalIdentifier', () => {
|
||||
const result = service.validateFlatPermissionFlagDefinitionDeletion({
|
||||
flatEntityToValidate: buildFlatDefinition({
|
||||
universalIdentifier: '00000000-0000-0000-0000-deadbeefdead',
|
||||
}),
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatPermissionFlagDefinitionMaps: buildEmptyMaps(),
|
||||
flatPermissionFlagMaps: buildEmptyPermissionFlagMaps(),
|
||||
},
|
||||
buildOptions: {} as never,
|
||||
} as unknown as Parameters<
|
||||
FlatPermissionFlagDefinitionValidatorService['validateFlatPermissionFlagDefinitionDeletion']
|
||||
>[0]);
|
||||
|
||||
expect(result.errors.map((error) => error.code)).toContain(
|
||||
PermissionFlagDefinitionExceptionCode.PERMISSION_FLAG_DEFINITION_NOT_FOUND,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects deleting a standard definition from a custom application', () => {
|
||||
const existing = buildFlatDefinition({
|
||||
applicationUniversalIdentifier:
|
||||
|
||||
+12
-13
@@ -6,6 +6,7 @@ import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES } from 'src/engine/metadata-modules/permission-flag-definition/constants/permission-flag-definition-permission-type.constant';
|
||||
import { PermissionFlagDefinitionExceptionCode } from 'src/engine/metadata-modules/permission-flag-definition/permission-flag-definition.exception';
|
||||
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
|
||||
import { isCallerTwentyStandardApp } from 'src/engine/metadata-modules/utils/is-caller-twenty-standard-app.util';
|
||||
@@ -14,8 +15,6 @@ import { getEmptyFlatEntityValidationError } from 'src/engine/workspace-manager/
|
||||
import { type FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type';
|
||||
import { type UniversalFlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-validation-args.type';
|
||||
|
||||
const VALID_CATEGORIES = ['settings', 'tool'] as const;
|
||||
|
||||
@Injectable()
|
||||
export class FlatPermissionFlagDefinitionValidatorService {
|
||||
validateFlatPermissionFlagDefinitionCreation({
|
||||
@@ -78,14 +77,14 @@ export class FlatPermissionFlagDefinitionValidatorService {
|
||||
}
|
||||
|
||||
if (
|
||||
!VALID_CATEGORIES.includes(
|
||||
flatPermissionFlagDefinitionToValidate.category as (typeof VALID_CATEGORIES)[number],
|
||||
!PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES.includes(
|
||||
flatPermissionFlagDefinitionToValidate.permissionType,
|
||||
)
|
||||
) {
|
||||
validationResult.errors.push({
|
||||
code: PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY,
|
||||
message: t`Permission flag definition category must be 'settings' or 'tool'`,
|
||||
userFriendlyMessage: msg`Invalid category`,
|
||||
code: PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE,
|
||||
message: t`Permission flag definition permission type must be 'settings' or 'tool'`,
|
||||
userFriendlyMessage: msg`Invalid permission type`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -152,15 +151,15 @@ export class FlatPermissionFlagDefinitionValidatorService {
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(flatEntityUpdate.category) &&
|
||||
!VALID_CATEGORIES.includes(
|
||||
flatEntityUpdate.category as (typeof VALID_CATEGORIES)[number],
|
||||
isDefined(flatEntityUpdate.permissionType) &&
|
||||
!PERMISSION_FLAG_DEFINITION_PERMISSION_TYPES.includes(
|
||||
flatEntityUpdate.permissionType,
|
||||
)
|
||||
) {
|
||||
validationResult.errors.push({
|
||||
code: PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_CATEGORY,
|
||||
message: t`Permission flag definition category must be 'settings' or 'tool'`,
|
||||
userFriendlyMessage: msg`Invalid category`,
|
||||
code: PermissionFlagDefinitionExceptionCode.INVALID_PERMISSION_FLAG_DEFINITION_PERMISSION_TYPE,
|
||||
message: t`Permission flag definition permission type must be 'settings' or 'tool'`,
|
||||
userFriendlyMessage: msg`Invalid permission type`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user