69494d7549
- GroupsService: listForTenant/create/update/remove/getImpact/listMembers/addMembers/removeMember/addUserToDefaultGroup, jede Query tenantId-gescoped (T-15-02/T-15-12)
- isDefault:true läuft in einer Transaktion (updateMany+update), D-13
- getImpact liefert { memberCount, grantCount } für den Löschdialog (D-17)
- removeMember beschränkt sich auf source:MANUAL (D-19)
- GroupsController: 8 rollengeschützte Routen unter /groups
- 19 Tests in groups.service.spec.ts, hand-rolled In-Memory-Fake
73 lines
2.5 KiB
TypeScript
73 lines
2.5 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 { 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 { 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,
|
|
AuthModule,
|
|
UserModule,
|
|
TenantModule,
|
|
HealthModule,
|
|
MailModule,
|
|
LdapModule,
|
|
ModuleRegistryModule,
|
|
GroupsModule,
|
|
DomaincheckModule,
|
|
CertManagerModule,
|
|
DashboardModule,
|
|
CalendarModule,
|
|
SettingsModule,
|
|
DkvModule,
|
|
FavoritesModule,
|
|
TendersModule,
|
|
],
|
|
providers: [
|
|
// Global JWT guard: all routes require auth unless @Public()
|
|
{
|
|
provide: APP_GUARD,
|
|
useClass: JwtAuthGuard,
|
|
},
|
|
// Runs after JwtAuthGuard — sets req.tenantId and req.tenantPrisma from req.user
|
|
{
|
|
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 {}
|