import { describe, it, expect } from 'vitest' import { readFileSync } from 'node:fs' import { resolve } from 'node:path' const adminDir = resolve(import.meta.dirname, '../../../server/api/admin') // All admin routes grouped by directory const adminRoutes = { 'admin/': [ 'dashboard.get.js', 'events.get.js', 'events.post.js', 'members.get.js', 'members.post.js', 'series.get.js', 'series.post.js', 'series.put.js' ], 'admin/events/': [ 'events/[id].delete.js', 'events/[id].get.js', 'events/[id].put.js' ], 'admin/members/': [ 'members/[id].put.js', 'members/[id]/role.patch.js', 'members/import.post.js', 'members/invite.post.js' ], 'admin/series/': [ 'series/[id].delete.js', 'series/[id].put.js', 'series/tickets.put.js' ], 'admin/pre-registrants/': [ 'pre-registrants/index.get.js', 'pre-registrants/[id].get.js', 'pre-registrants/[id].put.js', 'pre-registrants/bulk-status.patch.js', 'pre-registrants/invite.post.js', 'pre-registrants/stats.get.js' ], 'admin/alerts/': [ 'alerts/index.get.js', 'alerts/dismiss.post.js' ] } // Business logic markers that must appear after requireAdmin const businessLogicPatterns = [ 'readBody(event)', 'validateBody(event', 'fetch(', 'connectDB()', 'Member.find', 'Member.findOne', 'Member.findById', 'Member.countDocuments', 'Event.find', 'Event.findOne', 'Event.findById', 'Event.countDocuments', 'Series.find', 'Series.findOne', 'Series.findById', 'PreRegistration.find', 'PreRegistration.findById', 'PreRegistration.aggregate', 'PreRegistration.updateMany', 'computeAllAlerts(', 'AdminAlertDismissal.findOneAndUpdate' ] describe('Admin endpoint auth guards', () => { for (const [group, files] of Object.entries(adminRoutes)) { describe(group, () => { for (const file of files) { describe(file, () => { const source = readFileSync(resolve(adminDir, file), 'utf-8') it('calls requireAdmin', () => { expect(source).toContain('requireAdmin(event)') }) it('calls requireAdmin before any business logic', () => { const adminIndex = source.indexOf('requireAdmin(event)') expect(adminIndex).toBeGreaterThan(-1) for (const pattern of businessLogicPatterns) { const patternIndex = source.indexOf(pattern) if (patternIndex > -1) { expect( adminIndex, `requireAdmin must appear before ${pattern} in ${file}` ).toBeLessThan(patternIndex) } } }) }) } }) } })