fix(core): 执行记录查询补越权校验,待确认中的执行也能按 executionId 查到
This commit is contained in:
parent
498e7e60b4
commit
ee42650f9c
|
|
@ -257,6 +257,12 @@ test('A4.4 确认卡:写操作等确认、确认后执行、事件齐全、重
|
|||
assert.ok(await stream.waitFor((event) => event.type === 'approval.requested'), '要推确认卡给界面');
|
||||
assert.equal(aps.stats.calls['aps.write'], undefined, '没确认前不能动业务系统');
|
||||
|
||||
// 待确认中的执行也要能按 executionId 查到,且只有本人能查
|
||||
const pendingView = await fetch(`${server.url}/v1/executions/${receipt.executionId}`, { headers: headersFor(subject) });
|
||||
assert.equal((await pendingView.json()).status, 'pending-confirmation');
|
||||
const stolenView = await fetch(`${server.url}/v1/executions/${receipt.executionId}`, { headers: headersFor(otherSubject) });
|
||||
assert.equal(stolenView.status, 403, '执行记录只有本人能查');
|
||||
|
||||
const decision = await fetch(`${server.url}/v1/approvals/${receipt.approvalId}`, {
|
||||
method: 'POST',
|
||||
headers: headersFor(subject),
|
||||
|
|
|
|||
|
|
@ -227,13 +227,13 @@ test('HTTP:注册 Provider 后能力清单非空,执行记录端点可查回
|
|||
params: { text: '通过 HTTP 查回执' },
|
||||
});
|
||||
|
||||
const response = await fetch(`${server.url}/v1/executions/${receipt.executionId}`);
|
||||
const response = await fetch(`${server.url}/v1/executions/${receipt.executionId}`, { headers: { 'x-aps-user': subject.userId, 'x-aps-tenant': subject.tenantId } });
|
||||
assert.equal(response.status, 200, '执行记录端点应返回 200');
|
||||
const body = await response.json();
|
||||
assert.equal(body.executionId, receipt.executionId);
|
||||
assert.equal(body.status, 'succeeded');
|
||||
|
||||
const missing = await fetch(`${server.url}/v1/executions/exec-none`);
|
||||
const missing = await fetch(`${server.url}/v1/executions/exec-none`, { headers: { 'x-aps-user': subject.userId } });
|
||||
assert.equal(missing.status, 404, '未知执行记录应 404');
|
||||
const missingBody = await missing.json();
|
||||
assert.equal(missingBody.error.code, 'not_found');
|
||||
|
|
|
|||
|
|
@ -114,9 +114,17 @@ export class ApplicationService {
|
|||
return this.contextRepository?.get(sessionId);
|
||||
}
|
||||
|
||||
/** 执行记录查询:GET /v1/executions/{id} */
|
||||
execution(executionId: string) {
|
||||
return this.core.executions.get(executionId)?.receipt;
|
||||
/** 执行记录查询:GET /v1/executions/{id};待确认中的执行也能查到(回执 status = pending-confirmation) */
|
||||
execution(subject: Subject, executionId: string) {
|
||||
const record = this.core.executions.get(executionId);
|
||||
if (record) {
|
||||
if (record.subjectUserId !== subject.userId) throw new AppError('forbidden', '这是别人的执行记录', { status: 403 });
|
||||
return record.receipt;
|
||||
}
|
||||
const action = this.core.approvals?.byExecution(executionId);
|
||||
if (!action) return undefined;
|
||||
if (action.ownerUserId !== subject.userId) throw new AppError('forbidden', '这是别人的执行记录', { status: 403 });
|
||||
return action.receipt;
|
||||
}
|
||||
|
||||
/** 执行追溯(A4.5):按 executionId 追到人、参数摘要、审批与回执;只有本人能看 */
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse, service:
|
|||
return sendJson(res, 200, service.capabilities(subject, sessionFilter));
|
||||
case 'GET /v1/executions/{executionId}': {
|
||||
const executionId = params.get('executionId') ?? '';
|
||||
const receipt = service.execution(executionId);
|
||||
const receipt = service.execution(subject, executionId);
|
||||
if (!receipt) throw new AppError('not_found', `执行记录 不存在`, { status: 404 });
|
||||
return sendJson(res, 200, receipt);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue