Files
cn-rdms-web/tests/task-permission-rules.test.ts

180 lines
5.0 KiB
TypeScript
Raw Normal View History

import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
canDeleteExecutionByIdentity,
canDeleteTaskByIdentity,
canEditExecutionByIdentity,
canEditTaskByIdentity
} from '../src/views/project/project/execution/composables/task-permission-rules';
function createExecution(overrides: Partial<Api.Project.ProjectExecution> = {}): Api.Project.ProjectExecution {
return {
id: 'execution-1',
projectId: 'project-1',
projectRequirementId: null,
projectRequirementName: null,
projectRequirementStatusCode: null,
executionName: 'execution',
executionType: null,
ownerId: 'execution-owner',
ownerNickname: null,
statusCode: 'active',
statusName: null,
terminal: false,
allowEdit: true,
availableActions: [],
plannedStartDate: null,
plannedEndDate: null,
actualStartDate: null,
actualEndDate: null,
progressRate: 0,
priority: '2',
priorityName: null,
executionDesc: null,
lastStatusReason: null,
createTime: '2026-07-07 10:00:00',
updateTime: '2026-07-07 10:00:00',
...overrides
};
}
function createTask(overrides: Partial<Api.Project.ProjectTask> = {}): Api.Project.ProjectTask {
return {
id: 'task-1',
projectId: 'project-1',
executionId: 'execution-1',
executionName: '执行',
executionStatusCode: 'active',
parentTaskId: null,
projectRequirementId: null,
projectRequirementName: null,
projectRequirementStatusCode: null,
taskTitle: '任务',
type: '',
ownerId: 'task-owner',
ownerNickname: null,
executionOwnerId: 'execution-owner',
parentTaskOwnerId: null,
statusCode: 'active',
statusName: null,
terminal: false,
allowEdit: true,
availableActions: [],
progressRate: 0,
plannedStartDate: null,
plannedEndDate: null,
actualStartDate: null,
actualEndDate: null,
priority: '2',
priorityName: null,
taskDesc: null,
lastStatusReason: null,
assignees: null,
attachments: [],
totalSpentHours: null,
createTime: '2026-07-07 10:00:00',
updateTime: '2026-07-07 10:00:00',
...overrides
};
}
describe('task mutation permission rules', () => {
it('allows task owner, execution owner, and project manager to edit mutable tasks', () => {
const task = createTask();
assert.equal(
canEditTaskByIdentity(task, { currentUserId: 'task-owner', projectManagerUserId: 'project-manager' }),
true
);
assert.equal(
canEditTaskByIdentity(task, { currentUserId: 'execution-owner', projectManagerUserId: 'project-manager' }),
true
);
assert.equal(
canEditTaskByIdentity(task, { currentUserId: 'project-manager', projectManagerUserId: 'project-manager' }),
true
);
});
it('does not allow unrelated users to edit just because they have a task permission code', () => {
const task = createTask();
assert.equal(
canEditTaskByIdentity(task, {
currentUserId: 'developer',
projectManagerUserId: 'project-manager'
}),
false
);
});
it('uses the same identity rule for delete and only blocks completed tasks by status', () => {
assert.equal(
canDeleteTaskByIdentity(createTask({ statusCode: 'active' }), {
currentUserId: 'execution-owner',
projectManagerUserId: 'project-manager'
}),
true
);
assert.equal(
canDeleteTaskByIdentity(createTask({ statusCode: 'completed' }), {
currentUserId: 'execution-owner',
projectManagerUserId: 'project-manager'
}),
false
);
});
});
describe('execution mutation permission rules', () => {
it('allows only execution owner and project manager to edit mutable executions', () => {
const execution = createExecution();
assert.equal(
canEditExecutionByIdentity(execution, {
currentUserId: 'execution-owner',
projectManagerUserId: 'project-manager'
}),
true
);
assert.equal(
canEditExecutionByIdentity(execution, {
currentUserId: 'project-manager',
projectManagerUserId: 'project-manager'
}),
true
);
assert.equal(
canEditExecutionByIdentity(execution, {
currentUserId: 'developer',
projectManagerUserId: 'project-manager'
}),
false
);
});
it('uses the same identity rule for delete and only blocks completed executions by status', () => {
assert.equal(
canDeleteExecutionByIdentity(createExecution({ statusCode: 'active' }), {
currentUserId: 'execution-owner',
projectManagerUserId: 'project-manager'
}),
true
);
assert.equal(
canDeleteExecutionByIdentity(createExecution({ statusCode: 'active' }), {
currentUserId: 'developer',
projectManagerUserId: 'project-manager'
}),
false
);
assert.equal(
canDeleteExecutionByIdentity(createExecution({ statusCode: 'completed' }), {
currentUserId: 'execution-owner',
projectManagerUserId: 'project-manager'
}),
false
);
});
});