Standard Agent, Role, Role target (#16499)
# Introduction In this pullrequest have been migrated to the flat standard entities: Role, Agent and RoleTargets. ## What happens - Removed createStandardMorph tool util in favor of dynamic typing of `createMorphOrRelationStandardField` - Implemented a command to remove standard agents and their role that has been removed in https://github.com/twentyhq/twenty/pull/16513 also added a default role target to data manipulator role to the only remaining agent - Implemented an agent deleteMany service handler
This commit is contained in:
@@ -251,27 +251,58 @@ export class AgentService {
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<FlatAgentWithRoleId> {
|
||||
const {
|
||||
flatAgentMaps: existingFlatAgentMaps,
|
||||
flatRoleTargetByAgentIdMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatAgentMaps',
|
||||
'flatRoleTargetByAgentIdMaps',
|
||||
]);
|
||||
|
||||
const agentToDelete = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: existingFlatAgentMaps,
|
||||
const deletedAgents = await this.deleteManyAgents({
|
||||
ids: [id],
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!isDefined(agentToDelete)) {
|
||||
if (deletedAgents.length !== 1) {
|
||||
throw new AgentException(
|
||||
`Agent not found`,
|
||||
'Could not retrieve deleted agent',
|
||||
AgentExceptionCode.AGENT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const roleId = flatRoleTargetByAgentIdMaps[agentToDelete.id]?.roleId;
|
||||
const [deletedAgent] = deletedAgents;
|
||||
|
||||
return deletedAgent;
|
||||
}
|
||||
|
||||
async deleteManyAgents({
|
||||
ids,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
}: {
|
||||
ids: string[];
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
}): Promise<FlatAgentWithRoleId[]> {
|
||||
if (ids.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { flatAgentMaps, flatRoleTargetByAgentIdMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatAgentMaps',
|
||||
'flatRoleTargetByAgentIdMaps',
|
||||
]);
|
||||
|
||||
const agentsToDelete = ids
|
||||
.map((id) =>
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatAgentMaps,
|
||||
}),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
if (agentsToDelete.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const roleTargetsToDelete = agentsToDelete
|
||||
.map((agent) => flatRoleTargetByAgentIdMaps[agent.id])
|
||||
.filter(isDefined);
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
@@ -279,26 +310,31 @@ export class AgentService {
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
agent: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [agentToDelete],
|
||||
flatEntityToDelete: agentsToDelete,
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
roleTarget: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: roleTargetsToDelete,
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
isSystemBuild,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while deleting agent',
|
||||
`Multiple validation errors occurred while deleting agent${ids.length > 1 ? 's' : ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...agentToDelete,
|
||||
roleId: roleId ?? null,
|
||||
};
|
||||
return agentsToDelete.map((agent) => ({
|
||||
...agent,
|
||||
roleId: flatRoleTargetByAgentIdMaps[agent.id]?.roleId ?? null,
|
||||
}));
|
||||
}
|
||||
|
||||
async searchAgents(
|
||||
|
||||
+4
-1
@@ -52,8 +52,11 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
|
||||
role: {},
|
||||
roleTarget: {
|
||||
role: true,
|
||||
agent: true,
|
||||
},
|
||||
agent: {
|
||||
role: true,
|
||||
},
|
||||
agent: {},
|
||||
pageLayout: {},
|
||||
pageLayoutTab: {
|
||||
pageLayout: true,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Repository } from 'typeorm';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
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 { getFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/get-flat-entities-by-universal-identifier.util';
|
||||
import { fromCreateRoleInputToFlatRoleToCreate } from 'src/engine/metadata-modules/flat-role/utils/from-create-role-input-to-flat-role-to-create.util';
|
||||
import { fromDeleteRoleInputToFlatRoleOrThrow } from 'src/engine/metadata-modules/flat-role/utils/from-delete-role-input-to-flat-role-or-throw.util';
|
||||
import { fromUpdateRoleInputToFlatRoleToUpdateOrThrow } from 'src/engine/metadata-modules/flat-role/utils/from-update-role-input-to-flat-role-to-update-or-throw.util';
|
||||
@@ -25,7 +26,6 @@ import { fromFlatRoleToRoleDto } from 'src/engine/metadata-modules/role/utils/fr
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
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';
|
||||
import { getFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/get-flat-entities-by-universal-identifier.util';
|
||||
|
||||
@Injectable()
|
||||
export class RoleService {
|
||||
@@ -214,6 +214,38 @@ export class RoleService {
|
||||
roleId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<RoleDTO> {
|
||||
const deletedRoles = await this.deleteManyRoles({
|
||||
ids: [roleId],
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
});
|
||||
|
||||
const [deletedRole] = deletedRoles;
|
||||
|
||||
return deletedRole;
|
||||
}
|
||||
|
||||
public async deleteManyRoles({
|
||||
ids,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
}: {
|
||||
ids: string[];
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
}): Promise<RoleDTO[]> {
|
||||
if (ids.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { flatRoleMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRoleMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: {
|
||||
id: workspaceId,
|
||||
@@ -232,58 +264,56 @@ export class RoleService {
|
||||
);
|
||||
}
|
||||
|
||||
if (defaultRoleId === roleId) {
|
||||
throw new PermissionsException(
|
||||
PermissionsExceptionMessage.DEFAULT_ROLE_CANNOT_BE_DELETED,
|
||||
PermissionsExceptionCode.DEFAULT_ROLE_CANNOT_BE_DELETED,
|
||||
{
|
||||
userFriendlyMessage: msg`The default role cannot be deleted as it is required for the workspace to function properly.`,
|
||||
},
|
||||
);
|
||||
const rolesToDelete = [];
|
||||
|
||||
for (const roleId of ids) {
|
||||
const flatRoleToDelete = fromDeleteRoleInputToFlatRoleOrThrow({
|
||||
flatRoleMaps,
|
||||
roleId,
|
||||
});
|
||||
|
||||
if (defaultRoleId === roleId) {
|
||||
throw new PermissionsException(
|
||||
PermissionsExceptionMessage.DEFAULT_ROLE_CANNOT_BE_DELETED,
|
||||
PermissionsExceptionCode.DEFAULT_ROLE_CANNOT_BE_DELETED,
|
||||
{
|
||||
userFriendlyMessage: msg`The default role cannot be deleted as it is required for the workspace to function properly.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
await this.assignDefaultRoleToMembersWithRoleToDelete({
|
||||
roleId,
|
||||
workspaceId,
|
||||
defaultRoleId,
|
||||
});
|
||||
|
||||
rolesToDelete.push(flatRoleToDelete);
|
||||
}
|
||||
|
||||
await this.assignDefaultRoleToMembersWithRoleToDelete({
|
||||
roleId,
|
||||
workspaceId,
|
||||
defaultRoleId,
|
||||
});
|
||||
|
||||
const { flatRoleMaps: existingFlatRoleMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRoleMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatRoleToDelete = fromDeleteRoleInputToFlatRoleOrThrow({
|
||||
flatRoleMaps: existingFlatRoleMaps,
|
||||
roleId,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
role: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [flatRoleToDelete],
|
||||
flatEntityToDelete: rolesToDelete,
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
isSystemBuild,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationBuilderExceptionV2(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while deleting role',
|
||||
`Multiple validation errors occurred while deleting role${ids.length > 1 ? 's' : ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
return fromFlatRoleToRoleDto(flatRoleToDelete);
|
||||
return rolesToDelete.map(fromFlatRoleToRoleDto);
|
||||
}
|
||||
|
||||
public async createMemberRole({
|
||||
|
||||
Reference in New Issue
Block a user