admin login fixed.
Build & Push / Pipeline Tests (push) Failing after 1m34s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 56s
Test / API Unit Tests (push) Successful in 1m8s
Test / Homepage Unit Tests (push) Successful in 47s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 46s
Test / Dashboard Unit Tests (push) Failing after 43s
Test / API Integration Tests (push) Successful in 1m8s

This commit is contained in:
root
2026-07-28 22:56:18 -04:00
parent 5649ab02c7
commit 50c74b9007
29 changed files with 1155 additions and 118 deletions
@@ -16,7 +16,8 @@ vi.mock('../../lib/redis', () => ({
import request from 'supertest'
import { describe, expect, it } from 'vitest'
import { createApp } from '../../app'
import { createApp, isCorsOriginAllowed } from '../../app'
import { isTrustedBrowserOrigin } from '../../middleware/csrf'
const app = createApp()
@@ -87,6 +88,13 @@ describe('API foundation integration', () => {
expect(res.headers['access-control-allow-credentials']).toBe('true')
})
it('trusts private LAN app origins during local development only on known app ports', () => {
expect(isCorsOriginAllowed('http://192.168.3.3:3000')).toBe(true)
expect(isTrustedBrowserOrigin('http://192.168.3.3:3000')).toBe(true)
expect(isCorsOriginAllowed('http://192.168.3.3:8080')).toBe(false)
expect(isTrustedBrowserOrigin('http://192.168.3.3:8080')).toBe(false)
})
it('blocks legacy anonymous access to customer identity document storage paths', async () => {
const res = await request(app).get('/storage/companies/company_1/customers/customer_1/passport.jpg')
@@ -149,4 +149,35 @@ describe('auth middleware API boundaries', () => {
expect(res.body).toEqual({ data: { data: [{ id: 'company_1' }], pagination: { page: 1 } } })
expect(adminService.listCompanies).toHaveBeenCalledWith({ page: 1, pageSize: 20 })
})
it('clears any employee session when admin login succeeds', async () => {
vi.mocked(adminService.login).mockResolvedValue({
token: 'admin-jwt',
admin: { id: 'admin_1', email: 'admin@example.test', role: 'SUPER_ADMIN' },
} as never)
const res = await request(app)
.post('/api/v1/admin/auth/login')
.send({ email: 'admin@example.test', password: 'valid-password' })
expect(res.status).toBe(200)
expect(res.headers['set-cookie']).toEqual(expect.arrayContaining([
expect.stringMatching(/^employee_session=;/),
expect.stringMatching(/^admin_session=/),
]))
})
it('clears any employee session when admin credentials require 2FA', async () => {
vi.mocked(adminService.login).mockResolvedValue({ totpRequired: true } as never)
const res = await request(app)
.post('/api/v1/admin/auth/login')
.send({ email: 'admin@example.test', password: 'valid-password' })
expect(res.status).toBe(401)
expect(res.body.error).toBe('totp_required')
expect(res.headers['set-cookie']).toEqual(expect.arrayContaining([
expect.stringMatching(/^employee_session=;/),
]))
})
})
@@ -95,6 +95,19 @@ describe('employee, notification, and carplace API validation contracts', () =>
expect(employeeService.login).toHaveBeenCalledWith({ email: 'agent@example.test', password: 'valid-password' })
})
it('clears any admin session when employee login succeeds', async () => {
const res = await request(app).post('/api/v1/auth/employee/login').send({
email: 'agent@example.test',
password: 'valid-password',
})
expect(res.status).toBe(200)
expect(res.headers['set-cookie']).toEqual(expect.arrayContaining([
expect.stringMatching(/^admin_session=;/),
expect.stringMatching(/^employee_session=/),
]))
})
it('rejects empty employee reset tokens before service execution', async () => {
const res = await request(app).post('/api/v1/auth/employee/reset-password').send({ token: '', password: 'new-password' })
+43 -1
View File
@@ -3,8 +3,10 @@ import { createApp } from '../../app'
import {
authHeader,
createAdminUser,
createCompanyNotification,
createCompanyWithEmployee,
createRenter,
createRenterNotification,
signAdminToken,
} from '../helpers/fixtures'
@@ -17,6 +19,7 @@ describe('Admin API', () => {
let viewerToken: string
let adminId: string
let companyId: string
let employeeId: string
beforeAll(async () => {
const admin = await createAdminUser({
@@ -56,8 +59,9 @@ describe('Admin API', () => {
})
viewerToken = signAdminToken(viewerAdmin.id)
const { company } = await createCompanyWithEmployee()
const { company, employee } = await createCompanyWithEmployee()
companyId = company.id
employeeId = employee.id
await createRenter()
})
@@ -126,6 +130,41 @@ describe('Admin API', () => {
})
})
describe('GET /api/v1/admin/notifications', () => {
it('returns employee and renter notification deliveries in the platform log', async () => {
const renter = await createRenter()
const employeeNotification = await createCompanyNotification(companyId, employeeId, {
title: 'Employee audit notification',
})
const renterNotification = await createRenterNotification(renter.id, {
companyId,
title: 'Renter audit notification',
})
const res = await request(app)
.get('/api/v1/admin/notifications?pageSize=100')
.set(authHeader(protectedAdminToken))
expect(res.status).toBe(200)
expect(res.body.data.data).toEqual(
expect.arrayContaining([
expect.objectContaining({
notificationId: employeeNotification.notificationEventId,
recipientType: 'EMPLOYEE',
employeeId,
title: 'Employee audit notification',
}),
expect.objectContaining({
notificationId: renterNotification.notificationEventId,
recipientType: 'RENTER',
renterId: renter.id,
title: 'Renter audit notification',
}),
]),
)
})
})
describe('GET /api/v1/admin/metrics', () => {
it('returns 403 for VIEWER role', async () => {
const res = await request(app)
@@ -173,6 +212,9 @@ describe('Admin API', () => {
expect(res.status).toBe(200)
expect(res.body.data.id).toBe(billingAccountId)
expect(res.body.data.company.id).toBe(companyId)
expect(res.body.data.openBalance).toEqual(expect.any(Number))
expect(res.body.data.paidBalance).toEqual(expect.any(Number))
expect(res.body.data.creditBalance).toEqual(expect.any(Number))
expect(Array.isArray(res.body.data.invoices)).toBe(true)
})