- Integrated Sentry status check functionality in the health controller. - Updated tests to validate Sentry active/disabled states. - Improved Sentry initialization with enhanced logging and error handling.
97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
import { createHash } from "node:crypto";
|
|
import { Logger, ValidationPipe } from "@nestjs/common";
|
|
import { ConfigService } from "@nestjs/config";
|
|
import { NestFactory } from "@nestjs/core";
|
|
import { NestExpressApplication } from "@nestjs/platform-express";
|
|
import * as Sentry from "@sentry/nestjs";
|
|
import { nodeProfilingIntegration } from "@sentry/profiling-node";
|
|
import helmet from "helmet";
|
|
import { AppModule } from "./app.module";
|
|
import { AllExceptionsFilter } from "./common/filters/http-exception.filter";
|
|
|
|
async function bootstrap() {
|
|
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
|
const configService = app.get(ConfigService);
|
|
const logger = new Logger("Bootstrap");
|
|
|
|
// Activer trust proxy pour récupérer l'IP réelle derrière un reverse proxy
|
|
app.set("trust proxy", true);
|
|
|
|
const sentryDsn = configService.get<string>("SENTRY_DSN");
|
|
if (sentryDsn) {
|
|
try {
|
|
Sentry.init({
|
|
dsn: sentryDsn,
|
|
integrations: [Sentry.nestIntegration(), nodeProfilingIntegration()],
|
|
tracesSampleRate: 1.0,
|
|
profilesSampleRate: 1.0,
|
|
sendDefaultPii: false, // RGPD
|
|
beforeSend(event) {
|
|
// Hachage de l'IP utilisateur pour Sentry si elle est présente
|
|
if (event.user?.ip_address) {
|
|
event.user.ip_address = createHash("sha256")
|
|
.update(event.user.ip_address)
|
|
.digest("hex");
|
|
}
|
|
return event;
|
|
},
|
|
});
|
|
|
|
const client = Sentry.getClient();
|
|
if (client?.getOptions().dsn) {
|
|
logger.log("Sentry is initialized and connection is active");
|
|
} else {
|
|
logger.warn("Sentry initialized but DSN is missing");
|
|
}
|
|
} catch (error) {
|
|
logger.error(`Failed to initialize Sentry: ${error.message}`);
|
|
}
|
|
} else {
|
|
logger.warn("Sentry is disabled (SENTRY_DSN not configured)");
|
|
}
|
|
|
|
// Sécurité
|
|
app.use(
|
|
helmet({
|
|
crossOriginResourcePolicy: { policy: "cross-origin" },
|
|
}),
|
|
);
|
|
const corsEnabled = Boolean(configService.get<boolean>("ENABLE_CORS"));
|
|
if (corsEnabled) {
|
|
const domainName = configService.get<string>("CORS_DOMAIN_NAME");
|
|
app.enableCors({
|
|
origin: (origin, callback) => {
|
|
if (!origin || domainName === "*") {
|
|
callback(null, true);
|
|
return;
|
|
}
|
|
|
|
const allowedOrigins = domainName?.split(",").map((o) => o.trim()) || [];
|
|
if (allowedOrigins.includes(origin)) {
|
|
callback(null, true);
|
|
} else {
|
|
callback(null, false);
|
|
}
|
|
},
|
|
credentials: true,
|
|
});
|
|
}
|
|
|
|
// Validation Globale
|
|
app.useGlobalPipes(
|
|
new ValidationPipe({
|
|
whitelist: true,
|
|
forbidNonWhitelisted: true,
|
|
transform: true,
|
|
}),
|
|
);
|
|
|
|
// Filtre d'exceptions global
|
|
app.useGlobalFilters(new AllExceptionsFilter());
|
|
|
|
const port = configService.get<number>("PORT") || 3000;
|
|
await app.listen(port);
|
|
logger.log(`Application is running on: http://localhost:${port}`);
|
|
}
|
|
bootstrap().then();
|