Deuxième volet backend du tutoriel guidé, sur le socle de #42/#44 : permet à un admin de créer/éditer/supprimer les scénarios que `GET /reference/tours` sert au moteur front. `/admin/api/tours` (agrégateur `admin.routes.ts`, tout derrière `requireAdmin`) : - `GET /` — tous les scénarios (activés **et** désactivés) + étapes ordonnées. - `GET /targets` — le catalogue `TourTarget` pour le sélecteur de cible de l'éditeur. - `POST /` — crée un scénario vide (`key` + `name`) ; 409 `TOUR_KEY_ALREADY_IN_USE` (nouveau code 4025) sur une clé prise. - `PATCH /:id` — édite `name`/`enabled` **et remplace toute la liste d'étapes en bloc** (delete-all puis recreate avec `order` = index), même convention que `updateRecipe` pour les étapes d'une recette. `key` immuable. 404 `TOUR_NOT_FOUND` (id inconnu), 404 `TOUR_TARGET_NOT_FOUND` (nouveau code 4054, `targetKey` d'une étape hors catalogue — vérifié avant d'écrire, les étapes réelles restent intactes si la requête est rejetée). - `DELETE /:id` — 204 ; les étapes et les `TourProgress` des utilisateurs cascadent. Tests Mocha (`admin-tours.test.ts`) : 401 sans session admin sur chaque route ; list (activés+désactivés) ; targets ; create→patch pour remplir les étapes ; remplacement en bloc ; 409 clé dupliquée ; 404 cible inconnue (sans toucher aux étapes existantes) ; 404 id inconnu ; delete + cascade vérifiée ; un scénario désactivé disparaît de `/reference/tours` mais reste dans la liste admin. Refs #44 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
28 lines
1.3 KiB
TypeScript
28 lines
1.3 KiB
TypeScript
import { Router } from "express";
|
|
import { adminAuthRouter } from "./admin-auth.routes.js";
|
|
import { adminCatalogRouter } from "./admin-catalog.routes.js";
|
|
import { adminMetricsRouter } from "./admin-metrics.routes.js";
|
|
import { adminTechStepsRouter } from "./admin-tech-steps.routes.js";
|
|
import { adminToursRouter } from "./admin-tours.routes.js";
|
|
|
|
/**
|
|
* Aggregator for the admin application's API surface, mounted at
|
|
* `/admin/api` in `app.ts` (not bare `/admin` — see that mount point's own
|
|
* comment for why: it would collide with apps/web's `/admin/*` page
|
|
* routes). Every sub-router here backs one of those pages —
|
|
* `/admin/api/auth` is public (login), everything added later
|
|
* (`/admin/api/metrics`, `/admin/api/tech-steps/*`, `/admin/api/catalog/*`)
|
|
* sits behind `requireAdmin` (`middlewares/require-admin.ts`).
|
|
*
|
|
* Monitoring has **no** REST route here on purpose — it's pushed over
|
|
* WebSocket instead (`lib/monitoring-broadcast.service.ts`, wired in
|
|
* `server.ts`), not requested per-page-load. See that service's doc
|
|
* comment for the full mechanism.
|
|
*/
|
|
export const adminRouter = Router();
|
|
|
|
adminRouter.use("/auth", adminAuthRouter);
|
|
adminRouter.use("/metrics", adminMetricsRouter);
|
|
adminRouter.use("/tech-steps", adminTechStepsRouter);
|
|
adminRouter.use("/catalog", adminCatalogRouter);
|
|
adminRouter.use("/tours", adminToursRouter);
|