Files
massive-cloud/server/session.security.test.ts

45 lines
1.8 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import type { User } from "../drizzle/schema";
vi.mock("./db", () => ({ getUserById: vi.fn() }));
import * as db from "./db";
import { authenticateRequest, createSessionToken } from "./_core/auth";
import { ENV } from "./_core/env";
import { COOKIE_NAME } from "../shared/const";
function user(overrides: Partial<User> = {}): User {
const now = new Date();
return { id: 7, username: "session-user", passwordHash: "unused", name: "Session User", email: null, role: "user", isActive: 1, mustChangePassword: 0, sessionVersion: 3, createdAt: now, updatedAt: now, lastLoginAt: null, ...overrides };
}
function requestWith(token: string) {
return { headers: { cookie: `${COOKIE_NAME}=${token}` } } as Parameters<typeof authenticateRequest>[0];
}
describe("会话即时失效", () => {
beforeEach(() => {
vi.clearAllMocks();
ENV.cookieSecret = "test-session-secret-with-at-least-32-chars";
});
it("有效账号与匹配版本可恢复会话", async () => {
const current = user();
vi.mocked(db.getUserById).mockResolvedValue(current);
const token = await createSessionToken(current);
await expect(authenticateRequest(requestWith(token))).resolves.toMatchObject({ id: 7, sessionVersion: 3 });
});
it("改密或重置密码递增版本后旧会话立即失效", async () => {
const token = await createSessionToken(user());
vi.mocked(db.getUserById).mockResolvedValue(user({ sessionVersion: 4 }));
await expect(authenticateRequest(requestWith(token))).resolves.toBeNull();
});
it("账号被禁用后旧会话立即失效", async () => {
const token = await createSessionToken(user());
vi.mocked(db.getUserById).mockResolvedValue(user({ isActive: 0 }));
await expect(authenticateRequest(requestWith(token))).resolves.toBeNull();
});
});