feat: POST /simulations — quota check + insert productions — 65/65 tests

This commit is contained in:
Hermann_Kitio 2026-04-16 14:13:47 +03:00
parent 2fba6f2003
commit bf2c48b2c7
5 changed files with 361 additions and 0 deletions

81
src/routes/simulations.ts Normal file
View file

@ -0,0 +1,81 @@
import { Hono } from 'hono'
import { authMiddleware } from '../middleware/auth'
import type { AppVariables } from '../middleware/auth'
import { getPlanPermissions } from '../lib/access'
import type { Plan } from '../lib/access'
import * as simulationController from '../controllers/simulationController'
import type { Tache, Mode } from '../controllers/simulationController'
const VALID_TACHES: Tache[] = ['EE_T1', 'EE_T2', 'EE_T3', 'EO_T1', 'EO_T3', 'EO_T2_LIVE']
const VALID_MODES: Mode[] = ['entrainement', 'examen']
const simulations = new Hono<{ Variables: AppVariables }>()
simulations.post('/', authMiddleware, async (c) => {
let body: { tache?: unknown; mode?: unknown; contenu?: unknown }
try {
body = await c.req.json()
} catch {
return c.json(
{ error: true, code: 'VALIDATION_ERROR', message: 'Corps de la requête invalide.' },
400
)
}
// Valider tache
if (!body.tache || !VALID_TACHES.includes(body.tache as Tache)) {
return c.json(
{
error: true,
code: 'VALIDATION_ERROR',
message: `Tâche invalide. Valeurs acceptées : ${VALID_TACHES.join(', ')}`,
},
400
)
}
// Valider mode
if (!body.mode || !VALID_MODES.includes(body.mode as Mode)) {
return c.json(
{
error: true,
code: 'VALIDATION_ERROR',
message: `Mode invalide. Valeurs acceptées : ${VALID_MODES.join(', ')}`,
},
400
)
}
const tache = body.tache as Tache
const mode = body.mode as Mode
// Vérifier l'accès EO_T2_LIVE via getPlanPermissions (Règle D)
if (tache === 'EO_T2_LIVE') {
const profile = c.get('profile')
const perms = getPlanPermissions(profile.plan as Plan)
if (!perms.oral_t2_live) {
return c.json(
{
error: true,
code: 'PLAN_INSUFFICIENT',
message: 'La tâche EO T2 live est réservée au plan Premium.',
},
403
)
}
}
const profile = c.get('profile')
const result = await simulationController.create(
{ tache, mode, contenu: body.contenu as string | undefined },
profile
)
if ('error' in result) {
return c.json(result, result.status as 403 | 500)
}
return c.json(result.data, 201)
})
export default simulations