R87 修复企微直登会话提示
这个提交包含在:
@@ -28,6 +28,16 @@ function refreshCookieOptions(config) {
|
||||
};
|
||||
}
|
||||
|
||||
function sessionHintCookieOptions(config) {
|
||||
return {
|
||||
httpOnly: false,
|
||||
sameSite: "strict",
|
||||
secure: config.cookieSecure,
|
||||
path: "/",
|
||||
maxAge: config.refreshTtlSeconds,
|
||||
};
|
||||
}
|
||||
|
||||
function bindCookieOptions(config) {
|
||||
return {
|
||||
httpOnly: true,
|
||||
@@ -519,6 +529,7 @@ async function wecomAuthRoutes(fastify) {
|
||||
});
|
||||
|
||||
reply.setCookie(fastify.config.refreshCookieName, session.refreshToken, refreshCookieOptions(fastify.config));
|
||||
reply.setCookie("has_session", "1", sessionHintCookieOptions(fastify.config));
|
||||
return reply.redirect(`${origin}${returnTo}`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,6 +225,58 @@ describe("wecom auth routes R27", () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("sets session hint cookie after successful wecom login callback", async () => {
|
||||
mockWecomFetch({ userId: "wecom-bound-user" });
|
||||
const authSession = {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
updateMany: vi.fn().mockResolvedValue({ count: 0 }),
|
||||
create: vi.fn().mockResolvedValue({ id: "session-1" }),
|
||||
};
|
||||
const prisma = buildPrisma({
|
||||
authSession,
|
||||
wecomIdentityBinding: {
|
||||
findUnique: vi.fn().mockResolvedValue({
|
||||
employee_id: EMPLOYEE_ID,
|
||||
employee: {
|
||||
id: EMPLOYEE_ID,
|
||||
status: "active",
|
||||
token_version: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
prisma.$transaction = vi.fn(async (callback) => callback(prisma));
|
||||
const app = await buildApp({ prisma });
|
||||
const state = signPayload({
|
||||
exp: Date.now() + 60_000,
|
||||
nonce: "nonce-login-success",
|
||||
returnTo: "/portal",
|
||||
mode: "login",
|
||||
}, JWT_SECRET);
|
||||
|
||||
const response = await app.inject({
|
||||
method: "GET",
|
||||
url: `/api/auth/wecom/callback?state=${encodeURIComponent(state)}&code=test-code`,
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(302);
|
||||
expect(response.headers.location).toBe("https://oa.hyinda.com/portal");
|
||||
const setCookieHeader = String(response.headers["set-cookie"] ?? "");
|
||||
expect(setCookieHeader).toContain("refresh_token=");
|
||||
expect(setCookieHeader).toContain("has_session=1");
|
||||
expect(authSession.create).toHaveBeenCalled();
|
||||
expect(prisma.auditLog.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
actor_id: EMPLOYEE_ID,
|
||||
action: "AUTH_WECOM_LOGIN_SUCCESS",
|
||||
target_type: "employee",
|
||||
target_id: EMPLOYEE_ID,
|
||||
}),
|
||||
}));
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("returns structured diagnostics when wecom callback has only open id", async () => {
|
||||
const logs = [];
|
||||
mockWecomFetchWithPayload({
|
||||
|
||||
在新工单中引用
屏蔽一个用户