实现企微首次免密自动绑定(07-28-all-account-login-readiness)
这个提交包含在:
@@ -0,0 +1,201 @@
|
||||
const {
|
||||
applyReset,
|
||||
diagnoseWecomBinding,
|
||||
preflight,
|
||||
verifyCompletedPasswordChange,
|
||||
verifyState,
|
||||
} = require("../../../src/scripts/reset-active-admin-password");
|
||||
|
||||
function createPrismaFixture({ adminCount = 1 } = {}) {
|
||||
const admins = Array.from({ length: adminCount }, (_, index) => ({
|
||||
id: `00000000-0000-4000-8000-${String(index + 1).padStart(12, "0")}`,
|
||||
token_version: 7,
|
||||
}));
|
||||
const tx = {
|
||||
employee: {
|
||||
findUnique: vi.fn().mockResolvedValue({
|
||||
status: "active",
|
||||
archived_at: null,
|
||||
token_version: 7,
|
||||
roles: [{ role_code: "system_admin" }],
|
||||
}),
|
||||
update: vi
|
||||
.fn()
|
||||
.mockResolvedValue({ must_change_password: true, token_version: 8 }),
|
||||
},
|
||||
authSession: { updateMany: vi.fn().mockResolvedValue({ count: 2 }) },
|
||||
passwordResetCode: { updateMany: vi.fn().mockResolvedValue({ count: 1 }) },
|
||||
emailLoginCode: { updateMany: vi.fn().mockResolvedValue({ count: 3 }) },
|
||||
auditLog: { create: vi.fn().mockResolvedValue({}) },
|
||||
};
|
||||
return {
|
||||
tx,
|
||||
prisma: {
|
||||
employee: {
|
||||
findMany: vi.fn().mockResolvedValue(admins),
|
||||
findUnique: vi.fn().mockResolvedValue({
|
||||
must_change_password: true,
|
||||
login_failed_count: 0,
|
||||
login_locked_until: null,
|
||||
email_login_code_failed_count: 0,
|
||||
email_login_code_locked_until: null,
|
||||
password_reset_failed_count: 0,
|
||||
password_reset_locked_until: null,
|
||||
token_version: 8,
|
||||
}),
|
||||
},
|
||||
authSession: { count: vi.fn().mockResolvedValue(0) },
|
||||
passwordResetCode: { count: vi.fn().mockResolvedValue(0) },
|
||||
emailLoginCode: { count: vi.fn().mockResolvedValue(0) },
|
||||
auditLog: { count: vi.fn().mockResolvedValue(1) },
|
||||
wecomIdentityBinding: {
|
||||
findUnique: vi.fn().mockResolvedValue(null),
|
||||
count: vi.fn().mockResolvedValue(0),
|
||||
},
|
||||
wecomDirectorySyncRun: { findFirst: vi.fn().mockResolvedValue(null) },
|
||||
wecomHrMasterSyncItem: { count: vi.fn().mockResolvedValue(0) },
|
||||
$transaction: vi.fn(async (callback) => callback(tx)),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("active administrator break-glass reset", () => {
|
||||
it("blocks preflight unless the active protected administrator is unique", async () => {
|
||||
const none = createPrismaFixture({ adminCount: 0 });
|
||||
const multiple = createPrismaFixture({ adminCount: 2 });
|
||||
|
||||
await expect(preflight(none.prisma)).resolves.toEqual({
|
||||
status: "BLOCKED",
|
||||
activeAdminMatches: 0,
|
||||
exactTarget: false,
|
||||
});
|
||||
await expect(preflight(multiple.prisma)).resolves.toEqual({
|
||||
status: "BLOCKED",
|
||||
activeAdminMatches: 2,
|
||||
exactTarget: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("resets only the unique active administrator and revokes authentication state", async () => {
|
||||
const { prisma, tx } = createPrismaFixture();
|
||||
|
||||
const result = await applyReset(prisma, "UniqueBreakGlass9Qz!");
|
||||
|
||||
expect(result).toEqual({
|
||||
status: "PASS",
|
||||
activeAdminMatches: 1,
|
||||
passwordUpdated: true,
|
||||
mustChangePassword: true,
|
||||
tokenVersionIncremented: true,
|
||||
locksCleared: true,
|
||||
revokedSessions: 2,
|
||||
invalidatedPasswordResetCodes: 1,
|
||||
consumedEmailLoginCodes: 3,
|
||||
auditCreated: true,
|
||||
});
|
||||
expect(tx.employee.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { id: "00000000-0000-4000-8000-000000000001" },
|
||||
data: expect.objectContaining({
|
||||
must_change_password: true,
|
||||
login_failed_count: 0,
|
||||
email_login_code_failed_count: 0,
|
||||
password_reset_failed_count: 0,
|
||||
token_version: { increment: 1 },
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(tx.authSession.updateMany).toHaveBeenCalledTimes(1);
|
||||
expect(tx.passwordResetCode.updateMany).toHaveBeenCalledTimes(1);
|
||||
expect(tx.emailLoginCode.updateMany).toHaveBeenCalledTimes(1);
|
||||
expect(tx.auditLog.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
action: "SYSTEM_ADMIN_BREAK_GLASS_PASSWORD_RESET",
|
||||
extra: { credentialRecorded: false },
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
it("verifies the post-reset state without returning an account identifier", async () => {
|
||||
const { prisma } = createPrismaFixture();
|
||||
|
||||
await expect(verifyState(prisma)).resolves.toEqual({
|
||||
status: "PASS",
|
||||
activeAdminMatches: 1,
|
||||
exactTarget: true,
|
||||
mustChangePassword: true,
|
||||
locksCleared: true,
|
||||
activeSessions: 0,
|
||||
activePasswordResetCodes: 0,
|
||||
activeEmailLoginCodes: 0,
|
||||
auditPresent: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("verifies that the administrator completed the forced password change", async () => {
|
||||
const { prisma } = createPrismaFixture();
|
||||
prisma.employee.findUnique.mockResolvedValue({
|
||||
must_change_password: false,
|
||||
login_failed_count: 0,
|
||||
login_locked_until: null,
|
||||
email_login_code_failed_count: 0,
|
||||
email_login_code_locked_until: null,
|
||||
password_reset_failed_count: 0,
|
||||
password_reset_locked_until: null,
|
||||
});
|
||||
prisma.authSession.count.mockResolvedValue(1);
|
||||
prisma.auditLog.count.mockResolvedValueOnce(1).mockResolvedValueOnce(1);
|
||||
|
||||
await expect(verifyCompletedPasswordChange(prisma)).resolves.toEqual({
|
||||
status: "PASS",
|
||||
activeAdminMatches: 1,
|
||||
exactTarget: true,
|
||||
mustChangePassword: false,
|
||||
locksCleared: true,
|
||||
activeSessions: 1,
|
||||
passwordChangeAuditPresent: true,
|
||||
breakGlassAuditPresent: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("classifies whether a recent password login happened inside the WeCom webview", async () => {
|
||||
const { prisma } = createPrismaFixture();
|
||||
prisma.auditLog.findMany = vi.fn().mockResolvedValue([
|
||||
{ action: "AUTH_LOGIN_SUCCESS", user_agent: "wxwork MicroMessenger" },
|
||||
{ action: "AUTH_LOGIN_SUCCESS", user_agent: "Desktop Browser" },
|
||||
]);
|
||||
|
||||
await expect(diagnoseWecomBinding(prisma)).resolves.toEqual({
|
||||
status: "PASS",
|
||||
activeAdminMatches: 1,
|
||||
exactTarget: true,
|
||||
targetBound: false,
|
||||
directoryUserIdPresent: false,
|
||||
latestDirectorySyncSuccessful: false,
|
||||
directoryUserIdAlreadyBoundElsewhere: false,
|
||||
linkedSuccessfulHrSyncPresent: false,
|
||||
recentPasswordLogins: 2,
|
||||
recentPasswordLoginsFromWecomWebView: 1,
|
||||
recentFailedPasswordLogins: 0,
|
||||
recentFailedPasswordLoginsFromWecomWebView: 0,
|
||||
recentWecomBindAudits: 0,
|
||||
recentWecomLoginAudits: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("fails closed when the selected administrator changes before the transaction", async () => {
|
||||
const { prisma, tx } = createPrismaFixture();
|
||||
tx.employee.findUnique.mockResolvedValue({
|
||||
status: "active",
|
||||
archived_at: null,
|
||||
token_version: 8,
|
||||
roles: [{ role_code: "system_admin" }],
|
||||
});
|
||||
|
||||
await expect(applyReset(prisma, "UniqueBreakGlass9Qz!")).rejects.toThrow(
|
||||
"active_admin_target_changed",
|
||||
);
|
||||
expect(tx.employee.update).not.toHaveBeenCalled();
|
||||
expect(tx.auditLog.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
在新工单中引用
屏蔽一个用户