- Add deletedAt/deletionScheduledAt fields to User model with indexes - Implement 5 CQRS command handlers: - RequestUserDeletion: 30-day soft-delete grace period - CancelUserDeletion: restore within grace period - ForceDeleteUser: admin immediate deletion with PII anonymization - ProcessScheduledDeletions: cron-ready batch processor - ExportUserData: GDPR Article 20 data portability - Cascade strategy: anonymize PII, expire listings, cancel subscriptions, delete reviews/inquiries/searches/notifications, preserve payments for audit - Add UserDataController with DELETE /users/me, POST /users/me/cancel-deletion, GET /users/me/export, DELETE /users/:id/force (admin) - 22 unit tests covering all handlers (160 files, 853 tests passing) - Migration: 20260410000000_add_user_soft_delete_fields Co-Authored-By: Paperclip <noreply@paperclip.ing>
84 lines
3.7 KiB
TypeScript
84 lines
3.7 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { CqrsModule } from '@nestjs/cqrs';
|
|
import { JwtModule } from '@nestjs/jwt';
|
|
import { PassportModule } from '@nestjs/passport';
|
|
import { CancelUserDeletionHandler } from './application/commands/cancel-user-deletion/cancel-user-deletion.handler';
|
|
import { ExportUserDataHandler } from './application/commands/export-user-data/export-user-data.handler';
|
|
import { ForceDeleteUserHandler } from './application/commands/force-delete-user/force-delete-user.handler';
|
|
import { LoginUserHandler } from './application/commands/login-user/login-user.handler';
|
|
import { ProcessScheduledDeletionsHandler } from './application/commands/process-scheduled-deletions/process-scheduled-deletions.handler';
|
|
import { RefreshTokenHandler } from './application/commands/refresh-token/refresh-token.handler';
|
|
import { RegisterUserHandler } from './application/commands/register-user/register-user.handler';
|
|
import { RequestUserDeletionHandler } from './application/commands/request-user-deletion/request-user-deletion.handler';
|
|
import { VerifyKycHandler } from './application/commands/verify-kyc/verify-kyc.handler';
|
|
import { GetAgentByUserIdHandler } from './application/queries/get-agent-by-user-id/get-agent-by-user-id.handler';
|
|
import { GetProfileHandler } from './application/queries/get-profile/get-profile.handler';
|
|
import { REFRESH_TOKEN_REPOSITORY } from './domain/repositories/refresh-token.repository';
|
|
import { USER_REPOSITORY } from './domain/repositories/user.repository';
|
|
import { PrismaRefreshTokenRepository } from './infrastructure/repositories/prisma-refresh-token.repository';
|
|
import { PrismaUserRepository } from './infrastructure/repositories/prisma-user.repository';
|
|
import { OAuthService } from './infrastructure/services/oauth.service';
|
|
import { TokenService } from './infrastructure/services/token.service';
|
|
import { GoogleOAuthStrategy } from './infrastructure/strategies/google-oauth.strategy';
|
|
import { JwtStrategy } from './infrastructure/strategies/jwt.strategy';
|
|
import { LocalStrategy } from './infrastructure/strategies/local.strategy';
|
|
import { ZaloOAuthStrategy } from './infrastructure/strategies/zalo-oauth.strategy';
|
|
import { AuthController } from './presentation/controllers/auth.controller';
|
|
import { OAuthController } from './presentation/controllers/oauth.controller';
|
|
import { UserDataController } from './presentation/controllers/user-data.controller';
|
|
|
|
const CommandHandlers = [
|
|
RegisterUserHandler,
|
|
LoginUserHandler,
|
|
RefreshTokenHandler,
|
|
VerifyKycHandler,
|
|
RequestUserDeletionHandler,
|
|
CancelUserDeletionHandler,
|
|
ForceDeleteUserHandler,
|
|
ProcessScheduledDeletionsHandler,
|
|
ExportUserDataHandler,
|
|
];
|
|
|
|
const QueryHandlers = [GetProfileHandler, GetAgentByUserIdHandler];
|
|
|
|
@Module({
|
|
imports: [
|
|
CqrsModule,
|
|
PassportModule,
|
|
JwtModule.registerAsync({
|
|
useFactory: () => {
|
|
const secret = process.env['JWT_SECRET'];
|
|
if (!secret) {
|
|
throw new Error('JWT_SECRET environment variable is required');
|
|
}
|
|
return {
|
|
secret,
|
|
signOptions: { expiresIn: '15m', audience: 'goodgo-api', issuer: 'goodgo-platform' },
|
|
};
|
|
},
|
|
}),
|
|
],
|
|
controllers: [AuthController, OAuthController, UserDataController],
|
|
providers: [
|
|
// Repositories
|
|
{ provide: USER_REPOSITORY, useClass: PrismaUserRepository },
|
|
{ provide: REFRESH_TOKEN_REPOSITORY, useClass: PrismaRefreshTokenRepository },
|
|
|
|
// Strategies
|
|
JwtStrategy,
|
|
LocalStrategy,
|
|
GoogleOAuthStrategy,
|
|
ZaloOAuthStrategy,
|
|
|
|
// Services
|
|
TokenService,
|
|
OAuthService,
|
|
|
|
// CQRS
|
|
...CommandHandlers,
|
|
...QueryHandlers,
|
|
],
|
|
exports: [TokenService, OAuthService, USER_REPOSITORY],
|
|
})
|
|
export class AuthModule {}
|