forked from Shared/esg
feat: add Persian error translations and comprehensive test suite
Implement normalized error handling with Persian translations across all exception types, replace legacy NestJS exceptions with AppException, and add unit, integration, and smoke tests. - Add error catalog with gateway-owned codes and Persian messages - Introduce AppException wrapping normalized error envelopes - Add translateError helper for automatic messageFa population - Remove claims module and update provider error normalization - Add unit tests for error contracts and helper functions - Add integration tests for admin and inquiry endpoints - Add smoke tests for real provider connectivity - Add test support utilities (auth mocks, assertions, app factory)
This commit is contained in:
@@ -2,11 +2,11 @@ import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Request } from 'express';
|
||||
import { API_KEY_HEADER } from '../../common/constants/app.constants';
|
||||
import { AppException } from '../../common/exceptions/app-exception';
|
||||
|
||||
/**
|
||||
* API key authentication for inquiry endpoints.
|
||||
@@ -22,11 +22,11 @@ export class ApiKeyGuard implements CanActivate {
|
||||
const expected = this.configService.get<string>('auth.apiKey');
|
||||
|
||||
if (!expected) {
|
||||
throw new UnauthorizedException('API key authentication is not configured');
|
||||
throw new AppException('API_KEY_NOT_CONFIGURED');
|
||||
}
|
||||
|
||||
if (!apiKey || apiKey !== expected) {
|
||||
throw new UnauthorizedException('Invalid or missing API key');
|
||||
throw new AppException('INVALID_API_KEY');
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common';
|
||||
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { Request } from 'express';
|
||||
import { ADMIN_ROLES } from '../../common/enums/role.enum';
|
||||
import { InquiryType } from '../../common/enums/inquiry-type.enum';
|
||||
import { INQUIRY_ACCESS_KEY } from '../constants/auth.constants';
|
||||
import { AuthenticatedUser } from '../interfaces/authenticated-user.interface';
|
||||
import { AppException } from '../../common/exceptions/app-exception';
|
||||
|
||||
/**
|
||||
* Validates that the user may call a specific inquiry endpoint.
|
||||
@@ -28,7 +29,7 @@ export class InquiryAccessGuard implements CanActivate {
|
||||
const user = request.user;
|
||||
|
||||
if (!user) {
|
||||
throw new ForbiddenException('Authentication required');
|
||||
throw new AppException('AUTHENTICATION_REQUIRED');
|
||||
}
|
||||
|
||||
if (ADMIN_ROLES.includes(user.role)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { ExecutionContext, Injectable } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { JWT_ACCESS_STRATEGY } from '../constants/auth.constants';
|
||||
import { AppException } from '../../common/exceptions/app-exception';
|
||||
|
||||
/**
|
||||
* Protects routes with Passport JWT access strategy.
|
||||
@@ -14,7 +15,7 @@ export class JwtAuthGuard extends AuthGuard(JWT_ACCESS_STRATEGY) {
|
||||
_context: ExecutionContext,
|
||||
): TUser {
|
||||
if (err || !user) {
|
||||
throw err ?? new UnauthorizedException('Unauthorized');
|
||||
throw err ?? new AppException('UNAUTHORIZED');
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common';
|
||||
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { Request } from 'express';
|
||||
import { ROLES_KEY } from '../constants/auth.constants';
|
||||
import { AuthenticatedUser } from '../interfaces/authenticated-user.interface';
|
||||
import { Role } from '../../common/enums/role.enum';
|
||||
import { AppException } from '../../common/exceptions/app-exception';
|
||||
|
||||
/**
|
||||
* Enforces @Roles() metadata against the authenticated user's role.
|
||||
@@ -26,7 +27,7 @@ export class RolesGuard implements CanActivate {
|
||||
const user = request.user;
|
||||
|
||||
if (!user || !requiredRoles.includes(user.role)) {
|
||||
throw new ForbiddenException('Insufficient role permissions');
|
||||
throw new AppException('INSUFFICIENT_ROLE');
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user