From 8acfa604124da22d5f362f69a5e2f60d08685c54 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:14:24 +0100 Subject: [PATCH] Fix standard agent and roles deletion command (#16686) # Introduction Caught red handed, introduced a failing command in https://github.com/twentyhq/twenty/pull/16499 that was failing even in system build which is should not --- .../1-14-delete-removed-agents.command.ts | 36 +++++++++++++------ .../services/flat-agent-validator.service.ts | 13 +++---- .../services/flat-role-validator.service.ts | 4 +++ .../utils/validate-role-is-editable.util.ts | 5 ++- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-14/1-14-delete-removed-agents.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-14/1-14-delete-removed-agents.command.ts index 6d0a805335..24eddb723a 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-14/1-14-delete-removed-agents.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-14/1-14-delete-removed-agents.command.ts @@ -90,11 +90,19 @@ export class DeleteRemovedAgentsCommand extends ActiveOrSuspendedWorkspacesMigra const agentIds = agentsToDelete.map((agent) => agent.id); - await this.agentService.deleteManyAgents({ - ids: agentIds, - workspaceId, - isSystemBuild: true, - }); + try { + await this.agentService.deleteManyAgents({ + ids: agentIds, + workspaceId, + isSystemBuild: true, + }); + } catch (error) { + this.logger.error( + `Failed to delete workspace agents \n ${JSON.stringify(error, null, 2)}`, + ); + + throw error; + } this.logger.log( `Deleted ${agentsToDelete.length} removed agent(s): ${agentNames}`, @@ -128,11 +136,19 @@ export class DeleteRemovedAgentsCommand extends ActiveOrSuspendedWorkspacesMigra const roleIds = rolesToDelete.map((role) => role.id); - await this.roleService.deleteManyRoles({ - ids: roleIds, - workspaceId, - isSystemBuild: true, - }); + try { + await this.roleService.deleteManyRoles({ + ids: roleIds, + workspaceId, + isSystemBuild: true, + }); + } catch (error) { + this.logger.error( + `Failed to delete workspace roles \n ${JSON.stringify(error, null, 2)}`, + ); + + throw error; + } this.logger.log( `Deleted ${rolesToDelete.length} removed role(s): ${roleLabels}`, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-agent-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-agent-validator.service.ts index 78e47e22f1..4293c984f8 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-agent-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-agent-validator.service.ts @@ -7,6 +7,7 @@ import { isDefined } from 'twenty-shared/utils'; import { AgentExceptionCode } from 'src/engine/metadata-modules/ai/ai-agent/agent.exception'; import { type FlatAgent } from 'src/engine/metadata-modules/flat-agent/types/flat-agent.type'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util'; import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; import { type FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type'; import { type FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type'; @@ -67,6 +68,7 @@ export class FlatAgentValidatorService { optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatAgentMaps: optimisticFlatAgentMaps, }, + buildOptions, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.agent >): FailedFlatEntityValidation { @@ -94,10 +96,7 @@ export class FlatAgentValidatorService { return validationResult; } - if ( - existingAgent.isCustom === false && - isDefined(existingAgent.standardId) - ) { + if (!buildOptions.isSystemBuild && isStandardMetadata(existingAgent)) { validationResult.errors.push({ code: AgentExceptionCode.AGENT_IS_STANDARD, message: t`Cannot delete standard agent`, @@ -114,6 +113,7 @@ export class FlatAgentValidatorService { optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatAgentMaps: optimisticFlatAgentMaps, }, + buildOptions, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.agent >): FailedFlatEntityValidation { @@ -140,10 +140,7 @@ export class FlatAgentValidatorService { return validationResult; } - if ( - fromFlatAgent.isCustom === false && - isDefined(fromFlatAgent.standardId) - ) { + if (!buildOptions.isSystemBuild && isStandardMetadata(fromFlatAgent)) { validationResult.errors.push({ code: AgentExceptionCode.AGENT_IS_STANDARD, message: t`Cannot update standard agent`, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-role-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-role-validator.service.ts index 5dd96cfc47..c3a61241a9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-role-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-role-validator.service.ts @@ -66,6 +66,7 @@ export class FlatRoleValidatorService { optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatRoleMaps: optimisticFlatRoleMaps, }, + buildOptions, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.role >): FailedFlatEntityValidation { @@ -93,6 +94,7 @@ export class FlatRoleValidatorService { validationResult.errors.push( ...validateRoleIsEditable({ flatRole: existingRole, + buildOptions, }), ); @@ -105,6 +107,7 @@ export class FlatRoleValidatorService { optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatRoleMaps: optimisticFlatRoleMaps, }, + buildOptions, }: FlatEntityUpdateValidationArgs< typeof ALL_METADATA_NAME.role >): FailedFlatEntityValidation { @@ -131,6 +134,7 @@ export class FlatRoleValidatorService { validationResult.errors.push( ...validateRoleIsEditable({ flatRole: fromFlatRole, + buildOptions, }), ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-role-is-editable.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-role-is-editable.util.ts index 2e3b99cc50..37f4412764 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-role-is-editable.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-role-is-editable.util.ts @@ -6,15 +6,18 @@ import { PermissionsExceptionMessage, } from 'src/engine/metadata-modules/permissions/permissions.exception'; import { type FlatEntityValidationError } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; +import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; export const validateRoleIsEditable = ({ flatRole, + buildOptions, }: { flatRole: FlatRole; + buildOptions: WorkspaceMigrationBuilderOptions; }): FlatEntityValidationError[] => { const errors: FlatEntityValidationError[] = []; - if (!flatRole.isEditable) { + if (!buildOptions.isSystemBuild && !flatRole.isEditable) { errors.push({ code: PermissionsExceptionCode.ROLE_NOT_EDITABLE, message: PermissionsExceptionMessage.ROLE_NOT_EDITABLE,