import {Request, Response} from 'express'; jest.mock('../../src/models/calendar/users/users.service', () => ({ checkSession: jest.fn() })); import * as UserService from '../../src/models/calendar/users/users.service'; import {requireAdminAuth, sessionHeaderAuthenticator} from '../../src/models/feedback/feedback.auth'; const mockCheckSession = UserService.checkSession as jest.Mock; const makeReq = (headers: Record): Request => { return { header: (name: string) => headers[name], ip: '203.0.113.42' } as unknown as Request; }; const makeRes = (): Response => { const res: any = {}; res.status = jest.fn().mockReturnValue(res); res.send = jest.fn().mockReturnValue(res); res.locals = {}; return res as Response; }; describe('sessionHeaderAuthenticator', () => { beforeEach(() => mockCheckSession.mockReset()); it('returns null when headers are missing', async () => { const identity = await sessionHeaderAuthenticator(makeReq({})); expect(identity).toBeNull(); expect(mockCheckSession).not.toHaveBeenCalled(); }); it('returns null when checkSession finds no user', async () => { mockCheckSession.mockResolvedValue(null); const identity = await sessionHeaderAuthenticator(makeReq({'X-Session-Id': '1', 'X-Session-Key': 'k'})); expect(identity).toBeNull(); }); it('returns null for a valid session on an inactive account', async () => { mockCheckSession.mockResolvedValue({userId: 1, email: 'a@nachklang.art', fullName: 'A', isActive: false}); const identity = await sessionHeaderAuthenticator(makeReq({'X-Session-Id': '1', 'X-Session-Key': 'k'})); expect(identity).toBeNull(); }); it('returns the identity for a valid session on an active account', async () => { mockCheckSession.mockResolvedValue({userId: 1, email: 'a@nachklang.art', fullName: 'Anna Admin', isActive: true}); const identity = await sessionHeaderAuthenticator(makeReq({'X-Session-Id': '1', 'X-Session-Key': 'k'})); expect(identity).toEqual({id: '1', email: 'a@nachklang.art', displayName: 'Anna Admin'}); }); it('passes the session id and key from headers through to checkSession, never from query params', async () => { mockCheckSession.mockResolvedValue({userId: 1, email: 'a@nachklang.art', fullName: 'A', isActive: true}); await sessionHeaderAuthenticator(makeReq({'X-Session-Id': '42', 'X-Session-Key': 'sekret'})); expect(mockCheckSession).toHaveBeenCalledWith('42', 'sekret', '203.0.113.42'); }); }); describe('requireAdminAuth', () => { beforeEach(() => mockCheckSession.mockReset()); it('responds 401 and does not call next() when unauthenticated', async () => { mockCheckSession.mockResolvedValue(null); const req = makeReq({}); const res = makeRes(); const next = jest.fn(); await requireAdminAuth(req, res, next); expect(res.status).toHaveBeenCalledWith(401); expect(next).not.toHaveBeenCalled(); }); it('sets res.locals.admin and calls next() when authenticated', async () => { mockCheckSession.mockResolvedValue({userId: 1, email: 'a@nachklang.art', fullName: 'Anna Admin', isActive: true}); const req = makeReq({'X-Session-Id': '1', 'X-Session-Key': 'k'}); const res = makeRes(); const next = jest.fn(); await requireAdminAuth(req, res, next); expect(next).toHaveBeenCalled(); expect(res.locals.admin).toEqual({id: '1', email: 'a@nachklang.art', displayName: 'Anna Admin'}); }); });