实现企业银行账户与建行制单(corporate-bank-account-payment-order)
这个提交包含在:
@@ -85,15 +85,16 @@ describe("user sensitive field permissions", () => {
|
||||
await testApp.app.close();
|
||||
});
|
||||
|
||||
it("returns only bank fields to finance and audits the authorized scope", async () => {
|
||||
it("returns only masked bank fields to finance without a full-account view audit", async () => {
|
||||
const testApp = await buildApp(["employee.bank.read"]);
|
||||
|
||||
const response = await testApp.app.inject({ method: "GET", url: `/api/users/${EMPLOYEE_ID}/sensitive` });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data).toEqual({
|
||||
bankInstitution: null,
|
||||
bankName: "合成银行",
|
||||
bankAccount: "6222000012345678",
|
||||
bankAccountMasked: "6222********5678",
|
||||
});
|
||||
expect(response.json().data).not.toHaveProperty("idNumber");
|
||||
expect(testApp.employeeFindUnique).toHaveBeenCalledWith({
|
||||
@@ -101,15 +102,12 @@ describe("user sensitive field permissions", () => {
|
||||
select: {
|
||||
id: true,
|
||||
bank_name: true,
|
||||
bank_institution_id: true,
|
||||
bank_account_encrypted: true,
|
||||
bank_institution: { select: { id: true, code: true, name: true } },
|
||||
},
|
||||
});
|
||||
expect(testApp.auditCreate).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
action: "SYSTEM_USER_SENSITIVE_VIEWED",
|
||||
extra: { scopes: ["bank"] },
|
||||
}),
|
||||
});
|
||||
expect(testApp.auditCreate).not.toHaveBeenCalled();
|
||||
await testApp.app.close();
|
||||
});
|
||||
|
||||
@@ -119,7 +117,7 @@ describe("user sensitive field permissions", () => {
|
||||
const response = await testApp.app.inject({
|
||||
method: "PATCH",
|
||||
url: `/api/users/${EMPLOYEE_ID}/sensitive`,
|
||||
payload: { bankName: "新银行" },
|
||||
payload: { bankAccount: "6222000099995678" },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
@@ -134,7 +132,7 @@ describe("user sensitive field permissions", () => {
|
||||
const response = await testApp.app.inject({
|
||||
method: "PATCH",
|
||||
url: `/api/users/${EMPLOYEE_ID}/sensitive`,
|
||||
payload: { bankName: "新银行", idNumber: "110101199001011234" },
|
||||
payload: { bankAccount: "6222000099995678", idNumber: "110101199001011234" },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
@@ -143,6 +141,33 @@ describe("user sensitive field permissions", () => {
|
||||
await testApp.app.close();
|
||||
});
|
||||
|
||||
it("reveals a full bank account only after a reason and records the view audit", async () => {
|
||||
const testApp = await buildApp(["employee.bank.read"]);
|
||||
|
||||
const missingReason = await testApp.app.inject({
|
||||
method: "POST",
|
||||
url: `/api/users/${EMPLOYEE_ID}/sensitive/bank/reveal`,
|
||||
payload: {},
|
||||
});
|
||||
expect(missingReason.statusCode).toBe(400);
|
||||
expect(testApp.auditCreate).not.toHaveBeenCalled();
|
||||
|
||||
const response = await testApp.app.inject({
|
||||
method: "POST",
|
||||
url: `/api/users/${EMPLOYEE_ID}/sensitive/bank/reveal`,
|
||||
payload: { reason: "付款核对" },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data).toEqual({ bankAccount: "6222000012345678" });
|
||||
expect(testApp.auditCreate).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
action: "SYSTEM_USER_BANK_ACCOUNT_REVEALED",
|
||||
extra: { reason: "付款核对" },
|
||||
}),
|
||||
});
|
||||
await testApp.app.close();
|
||||
});
|
||||
|
||||
it("writes only authorized fields and keeps plaintext out of the audit", async () => {
|
||||
const testApp = await buildApp(["employee.bank.manage", "employee.identity.manage"]);
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户