54121c1721
- SmtpConfig.bugReportRecipient (nullable, additive Migration 20260914170000), DTO @IsOptional @IsEmail, SAFE_SELECT, getBugReportRecipient gebunden - MailService: Versandkern deliver (wirft, Anhaenge), sendViaTenantTransport bleibt verschluckender Mantel (T-02-12), sendBugReport laesst Fehler durch - POST /bug-reports: Multipart 4 MiB je Route, alle angemeldeten Rollen, Drossel 5/10 min -> 429, PNG-Signatur -> 400, kein Empfaenger -> 409, Versandfehler -> 502, eine Protokollzeile - Falsifizierungen (a)-(d) als Specs; @Expose() im DTO, damit errors auch bei fehlendem Feld zu [] wird - Doku-Zeile fuer rls-access-inventory, TESSERA_BUGREPORT_TO in docker-compose.prod.yml Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { ConfigModule } from '@nestjs/config';
|
|
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
|
|
import { ScheduleModule } from '@nestjs/schedule';
|
|
import { AuthModule } from './auth/auth.module';
|
|
import { BugReportsModule } from './bug-reports/bug-reports.module';
|
|
import { JwtAuthGuard } from './auth/guards/jwt-auth.guard';
|
|
import { RolesGuard } from './auth/guards/roles.guard';
|
|
import { ForcePasswordChangeInterceptor } from './auth/interceptors/force-password-change.interceptor';
|
|
import { HealthModule } from './health/health.module';
|
|
import { LdapModule } from './ldap/ldap.module';
|
|
import { MailModule } from './mail/mail.module';
|
|
import { CalendarModule } from './calendar/calendar.module';
|
|
import { DashboardModule } from './dashboard/dashboard.module';
|
|
import { DkvModule } from './dkv/dkv.module';
|
|
import { CertManagerModule } from './cert-manager/cert-manager.module';
|
|
import { FavoritesModule } from './favorites/favorites.module';
|
|
import { DomaincheckModule } from './domaincheck/domaincheck.module';
|
|
import { GroupsModule } from './groups/groups.module';
|
|
import { ModuleRegistryModule } from './module-registry/module-registry.module';
|
|
import { PrismaModule } from './prisma/prisma.module';
|
|
import { CryptoModule } from './crypto/crypto.module';
|
|
import { SettingsModule } from './settings/settings.module';
|
|
import { TenantGuard } from './tenant/tenant.guard';
|
|
import { TenantModule } from './tenant/tenant.module';
|
|
import { TendersModule } from './tenders/tenders.module';
|
|
import { UserModule } from './user/user.module';
|
|
|
|
@Module({
|
|
imports: [
|
|
ConfigModule.forRoot({ isGlobal: true }),
|
|
ScheduleModule.forRoot(),
|
|
PrismaModule,
|
|
CryptoModule,
|
|
AuthModule,
|
|
UserModule,
|
|
TenantModule,
|
|
HealthModule,
|
|
MailModule,
|
|
LdapModule,
|
|
ModuleRegistryModule,
|
|
GroupsModule,
|
|
DomaincheckModule,
|
|
CertManagerModule,
|
|
DashboardModule,
|
|
CalendarModule,
|
|
SettingsModule,
|
|
DkvModule,
|
|
FavoritesModule,
|
|
TendersModule,
|
|
BugReportsModule,
|
|
],
|
|
providers: [
|
|
// Global JWT guard: all routes require auth unless @Public()
|
|
{
|
|
provide: APP_GUARD,
|
|
useClass: JwtAuthGuard,
|
|
},
|
|
// Runs after JwtAuthGuard — sets req.tenantId from req.user (260911-e2s: no longer creates a Prisma client)
|
|
{
|
|
provide: APP_GUARD,
|
|
useClass: TenantGuard,
|
|
},
|
|
// Global roles guard: checks @Roles() decorator
|
|
{
|
|
provide: APP_GUARD,
|
|
useClass: RolesGuard,
|
|
},
|
|
// Global interceptor: forces password change if mustChangePassword=true (D-06 / Pitfall 5)
|
|
{
|
|
provide: APP_INTERCEPTOR,
|
|
useClass: ForcePasswordChangeInterceptor,
|
|
},
|
|
],
|
|
})
|
|
export class AppModule {}
|