9d3d431416
- 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.
32 lines
2.3 KiB
JavaScript
32 lines
2.3 KiB
JavaScript
const mockDb = { User: { findOne: jest.fn() } };
|
|
const mockCheckPassword = jest.fn();
|
|
const mockCreateChallenge = jest.fn();
|
|
const mockSendOtp = jest.fn();
|
|
jest.mock("../../app/models", () => mockDb);
|
|
jest.mock("../../app/utils/hashPassword.util", () => ({ checkPassword: mockCheckPassword }));
|
|
jest.mock("../../app/services/auth/otp.service", () => ({ createLoginChallenge: mockCreateChallenge, verifyLoginChallenge: jest.fn() }));
|
|
jest.mock("../../app/services/auth/email.service", () => ({ sendLoginOtp: mockSendOtp }));
|
|
jest.mock("../../app/utils/idGen.util", () => ({ generateUserId: jest.fn(), generateId: jest.fn() }));
|
|
jest.mock("../../app/services/auth/session.service", () => ({ createSession: jest.fn(), rotateSession: jest.fn() }));
|
|
jest.mock("../../app/services/auth/oauth.service", () => ({ verifyGoogleToken: jest.fn(), verifyAppleToken: jest.fn() }));
|
|
const { beginPasswordLogin } = require("../../app/services/auth/auth.service");
|
|
const req = { get: jest.fn(), ip: "127.0.0.1" };
|
|
|
|
describe("password login boundary", () => {
|
|
beforeEach(() => { jest.clearAllMocks(); mockCheckPassword.mockResolvedValue(true); });
|
|
test.each(["PENDING_VERIFICATION", "SUSPENDED", "DEACTIVATED"])("rejects %s accounts", async (status) => {
|
|
mockDb.User.findOne.mockResolvedValue({ id: "usr", password: "hash", accountStatus: status, accountType: "customer" });
|
|
await expect(beginPasswordLogin({ email: "x@example.com", password: "secret", rememberMe: false }, req)).rejects.toMatchObject({ code: "ACCOUNT_NOT_ACTIVE" });
|
|
});
|
|
test("uses a generic error for missing users and wrong passwords", async () => {
|
|
mockDb.User.findOne.mockResolvedValue(null);
|
|
await expect(beginPasswordLogin({ email: "x@example.com", password: "wrong" }, req)).rejects.toMatchObject({ code: "INVALID_CREDENTIALS" });
|
|
});
|
|
test("creates an OTP challenge but no session for valid credentials", async () => {
|
|
const user = { id: "usr", password: "hash", accountStatus: "ACTIVE", accountType: "customer" };
|
|
mockDb.User.findOne.mockResolvedValue(user); mockCreateChallenge.mockResolvedValue({ challengeId: "challenge", otp: "123456" });
|
|
await expect(beginPasswordLogin({ email: "x@example.com", password: "secret", rememberMe: true }, req)).resolves.toEqual({ challengeId: "challenge" });
|
|
expect(mockSendOtp).toHaveBeenCalledWith(user, "123456");
|
|
});
|
|
});
|