Admin User v1

This commit is contained in:
Eric Gullickson
2025-11-05 19:04:06 -06:00
parent e4e7e32a4f
commit 8174e0d5f9
48 changed files with 11289 additions and 1112 deletions

View File

@@ -0,0 +1,222 @@
/**
* @ai-summary Admin feature routes
* @ai-context Registers admin API endpoints with proper guards
*/
import { FastifyPluginAsync } from 'fastify';
import { AdminController } from './admin.controller';
import {
CreateAdminInput,
AdminAuth0SubInput,
AuditLogsQueryInput
} from './admin.validation';
import { AdminRepository } from '../data/admin.repository';
import { StationOversightService } from '../domain/station-oversight.service';
import { StationsController } from './stations.controller';
import { CatalogController } from './catalog.controller';
import { VehicleCatalogService } from '../domain/vehicle-catalog.service';
import { PlatformCacheService } from '../../platform/domain/platform-cache.service';
import { cacheService } from '../../../core/config/redis';
import { pool } from '../../../core/config/database';
export const adminRoutes: FastifyPluginAsync = async (fastify) => {
const adminController = new AdminController();
// Initialize station oversight dependencies
const adminRepository = new AdminRepository(pool);
const stationOversightService = new StationOversightService(pool, adminRepository);
const stationsController = new StationsController(stationOversightService);
// Initialize catalog dependencies
const platformCacheService = new PlatformCacheService(cacheService);
const catalogService = new VehicleCatalogService(pool, platformCacheService);
const catalogController = new CatalogController(catalogService);
// Admin access verification (used by frontend auth checks)
fastify.get('/admin/verify', {
preHandler: [fastify.authenticate] // Requires JWT, does NOT require admin role
}, adminController.verifyAccess.bind(adminController));
// Phase 2: Admin management endpoints
// GET /api/admin/admins - List all admin users
fastify.get('/admin/admins', {
preHandler: [fastify.requireAdmin],
handler: adminController.listAdmins.bind(adminController)
});
// POST /api/admin/admins - Create new admin
fastify.post<{ Body: CreateAdminInput }>('/admin/admins', {
preHandler: [fastify.requireAdmin],
handler: adminController.createAdmin.bind(adminController)
});
// PATCH /api/admin/admins/:auth0Sub/revoke - Revoke admin access
fastify.patch<{ Params: AdminAuth0SubInput }>('/admin/admins/:auth0Sub/revoke', {
preHandler: [fastify.requireAdmin],
handler: adminController.revokeAdmin.bind(adminController)
});
// PATCH /api/admin/admins/:auth0Sub/reinstate - Restore revoked admin
fastify.patch<{ Params: AdminAuth0SubInput }>('/admin/admins/:auth0Sub/reinstate', {
preHandler: [fastify.requireAdmin],
handler: adminController.reinstateAdmin.bind(adminController)
});
// GET /api/admin/audit-logs - Fetch audit trail
fastify.get<{ Querystring: AuditLogsQueryInput }>('/admin/audit-logs', {
preHandler: [fastify.requireAdmin],
handler: adminController.getAuditLogs.bind(adminController)
});
// Phase 3: Catalog CRUD endpoints
// Makes endpoints
fastify.get('/admin/catalog/makes', {
preHandler: [fastify.requireAdmin],
handler: catalogController.getMakes.bind(catalogController)
});
fastify.post('/admin/catalog/makes', {
preHandler: [fastify.requireAdmin],
handler: catalogController.createMake.bind(catalogController)
});
fastify.put('/admin/catalog/makes/:makeId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.updateMake.bind(catalogController)
});
fastify.delete('/admin/catalog/makes/:makeId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.deleteMake.bind(catalogController)
});
// Models endpoints
fastify.get('/admin/catalog/makes/:makeId/models', {
preHandler: [fastify.requireAdmin],
handler: catalogController.getModels.bind(catalogController)
});
fastify.post('/admin/catalog/models', {
preHandler: [fastify.requireAdmin],
handler: catalogController.createModel.bind(catalogController)
});
fastify.put('/admin/catalog/models/:modelId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.updateModel.bind(catalogController)
});
fastify.delete('/admin/catalog/models/:modelId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.deleteModel.bind(catalogController)
});
// Years endpoints
fastify.get('/admin/catalog/models/:modelId/years', {
preHandler: [fastify.requireAdmin],
handler: catalogController.getYears.bind(catalogController)
});
fastify.post('/admin/catalog/years', {
preHandler: [fastify.requireAdmin],
handler: catalogController.createYear.bind(catalogController)
});
fastify.put('/admin/catalog/years/:yearId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.updateYear.bind(catalogController)
});
fastify.delete('/admin/catalog/years/:yearId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.deleteYear.bind(catalogController)
});
// Trims endpoints
fastify.get('/admin/catalog/years/:yearId/trims', {
preHandler: [fastify.requireAdmin],
handler: catalogController.getTrims.bind(catalogController)
});
fastify.post('/admin/catalog/trims', {
preHandler: [fastify.requireAdmin],
handler: catalogController.createTrim.bind(catalogController)
});
fastify.put('/admin/catalog/trims/:trimId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.updateTrim.bind(catalogController)
});
fastify.delete('/admin/catalog/trims/:trimId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.deleteTrim.bind(catalogController)
});
// Engines endpoints
fastify.get('/admin/catalog/trims/:trimId/engines', {
preHandler: [fastify.requireAdmin],
handler: catalogController.getEngines.bind(catalogController)
});
fastify.post('/admin/catalog/engines', {
preHandler: [fastify.requireAdmin],
handler: catalogController.createEngine.bind(catalogController)
});
fastify.put('/admin/catalog/engines/:engineId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.updateEngine.bind(catalogController)
});
fastify.delete('/admin/catalog/engines/:engineId', {
preHandler: [fastify.requireAdmin],
handler: catalogController.deleteEngine.bind(catalogController)
});
// Change logs endpoint
fastify.get('/admin/catalog/change-logs', {
preHandler: [fastify.requireAdmin],
handler: catalogController.getChangeLogs.bind(catalogController)
});
// Phase 4: Station oversight endpoints
// GET /api/admin/stations - List all stations globally
fastify.get('/admin/stations', {
preHandler: [fastify.requireAdmin],
handler: stationsController.listAllStations.bind(stationsController)
});
// POST /api/admin/stations - Create new station
fastify.post('/admin/stations', {
preHandler: [fastify.requireAdmin],
handler: stationsController.createStation.bind(stationsController)
});
// PUT /api/admin/stations/:stationId - Update station
fastify.put('/admin/stations/:stationId', {
preHandler: [fastify.requireAdmin],
handler: stationsController.updateStation.bind(stationsController)
});
// DELETE /api/admin/stations/:stationId - Delete station (soft delete by default, ?force=true for hard delete)
fastify.delete('/admin/stations/:stationId', {
preHandler: [fastify.requireAdmin],
handler: stationsController.deleteStation.bind(stationsController)
});
// GET /api/admin/users/:userId/stations - Get user's saved stations
fastify.get('/admin/users/:userId/stations', {
preHandler: [fastify.requireAdmin],
handler: stationsController.getUserSavedStations.bind(stationsController)
});
// DELETE /api/admin/users/:userId/stations/:stationId - Remove user's saved station (soft delete by default, ?force=true for hard delete)
fastify.delete('/admin/users/:userId/stations/:stationId', {
preHandler: [fastify.requireAdmin],
handler: stationsController.removeUserSavedStation.bind(stationsController)
});
};