123
This commit is contained in:
@ -15,12 +15,20 @@ import { UsersModule } from '../users/users.module';
|
||||
PassportModule.register({ defaultStrategy: 'jwt' }),
|
||||
JwtModule.registerAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => ({
|
||||
secret: configService.get('JWT_SECRET'),
|
||||
signOptions: {
|
||||
expiresIn: '7d',
|
||||
},
|
||||
}),
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
const secret = configService.get<string>('JWT_SECRET');
|
||||
if (!secret || secret.trim() === '') {
|
||||
throw new Error(
|
||||
'JWT_SECRET is not set or empty. Set it in .env and run Docker with: docker compose --env-file .env up -d',
|
||||
);
|
||||
}
|
||||
return {
|
||||
secret: secret.trim(),
|
||||
signOptions: {
|
||||
expiresIn: '7d',
|
||||
},
|
||||
};
|
||||
},
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
UsersModule,
|
||||
|
||||
48
apps/api/src/common/all-exceptions.filter.ts
Normal file
48
apps/api/src/common/all-exceptions.filter.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import {
|
||||
ExceptionFilter,
|
||||
Catch,
|
||||
ArgumentsHost,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Logger,
|
||||
} from '@nestjs/common';
|
||||
import { Request, Response } from 'express';
|
||||
|
||||
/**
|
||||
* Логирует все необработанные ошибки в консоль (видны в docker logs coursecraft-api).
|
||||
* Помогает диагностировать 500 при запуске в Docker.
|
||||
*/
|
||||
@Catch()
|
||||
export class AllExceptionsFilter implements ExceptionFilter {
|
||||
private readonly logger = new Logger(AllExceptionsFilter.name);
|
||||
|
||||
catch(exception: unknown, host: ArgumentsHost): void {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<Response>();
|
||||
const request = ctx.getRequest<Request>();
|
||||
|
||||
const status =
|
||||
exception instanceof HttpException
|
||||
? exception.getStatus()
|
||||
: HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
|
||||
const message =
|
||||
exception instanceof HttpException
|
||||
? exception.getResponse()
|
||||
: exception instanceof Error
|
||||
? exception.message
|
||||
: 'Internal server error';
|
||||
|
||||
this.logger.error(
|
||||
`${request.method} ${request.url} → ${status}`,
|
||||
exception instanceof Error ? exception.stack : String(exception),
|
||||
);
|
||||
|
||||
response.status(status).json({
|
||||
statusCode: status,
|
||||
message: typeof message === 'object' && message && 'message' in message
|
||||
? (message as { message: string }).message
|
||||
: message,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -4,11 +4,14 @@ import { ConfigService } from '@nestjs/config';
|
||||
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
||||
import helmet from 'helmet';
|
||||
import { AppModule } from './app.module';
|
||||
import { AllExceptionsFilter } from './common/all-exceptions.filter';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const configService = app.get(ConfigService);
|
||||
|
||||
app.useGlobalFilters(new AllExceptionsFilter());
|
||||
|
||||
// Security
|
||||
app.use(helmet());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user