feat(core): Forbid updating archived workflows (#24528)

This commit is contained in:
Daria
2026-01-19 12:36:01 +00:00
committed by GitHub
parent 715a53cfac
commit 0bbb6316ff
2 changed files with 43 additions and 0 deletions
@@ -265,6 +265,10 @@ export class WorkflowService {
);
}
if (workflow.isArchived) {
throw new BadRequestError('Cannot update an archived workflow.');
}
if (!forceSave && expectedChecksum) {
await this._detectConflicts(workflow, expectedChecksum);
}
@@ -533,6 +537,10 @@ export class WorkflowService {
);
}
if (workflow.isArchived) {
throw new BadRequestError('Cannot activate an archived workflow.');
}
const versionIdToActivate = options?.versionId ?? workflow.versionId;
const wasActive = workflow.activeVersionId !== null;
@@ -3300,6 +3300,24 @@ describe('PATCH /workflows/:workflowId', () => {
expect(activeWorkflowManagerLike.add).not.toHaveBeenCalled();
});
test('should not update an archived workflow', async () => {
const workflow = await createWorkflowWithHistory({ isArchived: true }, owner);
const response = await authOwnerAgent
.patch(`/workflows/${workflow.id}`)
.send({
name: 'Updated Name',
})
.expect(400);
expect(response.body.message).toBe('Cannot update an archived workflow.');
const updatedWorkflow = await workflowRepository.findById(workflow.id);
expect(updatedWorkflow).not.toBeNull();
expect(updatedWorkflow!.name).toBe(workflow.name);
expect(updatedWorkflow!.isArchived).toBe(true);
});
describe('Security: Mass Assignment Protection on Update', () => {
test.each([
{
@@ -3805,6 +3823,23 @@ describe('POST /workflows/:workflowId/activate', () => {
workflowId: workflow.id,
});
});
test('should not activate an archived workflow', async () => {
const workflow = await createWorkflowWithHistory({ isArchived: true }, owner);
const response = await authOwnerAgent
.post(`/workflows/${workflow.id}/activate`)
.send({ versionId: workflow.versionId })
.expect(400);
expect(response.body.message).toBe('Cannot activate an archived workflow.');
expect(activeWorkflowManagerLike.add).not.toHaveBeenCalled();
const updatedWorkflow = await workflowRepository.findById(workflow.id);
expect(updatedWorkflow).not.toBeNull();
expect(updatedWorkflow!.active).toBe(false);
expect(updatedWorkflow!.activeVersionId).toBeNull();
});
});
describe('POST /workflows/:workflowId/deactivate', () => {