diff --git a/packages/twenty-server/project.json b/packages/twenty-server/project.json index 600f5defa8..59692d0a81 100644 --- a/packages/twenty-server/project.json +++ b/packages/twenty-server/project.json @@ -135,7 +135,8 @@ "options": { "cwd": "packages/twenty-server", "command": "ts-node --transpile-only -P tsconfig.json ../../node_modules/typeorm/cli.js" - } + }, + "dependsOn": ["build"] }, "ts-node": { "executor": "nx:run-commands", diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command.ts new file mode 100644 index 0000000000..5d3b493c19 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command.ts @@ -0,0 +1,166 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { isDefined } from 'twenty-shared/utils'; +import { IsNull, Repository } from 'typeorm'; +import { v4 } from 'uuid'; + +import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; +import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner'; +import { ApplicationService } from 'src/engine/core-modules/application/application.service'; +import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util'; +import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util'; +import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity'; +import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; +import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; +import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-role.constant'; + +@Command({ + name: 'upgrade:1-16:identify-role-metadata', + description: 'Identify standard role metadata', +}) +export class IdentifyRoleMetadataCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner { + constructor( + @InjectRepository(WorkspaceEntity) + protected readonly workspaceRepository: Repository, + @InjectRepository(RoleEntity) + private readonly roleRepository: Repository, + protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager, + protected readonly dataSourceService: DataSourceService, + protected readonly applicationService: ApplicationService, + protected readonly workspaceCacheService: WorkspaceCacheService, + ) { + super(workspaceRepository, twentyORMGlobalManager, dataSourceService); + } + + override async runOnWorkspace({ + workspaceId, + options, + }: RunOnWorkspaceArgs): Promise { + this.logger.log( + `Running identify standard role metadata for workspace ${workspaceId}`, + ); + + const { twentyStandardFlatApplication, workspaceCustomFlatApplication } = + await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow( + { workspaceId }, + ); + + await this.identifyStandardRole({ + workspaceId, + twentyStandardApplicationId: twentyStandardFlatApplication.id, + dryRun: options.dryRun ?? false, + }); + + await this.identifyCustomRoles({ + workspaceId, + workspaceCustomApplicationId: workspaceCustomFlatApplication.id, + dryRun: options.dryRun ?? false, + }); + + const relatedMetadataNames = getMetadataRelatedMetadataNames('role'); + const relatedCacheKeysToInvalidate = relatedMetadataNames.map( + getMetadataFlatEntityMapsKey, + ); + + this.logger.log( + `Invalidating caches: flatRoleMaps ${relatedCacheKeysToInvalidate.join(' ')}`, + ); + if (!options.dryRun) { + await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [ + 'flatRoleMaps', + ...relatedCacheKeysToInvalidate, + ]); + } + } + + private async identifyStandardRole({ + workspaceId, + twentyStandardApplicationId, + dryRun, + }: { + workspaceId: string; + twentyStandardApplicationId: string; + dryRun: boolean; + }): Promise { + const adminRole = await this.roleRepository.findOne({ + select: { + id: true, + label: true, + universalIdentifier: true, + applicationId: true, + }, + where: { + workspaceId, + label: 'Admin', + isEditable: false, + }, + }); + + if (!isDefined(adminRole)) { + this.logger.warn( + `Standard role "Admin" not found for workspace ${workspaceId}, skipping standard role identification`, + ); + + return; + } + + if (isDefined(adminRole.applicationId)) { + this.logger.warn( + `Standard role "Admin" already has applicationId set, skipping`, + ); + + return; + } + + this.logger.log( + ` - Standard role "Admin" (id=${adminRole.id}) -> universalIdentifier=${STANDARD_ROLE.admin.universalIdentifier}`, + ); + + if (!dryRun) { + await this.roleRepository.save({ + id: adminRole.id, + universalIdentifier: STANDARD_ROLE.admin.universalIdentifier, + applicationId: twentyStandardApplicationId, + }); + } + } + + private async identifyCustomRoles({ + workspaceId, + workspaceCustomApplicationId, + dryRun, + }: { + workspaceId: string; + workspaceCustomApplicationId: string; + dryRun: boolean; + }): Promise { + const remainingCustomRoles = await this.roleRepository.find({ + select: { + id: true, + universalIdentifier: true, + applicationId: true, + }, + where: { + workspaceId, + applicationId: IsNull(), + }, + }); + + const customUpdates = remainingCustomRoles.map((roleEntity) => ({ + id: roleEntity.id, + universalIdentifier: roleEntity.universalIdentifier ?? v4(), + applicationId: workspaceCustomApplicationId, + })); + + this.logger.log( + `Found ${customUpdates.length} custom role(s) to update for workspace ${workspaceId}`, + ); + + if (!dryRun) { + await this.roleRepository.save(customUpdates); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command.ts new file mode 100644 index 0000000000..13ce4db25e --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command.ts @@ -0,0 +1,71 @@ +import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { DataSource, Repository } from 'typeorm'; + +import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; +import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner'; +import { makeRoleUniversalIdentifierAndApplicationIdNotNullableQueries } from 'src/database/typeorm/core/migrations/utils/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.util'; +import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; + +@Command({ + name: 'upgrade:1-16:make-role-universal-identifier-and-application-id-not-nullable-migration', + description: + 'Make universalIdentifier and applicationId columns NOT NULL on role table', +}) +export class MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner { + private hasRunOnce = false; + + constructor( + @InjectRepository(WorkspaceEntity) + protected readonly workspaceRepository: Repository, + protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager, + protected readonly dataSourceService: DataSourceService, + @InjectDataSource() + private readonly coreDataSource: DataSource, + ) { + super(workspaceRepository, twentyORMGlobalManager, dataSourceService); + } + + override async runOnWorkspace({ + options, + }: RunOnWorkspaceArgs): Promise { + if (this.hasRunOnce) { + this.logger.warn( + 'Skipping has already been run once MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand', + ); + + return; + } + + if (options.dryRun) { + return; + } + + const queryRunner = this.coreDataSource.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + await makeRoleUniversalIdentifierAndApplicationIdNotNullableQueries( + queryRunner, + ); + + await queryRunner.commitTransaction(); + this.logger.log( + 'Successfully run MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand', + ); + this.hasRunOnce = true; + } catch (error) { + await queryRunner.rollbackTransaction(); + this.logger.error( + `Rolling back MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: ${error.message}`, + ); + } finally { + await queryRunner.release(); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-upgrade-version-command.module.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-upgrade-version-command.module.ts index 614416d787..0dc4b5462b 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-upgrade-version-command.module.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-16/1-16-upgrade-version-command.module.ts @@ -6,6 +6,7 @@ import { BackfillStandardPageLayoutsCommand } from 'src/database/commands/upgrad import { IdentifyAgentMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-agent-metadata.command'; import { IdentifyFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-field-metadata.command'; import { IdentifyObjectMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-object-metadata.command'; +import { IdentifyRoleMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command'; import { IdentifyViewFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-field-metadata.command'; import { IdentifyViewFilterMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-filter-metadata.command'; import { IdentifyViewGroupMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-group-metadata.command'; @@ -13,6 +14,7 @@ import { IdentifyViewMetadataCommand } from 'src/database/commands/upgrade-versi import { MakeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-agent-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-field-metadata-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-object-metadata-universal-identifier-and-application-id-not-nullable-migration.command'; +import { MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-field-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-filter-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-group-universal-identifier-and-application-id-not-nullable-migration.command'; @@ -26,6 +28,7 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { RoleEntity } from 'src/engine/metadata-modules/role/role.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'; @@ -42,6 +45,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace AgentEntity, FieldMetadataEntity, ObjectMetadataEntity, + RoleEntity, ViewEntity, ViewFieldEntity, ViewFilterEntity, @@ -63,6 +67,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace IdentifyAgentMetadataCommand, IdentifyFieldMetadataCommand, IdentifyObjectMetadataCommand, + IdentifyRoleMetadataCommand, IdentifyViewMetadataCommand, IdentifyViewFieldMetadataCommand, IdentifyViewFilterMetadataCommand, @@ -70,6 +75,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace IdentifyViewGroupMetadataCommand, MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, + MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeViewUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, @@ -82,6 +88,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace IdentifyAgentMetadataCommand, IdentifyFieldMetadataCommand, IdentifyObjectMetadataCommand, + IdentifyRoleMetadataCommand, IdentifyViewMetadataCommand, IdentifyViewFieldMetadataCommand, IdentifyViewFilterMetadataCommand, @@ -89,6 +96,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace IdentifyViewGroupMetadataCommand, MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, + MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeViewUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts index bbfaccc25e..12af9c95ab 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts @@ -27,6 +27,7 @@ import { BackfillStandardPageLayoutsCommand } from 'src/database/commands/upgrad import { IdentifyAgentMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-agent-metadata.command'; import { IdentifyFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-field-metadata.command'; import { IdentifyObjectMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-object-metadata.command'; +import { IdentifyRoleMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-role-metadata.command'; import { IdentifyViewFieldMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-field-metadata.command'; import { IdentifyViewFilterMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-filter-metadata.command'; import { IdentifyViewGroupMetadataCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-identify-view-group-metadata.command'; @@ -34,6 +35,7 @@ import { IdentifyViewMetadataCommand } from 'src/database/commands/upgrade-versi import { MakeAgentUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-agent-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-field-metadata-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-object-metadata-universal-identifier-and-application-id-not-nullable-migration.command'; +import { MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-role-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-field-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-filter-universal-identifier-and-application-id-not-nullable-migration.command'; import { MakeViewGroupUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-16/1-16-make-view-group-universal-identifier-and-application-id-not-nullable-migration.command'; @@ -84,6 +86,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { protected readonly identifyAgentMetadataCommand: IdentifyAgentMetadataCommand, protected readonly identifyFieldMetadataCommand: IdentifyFieldMetadataCommand, protected readonly identifyObjectMetadataCommand: IdentifyObjectMetadataCommand, + protected readonly identifyRoleMetadataCommand: IdentifyRoleMetadataCommand, protected readonly identifyViewMetadataCommand: IdentifyViewMetadataCommand, protected readonly identifyViewFieldMetadataCommand: IdentifyViewFieldMetadataCommand, protected readonly identifyViewFilterMetadataCommand: IdentifyViewFilterMetadataCommand, @@ -91,6 +94,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { protected readonly identifyViewGroupMetadataCommand: IdentifyViewGroupMetadataCommand, protected readonly makeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, protected readonly makeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, + protected readonly makeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, protected readonly makeViewUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeViewUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, protected readonly makeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeViewFieldUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, protected readonly makeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeViewFilterUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, @@ -135,6 +139,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { this.identifyAgentMetadataCommand, this.identifyFieldMetadataCommand, this.identifyObjectMetadataCommand, + this.identifyRoleMetadataCommand, this.identifyViewMetadataCommand, this.identifyViewFieldMetadataCommand, this.identifyViewFilterMetadataCommand, @@ -145,6 +150,8 @@ export class UpgradeCommand extends UpgradeCommandRunner { .makeFieldMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, this .makeObjectMetadataUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, + this + .makeRoleUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, this .makeViewUniversalIdentifierAndApplicationIdNotNullableMigrationCommand, this diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/common/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.ts b/packages/twenty-server/src/database/typeorm/core/migrations/common/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.ts new file mode 100644 index 0000000000..2c21134fe5 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/common/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.ts @@ -0,0 +1,63 @@ +import { type MigrationInterface, type QueryRunner } from 'typeorm'; + +import { makeRoleUniversalIdentifierAndApplicationIdNotNullableQueries } from 'src/database/typeorm/core/migrations/utils/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.util'; + +export class MakeRoleUniversalIdentifierAndApplicationIdNotNullable1768213174275 + implements MigrationInterface +{ + name = 'MakeRoleUniversalIdentifierAndApplicationIdNotNullable1768213174275'; + + public async up(queryRunner: QueryRunner): Promise { + const savepointName = + 'sp_make_role_universal_identifier_and_application_id_not_nullable'; + + try { + await queryRunner.query(`SAVEPOINT ${savepointName}`); + + await makeRoleUniversalIdentifierAndApplicationIdNotNullableQueries( + queryRunner, + ); + + await queryRunner.query(`RELEASE SAVEPOINT ${savepointName}`); + } catch (e) { + try { + await queryRunner.query(`ROLLBACK TO SAVEPOINT ${savepointName}`); + await queryRunner.query(`RELEASE SAVEPOINT ${savepointName}`); + } catch (rollbackError) { + // eslint-disable-next-line no-console + console.error( + 'Failed to rollback to savepoint in MakeRoleUniversalIdentifierAndApplicationIdNotNullable1768213174275', + rollbackError, + ); + throw rollbackError; + } + + // eslint-disable-next-line no-console + console.error( + 'Swallowing MakeRoleUniversalIdentifierAndApplicationIdNotNullable1768213174275 error', + e, + ); + } + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "core"."role" DROP CONSTRAINT "FK_7f3b96f15aaf5a27549288d264b"`, + ); + await queryRunner.query( + `DROP INDEX "core"."IDX_3b7ff27925c0959777682c1adc"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."role" ALTER COLUMN "applicationId" DROP NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "core"."role" ALTER COLUMN "universalIdentifier" DROP NOT NULL`, + ); + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_3b7ff27925c0959777682c1adc" ON "core"."role" ("workspaceId", "universalIdentifier") `, + ); + await queryRunner.query( + `ALTER TABLE "core"."role" ADD CONSTRAINT "FK_7f3b96f15aaf5a27549288d264b" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + } +} diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/utils/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.util.ts b/packages/twenty-server/src/database/typeorm/core/migrations/utils/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.util.ts new file mode 100644 index 0000000000..3cba431032 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/utils/1768213174275-makeRoleUniversalIdentifierAndApplicationIdNotNullable.util.ts @@ -0,0 +1,23 @@ +import { type QueryRunner } from 'typeorm'; + +export const makeRoleUniversalIdentifierAndApplicationIdNotNullableQueries = + async (queryRunner: QueryRunner): Promise => { + await queryRunner.query( + `ALTER TABLE "core"."role" DROP CONSTRAINT "FK_7f3b96f15aaf5a27549288d264b"`, + ); + await queryRunner.query( + `DROP INDEX "core"."IDX_3b7ff27925c0959777682c1adc"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."role" ALTER COLUMN "universalIdentifier" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "core"."role" ALTER COLUMN "applicationId" SET NOT NULL`, + ); + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_3b7ff27925c0959777682c1adc" ON "core"."role" ("workspaceId", "universalIdentifier") `, + ); + await queryRunner.query( + `ALTER TABLE "core"."role" ADD CONSTRAINT "FK_7f3b96f15aaf5a27549288d264b" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + }; diff --git a/packages/twenty-server/src/engine/metadata-modules/role/constants/admin-role.ts b/packages/twenty-server/src/engine/metadata-modules/role/constants/admin-role.ts index b58d95d60a..af19c02e9e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/role/constants/admin-role.ts +++ b/packages/twenty-server/src/engine/metadata-modules/role/constants/admin-role.ts @@ -15,7 +15,6 @@ export const ADMIN_ROLE = { canBeAssignedToUsers: true, canBeAssignedToAgents: false, canBeAssignedToApiKeys: true, - applicationId: null, // TODO: Replace with Twenty application ID } as const satisfies Pick< FlatRole, | 'standardId' @@ -32,5 +31,4 @@ export const ADMIN_ROLE = { | 'canBeAssignedToUsers' | 'canBeAssignedToAgents' | 'canBeAssignedToApiKeys' - | 'applicationId' >; diff --git a/packages/twenty-server/src/engine/metadata-modules/role/role.entity.ts b/packages/twenty-server/src/engine/metadata-modules/role/role.entity.ts index 7561620d2e..f5a0669f53 100644 --- a/packages/twenty-server/src/engine/metadata-modules/role/role.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/role/role.entity.ts @@ -15,11 +15,14 @@ import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-fla import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.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 { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface'; +import { SyncableEntityRequired } from 'src/engine/workspace-manager/types/syncable-entity-required.interface'; @Entity('role') @Unique('IDX_ROLE_LABEL_WORKSPACE_ID_UNIQUE', ['label', 'workspaceId']) -export class RoleEntity extends SyncableEntity implements Required { +export class RoleEntity + extends SyncableEntityRequired + implements Required +{ @PrimaryGeneratedColumn('uuid') id: string;