ci: docker_tag=ext chore(back): v1.0.3 IdNot 4xx passthrough robuste
All checks were successful
build-and-push-ext / build_push (push) Successful in 24s
All checks were successful
build-and-push-ext / build_push (push) Successful in 24s
This commit is contained in:
parent
bd042533b2
commit
723b532c64
@ -14,3 +14,10 @@
|
|||||||
- 5xx: erreurs internes ou partenaires (non applicatives)
|
- 5xx: erreurs internes ou partenaires (non applicatives)
|
||||||
- Documentation et tests mis à jour pour couvrir “JSON invalide -> 400”.
|
- Documentation et tests mis à jour pour couvrir “JSON invalide -> 400”.
|
||||||
- CI: utiliser `ci: docker_tag=ext` pour builder/pusher l’image.
|
- CI: utiliser `ci: docker_tag=ext` pour builder/pusher l’image.
|
||||||
|
|
||||||
|
## v1.0.3
|
||||||
|
|
||||||
|
- IdNot: renforcement de la gestion d’erreurs applicatives (4xx) dans `IdNotController.authenticate`.
|
||||||
|
- Laisse désormais passer toute erreur avec `statusCode` 4xx même si l’instance n’est pas exactement celle des classes locales.
|
||||||
|
- Fallback sur `name` (BusinessRuleError, ForbiddenError, UnauthorizedError, ValidationError) pour tolérer les divergences d’instances.
|
||||||
|
- Objectif: éviter les 502 lorsqu’un cas fonctionnel (ex: utilisateur non rattaché) survient, et renvoyer le bon 4xx.
|
||||||
|
@ -36,6 +36,8 @@ Analyse synthétique de `lecoffre-back-mini` (Express + TypeScript).
|
|||||||
- `403`: utilisateur non rattaché à une étude (ForbiddenError)
|
- `403`: utilisateur non rattaché à une étude (ForbiddenError)
|
||||||
- `5xx`: erreurs internes ou partenaires (ExternalServiceError)
|
- `5xx`: erreurs internes ou partenaires (ExternalServiceError)
|
||||||
|
|
||||||
|
Note: dans `IdNotController.authenticate`, toute erreur possédant un `statusCode` 4xx (ou un `name` applicatif connu) est relancée telle quelle afin d’éviter un fallback en 502.
|
||||||
|
|
||||||
### Dépendances clés
|
### Dépendances clés
|
||||||
- **HTTP**: `express`, `cors`
|
- **HTTP**: `express`, `cors`
|
||||||
- **Infra**: `pg`, `dotenv`
|
- **Infra**: `pg`, `dotenv`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lecoffre-back-mini",
|
"name": "lecoffre-back-mini",
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"description": "Mini serveur avec une route /api/ping",
|
"description": "Mini serveur avec une route /api/ping",
|
||||||
"main": "dist/server.js",
|
"main": "dist/server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -174,11 +174,25 @@ export class IdNotController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Laisser passer les erreurs applicatives connues (4xx) pour éviter un 502 côté client
|
// Laisser passer les erreurs applicatives connues (4xx) pour éviter un 502 côté client
|
||||||
|
// Approche robuste: on tolère les divergences d'instance en vérifiant le statusCode et le nom
|
||||||
|
const maybeStatus = (error as any)?.statusCode;
|
||||||
|
const maybeName = (error as any)?.name as string | undefined;
|
||||||
|
|
||||||
|
// 1) Si une erreur possède un statusCode 4xx, on la relaisse passer
|
||||||
|
if (typeof maybeStatus === 'number' && maybeStatus >= 400 && maybeStatus < 500) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Si le nom correspond à une erreur applicative connue, on la relaisse passer
|
||||||
if (
|
if (
|
||||||
error instanceof BusinessRuleError ||
|
error instanceof BusinessRuleError ||
|
||||||
error instanceof ForbiddenError ||
|
error instanceof ForbiddenError ||
|
||||||
error instanceof UnauthorizedError ||
|
error instanceof UnauthorizedError ||
|
||||||
error instanceof ValidationError
|
error instanceof ValidationError ||
|
||||||
|
maybeName === 'BusinessRuleError' ||
|
||||||
|
maybeName === 'ForbiddenError' ||
|
||||||
|
maybeName === 'UnauthorizedError' ||
|
||||||
|
maybeName === 'ValidationError'
|
||||||
) {
|
) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ export const errorHandler = (
|
|||||||
next: NextFunction
|
next: NextFunction
|
||||||
): void => {
|
): void => {
|
||||||
const requestId = req.headers['x-request-id'] as string || 'unknown';
|
const requestId = req.headers['x-request-id'] as string || 'unknown';
|
||||||
|
|
||||||
// If it's already an AppError, use it directly
|
// If it's already an AppError, use it directly
|
||||||
if (error instanceof AppError) {
|
if (error instanceof AppError) {
|
||||||
Logger.error('Application error occurred', {
|
Logger.error('Application error occurred', {
|
||||||
@ -43,7 +43,7 @@ export const errorHandler = (
|
|||||||
undefined,
|
undefined,
|
||||||
requestId
|
requestId
|
||||||
);
|
);
|
||||||
|
|
||||||
Logger.error('Validation error', {
|
Logger.error('Validation error', {
|
||||||
requestId,
|
requestId,
|
||||||
originalError: error.message,
|
originalError: error.message,
|
||||||
@ -63,7 +63,7 @@ export const errorHandler = (
|
|||||||
undefined,
|
undefined,
|
||||||
requestId
|
requestId
|
||||||
);
|
);
|
||||||
|
|
||||||
Logger.error('Unauthorized access attempt', {
|
Logger.error('Unauthorized access attempt', {
|
||||||
requestId,
|
requestId,
|
||||||
error: error.message,
|
error: error.message,
|
||||||
@ -161,11 +161,11 @@ export const asyncHandler = (fn: Function) => {
|
|||||||
|
|
||||||
// Request ID middleware
|
// Request ID middleware
|
||||||
export const requestIdMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
export const requestIdMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
||||||
const requestId = req.headers['x-request-id'] as string ||
|
const requestId = req.headers['x-request-id'] as string ||
|
||||||
`req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
`req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
|
||||||
req.headers['x-request-id'] = requestId;
|
req.headers['x-request-id'] = requestId;
|
||||||
res.setHeader('X-Request-ID', requestId);
|
res.setHeader('X-Request-ID', requestId);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
@ -19,3 +19,6 @@ Axes de tests pour `lecoffre-back-mini` (sans exemples d’implémentation).
|
|||||||
- Vérifier POST `/api/v1/idnot/auth` avec un code long dans le corps JSON (`{ code }`) retourne un statut applicatif (4xx/5xx) mais pas 502.
|
- Vérifier POST `/api/v1/idnot/auth` avec un code long dans le corps JSON (`{ code }`) retourne un statut applicatif (4xx/5xx) mais pas 502.
|
||||||
- Vérifier qu’un corps JSON invalide (ex: JSON mal formé) renvoie `400`.
|
- Vérifier qu’un corps JSON invalide (ex: JSON mal formé) renvoie `400`.
|
||||||
- Vérifier qu’un GET/POST avec segment d’URL trop long n’est plus utilisé par le front.
|
- Vérifier qu’un GET/POST avec segment d’URL trop long n’est plus utilisé par le front.
|
||||||
|
|
||||||
|
Focus régression v1.0.3:
|
||||||
|
- Cas « utilisateur non rattaché à une étude » doit renvoyer `403` (plus de 502).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user