Revert "refactor: Simplify CRUD services to leverage Common API (#157… (#15875)

This reverts commit 11e07f90d2.
This commit is contained in:
martmull
2025-11-18 09:44:15 +01:00
committed by GitHub
parent 0fa2a4524a
commit d0d90735cb
32 changed files with 872 additions and 502 deletions
@@ -1,25 +1,20 @@
import { Injectable, Logger } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { isDefined } from 'twenty-shared/utils';
import { FieldActorSource } from 'twenty-shared/types';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type WorkflowExecutionContext } from 'src/modules/workflow/workflow-executor/types/workflow-execution-context.type';
import { WorkflowRunWorkspaceService as WorkflowRunService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service';
@Injectable()
// eslint-disable-next-line @nx/workspace-inject-workspace-repository
export class WorkflowExecutionContextService {
private readonly logger = new Logger(WorkflowExecutionContextService.name);
constructor(
private readonly workflowRunService: WorkflowRunService,
private readonly userWorkspaceService: UserWorkspaceService,
private readonly userRoleService: UserRoleService,
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
) {}
async getExecutionContext(runInfo: {
@@ -31,26 +26,29 @@ export class WorkflowExecutionContextService {
workspaceId: runInfo.workspaceId,
});
if (!workflowRun.createdBy) {
throw new Error(
'WorkflowRun createdBy field is missing - cannot determine execution context',
);
}
const isActingOnBehalfOfUser =
workflowRun.createdBy.source === FieldActorSource.MANUAL &&
isDefined(workflowRun.createdBy.workspaceMemberId);
const { userWorkspaceId, roleId } = await this.resolveUserContext({
workflowRun,
isActingOnBehalfOfUser,
runInfo,
});
let roleId: string | undefined;
if (!userWorkspaceId) {
throw new Error(
`userWorkspaceId is required but could not be determined for workflow run ${runInfo.workflowRunId}`,
);
if (isActingOnBehalfOfUser) {
const workspaceMember =
await this.userWorkspaceService.getWorkspaceMemberOrThrow({
workspaceMemberId: workflowRun.createdBy.workspaceMemberId!,
workspaceId: runInfo.workspaceId,
});
const userWorkspace =
await this.userWorkspaceService.getUserWorkspaceForUserOrThrow({
userId: workspaceMember.userId,
workspaceId: runInfo.workspaceId,
});
roleId = await this.userRoleService.getRoleIdForUserWorkspace({
userWorkspaceId: userWorkspace.id,
workspaceId: runInfo.workspaceId,
});
}
const rolePermissionConfig = roleId
@@ -61,87 +59,6 @@ export class WorkflowExecutionContextService {
isActingOnBehalfOfUser,
initiator: workflowRun.createdBy,
rolePermissionConfig,
userWorkspaceId,
};
}
private async resolveUserContext({
workflowRun,
isActingOnBehalfOfUser,
runInfo,
}: {
workflowRun: {
createdBy: { workspaceMemberId?: string | null };
workflowId: string;
};
isActingOnBehalfOfUser: boolean;
runInfo: { workflowRunId: string; workspaceId: string };
}): Promise<{ userWorkspaceId?: string; roleId?: string }> {
// Determine which workspace member to use for context
let workspaceMemberId = workflowRun.createdBy.workspaceMemberId;
// If workflow run was triggered automatically (no user initiator),
// use the workflow creator's workspace member
if (!isDefined(workspaceMemberId)) {
const workflow = await this.getWorkflow(
workflowRun.workflowId,
runInfo.workspaceId,
);
if (!workflow.createdBy?.workspaceMemberId) {
this.logger.error(
`Workflow ${workflowRun.workflowId} has no creator workspaceMemberId - cannot determine execution context`,
);
return { userWorkspaceId: undefined, roleId: undefined };
}
workspaceMemberId = workflow.createdBy.workspaceMemberId;
}
const workspaceMember =
await this.userWorkspaceService.getWorkspaceMemberOrThrow({
workspaceMemberId,
workspaceId: runInfo.workspaceId,
});
const userWorkspace =
await this.userWorkspaceService.getUserWorkspaceForUserOrThrow({
userId: workspaceMember.userId,
workspaceId: runInfo.workspaceId,
});
if (!isActingOnBehalfOfUser) {
return { userWorkspaceId: userWorkspace.id, roleId: undefined };
}
const roleId = await this.userRoleService.getRoleIdForUserWorkspace({
userWorkspaceId: userWorkspace.id,
workspaceId: runInfo.workspaceId,
});
return { userWorkspaceId: userWorkspace.id, roleId };
}
private async getWorkflow(
workflowId: string,
workspaceId: string,
): Promise<WorkflowWorkspaceEntity> {
const workflowRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkflowWorkspaceEntity>(
workspaceId,
'workflow',
{ shouldBypassPermissionChecks: true },
);
const workflow = await workflowRepository.findOne({
where: { id: workflowId },
});
if (!workflow) {
throw new Error(`Workflow ${workflowId} not found`);
}
return workflow;
}
}
@@ -6,5 +6,4 @@ export type WorkflowExecutionContext = {
isActingOnBehalfOfUser: boolean;
initiator: ActorMetadata;
rolePermissionConfig: RolePermissionConfig;
userWorkspaceId?: string;
};
@@ -86,7 +86,6 @@ export class AiAgentWorkflowAction implements WorkflowAction {
? executionContext.initiator
: undefined,
rolePermissionConfig: executionContext.rolePermissionConfig,
userWorkspaceId: executionContext.userWorkspaceId,
},
);
@@ -38,7 +38,6 @@ export class AiAgentExecutorService {
workspaceId: string,
actorContext?: ActorMetadata,
rolePermissionConfig?: RolePermissionConfig,
userWorkspaceId?: string,
): Promise<ToolSet> {
const roleTarget = await this.roleTargetsRepository.findOne({
where: {
@@ -77,7 +76,6 @@ export class AiAgentExecutorService {
effectiveRoleContext,
workspaceId,
actorContext,
userWorkspaceId,
);
return {
@@ -92,14 +90,12 @@ export class AiAgentExecutorService {
userPrompt,
actorContext,
rolePermissionConfig,
userWorkspaceId,
}: {
agent: AgentEntity | null;
schema: OutputSchema;
userPrompt: string;
actorContext?: ActorMetadata;
rolePermissionConfig?: RolePermissionConfig;
userWorkspaceId?: string;
}): Promise<AgentExecutionResult> {
try {
const registeredModel =
@@ -111,7 +107,6 @@ export class AiAgentExecutorService {
agent.workspaceId,
actorContext,
rolePermissionConfig,
userWorkspaceId,
)
: {};
@@ -62,7 +62,6 @@ export class CreateRecordWorkflowAction implements WorkflowAction {
workspaceId,
createdBy,
rolePermissionConfig: executionContext.rolePermissionConfig,
userWorkspaceId: executionContext.userWorkspaceId,
});
if (!toolOutput.success) {
@@ -80,8 +80,6 @@ export class DeleteRecordWorkflowAction implements WorkflowAction {
objectRecordId: workflowActionInput.objectRecordId,
workspaceId,
rolePermissionConfig: executionContext.rolePermissionConfig,
userWorkspaceId: executionContext.userWorkspaceId,
createdBy: executionContext.initiator,
soft: true,
});
@@ -71,22 +71,23 @@ export class FindRecordsWorkflowAction implements WorkflowAction {
limit: workflowActionInput.limit,
workspaceId,
rolePermissionConfig: executionContext.rolePermissionConfig,
userWorkspaceId: executionContext.userWorkspaceId,
createdBy: executionContext.initiator,
});
if (!toolOutput.success || !toolOutput.result) {
if (!toolOutput.success) {
throw new RecordCrudException(
toolOutput.error || toolOutput.message,
RecordCrudExceptionCode.QUERY_FAILED,
);
}
const records = toolOutput.result?.records ?? [];
const totalCount = toolOutput.result?.count ?? 0;
return {
result: {
first: toolOutput.result.records[0],
all: toolOutput.result.records,
totalCount: toolOutput.result.totalCount,
first: records[0],
all: records,
totalCount,
},
};
}
@@ -82,8 +82,6 @@ export class UpdateRecordWorkflowAction implements WorkflowAction {
fieldsToUpdate: workflowActionInput.fieldsToUpdate,
workspaceId,
rolePermissionConfig: executionContext.rolePermissionConfig,
userWorkspaceId: executionContext.userWorkspaceId,
createdBy: executionContext.initiator,
});
if (!toolOutput.success) {
@@ -76,8 +76,6 @@ export class UpsertRecordWorkflowAction implements WorkflowAction {
objectRecord: workflowActionInput.objectRecord,
workspaceId,
rolePermissionConfig: executionContext.rolePermissionConfig,
userWorkspaceId: executionContext.userWorkspaceId,
createdBy: executionContext.initiator,
});
if (!toolOutput.success) {