Files
Zumri-Backend/tests/unit/session.service.test.js
T
Sathira Sri Sathara 9d3d431416 feat: implement identity and security features
- Added account types and privileged account types constants.
- Created admin user controller for updating user security fields.
- Developed role assignment controller for managing user roles.
- Implemented validation middleware for request schemas.
- Defined user role and auth session models for database interactions.
- Created services for authentication, email notifications, and OTP handling.
- Developed OAuth service for Google and Apple authentication.
- Added JWT utility functions for token generation and verification.
- Implemented comprehensive tests for authentication, session management, and password policies.
- Created migration for updating user schema and adding new tables for auth sessions and user identities.
2026-09-03 13:56:18 +05:30

38 lines
2.5 KiB
JavaScript

const mockTransaction = { LOCK: { UPDATE: "UPDATE" } };
const mockDb = {
AuthSession: { create: jest.fn(), findByPk: jest.fn(), update: jest.fn() },
User: { findByPk: jest.fn() },
sequelize: { transaction: jest.fn((callback) => callback(mockTransaction)) },
};
jest.mock("../../app/models", () => mockDb);
const service = require("../../app/services/auth/session.service");
describe("durable refresh sessions", () => {
beforeEach(() => jest.clearAllMocks());
test("stores a hash and never the raw refresh token", async () => {
mockDb.AuthSession.create.mockImplementation(async (values) => ({ ...values }));
const result = await service.createSession({ user: { id: "usr", tokenVersion: 2 }, rememberMe: false });
expect(result.refreshToken).toContain(`${result.session.id}.`);
expect(result.session.refresh_token_hash).toBe(service.hashRefreshToken(result.refreshToken));
expect(JSON.stringify(result.session)).not.toContain(result.refreshToken);
});
test("rotates once and marks the previous session replaced", async () => {
const token = "11111111-1111-4111-8111-111111111111.secret";
const old = { id: token.split(".")[0], user_id: "usr", token_family_id: "22222222-2222-4222-8222-222222222222", refresh_token_hash: service.hashRefreshToken(token), remember_me: false, token_version: 1, expires_at: new Date(Date.now() + 10000), revoked_at: null, save: jest.fn() };
const user = { id: "usr", accountStatus: "ACTIVE", tokenVersion: 1 };
mockDb.AuthSession.findByPk.mockResolvedValue(old); mockDb.User.findByPk.mockResolvedValue(user);
mockDb.AuthSession.create.mockImplementation(async (values) => ({ ...values }));
const result = await service.rotateSession(token);
expect(result.refreshToken).not.toBe(token);
expect(old.revoked_reason).toBe("ROTATED");
expect(old.replaced_by_session_id).toBe(result.session.id);
});
test("replay of a rotated token revokes its family", async () => {
const token = "id.old-token";
const old = { id: "id", token_family_id: "family", revoked_at: new Date(), revoked_reason: "ROTATED", refresh_token_hash: service.hashRefreshToken(token) };
mockDb.AuthSession.findByPk.mockResolvedValue(old); mockDb.AuthSession.update.mockResolvedValue([1]);
await expect(service.rotateSession(token)).rejects.toMatchObject({ code: "REFRESH_TOKEN_REUSE" });
expect(mockDb.AuthSession.update).toHaveBeenCalledWith(expect.objectContaining({ revoked_reason: "REFRESH_TOKEN_REUSE" }), expect.objectContaining({ where: expect.objectContaining({ token_family_id: "family" }) }));
});
});