# Guide d'Implémentation du Backend Ce document présente un guide complet pour l'implémentation du backend de l'application de création de groupes, basé sur les spécifications du cahier des charges et les plans détaillés précédemment établis. ## Table des Matières 1. [Vue d'Ensemble](#1-vue-densemble) 2. [Préparation de l'Environnement](#2-préparation-de-lenvironnement) 3. [Structure du Projet](#3-structure-du-projet) 4. [Configuration de Base](#4-configuration-de-base) 5. [Base de Données](#5-base-de-données) 6. [Authentification](#6-authentification) 7. [Modules Fonctionnels](#7-modules-fonctionnels) 8. [Communication en Temps Réel](#8-communication-en-temps-réel) 9. [Sécurité et Conformité RGPD](#9-sécurité-et-conformité-rgpd) 10. [Tests et Documentation](#10-tests-et-documentation) 11. [Déploiement](#11-déploiement) 12. [Calendrier d'Implémentation](#12-calendrier-dimplémentation) ## 1. Vue d'Ensemble L'application est une plateforme de création et de gestion de groupes qui permet aux utilisateurs de créer des groupes en prenant en compte divers paramètres et de conserver un historique des groupes précédemment créés. ### 1.1 Architecture Globale L'application suit une architecture monorepo avec séparation claire entre le frontend et le backend : - **Frontend** : Application Next.js avec App Router et Server Components - **Backend** : API NestJS avec PostgreSQL et DrizzleORM - **Communication** : API REST pour les opérations CRUD et WebSockets pour les mises à jour en temps réel - **Authentification** : OAuth 2.0 avec GitHub et JWT pour la gestion des sessions ## 2. Préparation de l'Environnement ### 2.1 Installation des Dépendances ```bash # Installation des dépendances principales pnpm add @nestjs/config @nestjs/passport passport passport-github2 @nestjs/jwt pnpm add @nestjs/websockets @nestjs/platform-socket.io socket.io pnpm add drizzle-orm pg pnpm add @node-rs/argon2 jose pnpm add class-validator class-transformer pnpm add zod zod-validation-error pnpm add uuid # Installation des dépendances de développement pnpm add -D drizzle-kit pnpm add -D @types/passport-github2 @types/socket.io @types/pg @types/uuid ``` ### 2.2 Configuration de l'Environnement Créer un fichier `.env.example` à la racine du projet backend : ``` # Application PORT=3000 NODE_ENV=development API_PREFIX=api # Database DATABASE_URL=postgres://postgres:postgres@localhost:5432/groupmaker # Authentication GITHUB_CLIENT_ID=your_github_client_id GITHUB_CLIENT_SECRET=your_github_client_secret GITHUB_CALLBACK_URL=http://localhost:3000/api/auth/github/callback # JWT JWT_ACCESS_SECRET=your_access_token_secret JWT_REFRESH_SECRET=your_refresh_token_secret JWT_ACCESS_EXPIRATION=15m JWT_REFRESH_EXPIRATION=7d # CORS CORS_ORIGIN=http://localhost:3000 FRONTEND_URL=http://localhost:3000 ``` ## 3. Structure du Projet La structure du projet backend suivra l'organisation suivante : ``` backend/ ├── src/ │ ├── main.ts # Point d'entrée de l'application │ ├── app.module.ts # Module principal │ ├── config/ # Configuration de l'application │ │ ├── app.config.ts # Configuration générale │ │ ├── database.config.ts # Configuration de la base de données │ │ ├── auth.config.ts # Configuration de l'authentification │ │ └── env.validation.ts # Validation des variables d'environnement │ ├── common/ # Utilitaires partagés │ │ ├── decorators/ # Décorateurs personnalisés │ │ ├── filters/ # Filtres d'exception │ │ ├── guards/ # Guards d'authentification et d'autorisation │ │ ├── interceptors/ # Intercepteurs │ │ ├── pipes/ # Pipes de validation │ │ └── utils/ # Fonctions utilitaires │ ├── modules/ # Modules fonctionnels │ │ ├── auth/ # Module d'authentification │ │ ├── users/ # Module de gestion des utilisateurs │ │ ├── projects/ # Module de gestion des projets │ │ ├── persons/ # Module de gestion des personnes │ │ ├── groups/ # Module de gestion des groupes │ │ ├── tags/ # Module de gestion des tags │ │ └── websockets/ # Module de gestion des WebSockets │ └── database/ # Configuration de la base de données │ ├── migrations/ # Migrations de base de données │ ├── schema/ # Schéma de base de données (DrizzleORM) │ └── database.module.ts # Module de base de données ├── test/ # Tests │ ├── e2e/ # Tests end-to-end │ └── unit/ # Tests unitaires └── .env.example # Exemple de fichier d'environnement ``` ## 4. Configuration de Base ### 4.1 Point d'Entrée de l'Application Mettre à jour le fichier `src/main.ts` : ```typescript import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); // Configuration globale des pipes de validation app.useGlobalPipes( new ValidationPipe({ whitelist: true, transform: true, forbidNonWhitelisted: true, }), ); // Configuration CORS app.enableCors({ origin: configService.get('CORS_ORIGIN'), methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', credentials: true, }); // Préfixe global pour les routes API app.setGlobalPrefix(configService.get('API_PREFIX', 'api')); const port = configService.get('PORT', 3000); await app.listen(port); console.log(`Application is running on: http://localhost:${port}`); } bootstrap(); ``` ### 4.2 Module Principal Mettre à jour le fichier `src/app.module.ts` : ```typescript import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { APP_GUARD } from '@nestjs/core'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { DatabaseModule } from './database/database.module'; import { AuthModule } from './modules/auth/auth.module'; import { UsersModule } from './modules/users/users.module'; import { ProjectsModule } from './modules/projects/projects.module'; import { PersonsModule } from './modules/persons/persons.module'; import { GroupsModule } from './modules/groups/groups.module'; import { TagsModule } from './modules/tags/tags.module'; import { WebSocketsModule } from './modules/websockets/websockets.module'; import { JwtAuthGuard } from './modules/auth/guards/jwt-auth.guard'; import { validate } from './config/env.validation'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, validate, }), DatabaseModule, AuthModule, UsersModule, ProjectsModule, PersonsModule, GroupsModule, TagsModule, WebSocketsModule, ], controllers: [AppController], providers: [ AppService, { provide: APP_GUARD, useClass: JwtAuthGuard, }, ], }) export class AppModule {} ``` ### 4.3 Validation des Variables d'Environnement Créer le fichier `src/config/env.validation.ts` : ```typescript import { plainToClass } from 'class-transformer'; import { IsEnum, IsNumber, IsString, validateSync } from 'class-validator'; enum Environment { Development = 'development', Production = 'production', Test = 'test', } class EnvironmentVariables { @IsEnum(Environment) NODE_ENV: Environment; @IsNumber() PORT: number; @IsString() API_PREFIX: string; @IsString() DATABASE_URL: string; @IsString() GITHUB_CLIENT_ID: string; @IsString() GITHUB_CLIENT_SECRET: string; @IsString() GITHUB_CALLBACK_URL: string; @IsString() JWT_ACCESS_SECRET: string; @IsString() JWT_REFRESH_SECRET: string; @IsString() JWT_ACCESS_EXPIRATION: string; @IsString() JWT_REFRESH_EXPIRATION: string; @IsString() CORS_ORIGIN: string; @IsString() FRONTEND_URL: string; } export function validate(config: Record) { const validatedConfig = plainToClass( EnvironmentVariables, { ...config, PORT: config.PORT ? parseInt(config.PORT as string, 10) : 3000, }, { enableImplicitConversion: true }, ); const errors = validateSync(validatedConfig, { skipMissingProperties: false, }); if (errors.length > 0) { throw new Error(errors.toString()); } return validatedConfig; } ``` ## 5. Base de Données ### 5.1 Configuration de DrizzleORM Créer le fichier `drizzle.config.ts` à la racine du projet backend : ```typescript import type { Config } from 'drizzle-kit'; import * as dotenv from 'dotenv'; dotenv.config(); export default { schema: './src/database/schema/*.ts', out: './src/database/migrations', driver: 'pg', dbCredentials: { connectionString: process.env.DATABASE_URL || 'postgres://postgres:postgres@localhost:5432/groupmaker', }, verbose: true, strict: true, } satisfies Config; ``` ### 5.2 Module de Base de Données Créer le fichier `src/database/database.module.ts` : ```typescript import { Module, Global } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { Pool } from 'pg'; import { drizzle } from 'drizzle-orm/node-postgres'; import * as schema from './schema'; export const DATABASE_POOL = 'DATABASE_POOL'; export const DRIZZLE = 'DRIZZLE'; @Global() @Module({ imports: [ConfigModule], providers: [ { provide: DATABASE_POOL, inject: [ConfigService], useFactory: async (configService: ConfigService) => { const pool = new Pool({ connectionString: configService.get('DATABASE_URL'), }); // Test the connection const client = await pool.connect(); try { await client.query('SELECT NOW()'); console.log('Database connection established successfully'); } finally { client.release(); } return pool; }, }, { provide: DRIZZLE, inject: [DATABASE_POOL], useFactory: (pool: Pool) => { return drizzle(pool, { schema }); }, }, ], exports: [DATABASE_POOL, DRIZZLE], }) export class DatabaseModule {} ``` ### 5.3 Script de Migration Créer le fichier `src/database/migrate.ts` : ```typescript import { drizzle } from 'drizzle-orm/node-postgres'; import { migrate } from 'drizzle-orm/node-postgres/migrator'; import { Pool } from 'pg'; import * as dotenv from 'dotenv'; dotenv.config(); const main = async () => { const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); const db = drizzle(pool); console.log('Running migrations...'); await migrate(db, { migrationsFolder: './src/database/migrations' }); console.log('Migrations completed successfully'); await pool.end(); }; main().catch((err) => { console.error('Migration failed'); console.error(err); process.exit(1); }); ``` ### 5.4 Schéma de Base de Données Créer les fichiers de schéma dans le dossier `src/database/schema/` selon le plan détaillé dans le document DATABASE_SCHEMA_PLAN.md. ### 5.5 Scripts pour les Migrations Ajouter les scripts suivants au `package.json` du backend : ```json { "scripts": { "db:generate": "drizzle-kit generate:pg", "db:migrate": "ts-node src/database/migrate.ts", "db:studio": "drizzle-kit studio" } } ``` ## 6. Authentification ### 6.1 Module d'Authentification Créer le fichier `src/modules/auth/auth.module.ts` selon le plan détaillé dans le document AUTH_IMPLEMENTATION_PLAN.md. ### 6.2 Stratégies d'Authentification Implémenter les stratégies d'authentification (GitHub, JWT, JWT Refresh) selon le plan détaillé dans le document AUTH_IMPLEMENTATION_PLAN.md. ### 6.3 Service d'Authentification Implémenter le service d'authentification selon le plan détaillé dans le document AUTH_IMPLEMENTATION_PLAN.md. ### 6.4 Contrôleur d'Authentification Implémenter le contrôleur d'authentification selon le plan détaillé dans le document AUTH_IMPLEMENTATION_PLAN.md. ### 6.5 Guards et Décorateurs Implémenter les guards et décorateurs d'authentification selon le plan détaillé dans le document AUTH_IMPLEMENTATION_PLAN.md. ## 7. Modules Fonctionnels ### 7.1 Module Utilisateurs #### 7.1.1 Service Utilisateurs ```typescript // src/modules/users/services/users.service.ts import { Injectable, NotFoundException } from '@nestjs/common'; import { DRIZZLE } from '../../../database/database.module'; import { Inject } from '@nestjs/common'; import { eq } from 'drizzle-orm'; import * as schema from '../../../database/schema'; import { CreateUserDto } from '../dto/create-user.dto'; import { UpdateUserDto } from '../dto/update-user.dto'; @Injectable() export class UsersService { constructor(@Inject(DRIZZLE) private readonly db: any) {} async create(createUserDto: CreateUserDto) { const [user] = await this.db .insert(schema.users) .values(createUserDto) .returning(); return user; } async findAll() { return this.db.select().from(schema.users); } async findById(id: string) { const [user] = await this.db .select() .from(schema.users) .where(eq(schema.users.id, id)); if (!user) { throw new NotFoundException(`User with ID ${id} not found`); } return user; } async findByGithubId(githubId: string) { const [user] = await this.db .select() .from(schema.users) .where(eq(schema.users.githubId, githubId)); return user; } async update(id: string, updateUserDto: UpdateUserDto) { const [user] = await this.db .update(schema.users) .set({ ...updateUserDto, updatedAt: new Date(), }) .where(eq(schema.users.id, id)) .returning(); if (!user) { throw new NotFoundException(`User with ID ${id} not found`); } return user; } async remove(id: string) { const [user] = await this.db .delete(schema.users) .where(eq(schema.users.id, id)) .returning(); if (!user) { throw new NotFoundException(`User with ID ${id} not found`); } return user; } async updateGdprConsent(id: string) { return this.update(id, { gdprTimestamp: new Date() }); } async exportUserData(id: string) { const user = await this.findById(id); const projects = await this.db .select() .from(schema.projects) .where(eq(schema.projects.ownerId, id)); return { user, projects, }; } } ``` #### 7.1.2 Contrôleur Utilisateurs ```typescript // src/modules/users/controllers/users.controller.ts import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards, } from '@nestjs/common'; import { UsersService } from '../services/users.service'; import { CreateUserDto } from '../dto/create-user.dto'; import { UpdateUserDto } from '../dto/update-user.dto'; import { GetUser } from '../../auth/decorators/get-user.decorator'; import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard'; import { RolesGuard } from '../../auth/guards/roles.guard'; import { Roles } from '../../auth/decorators/roles.decorator'; import { Role } from '../../auth/enums/role.enum'; @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} @Post() @UseGuards(JwtAuthGuard, RolesGuard) @Roles(Role.ADMIN) create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } @Get() @UseGuards(JwtAuthGuard, RolesGuard) @Roles(Role.ADMIN) findAll() { return this.usersService.findAll(); } @Get('profile') @UseGuards(JwtAuthGuard) getProfile(@GetUser() user) { return user; } @Get(':id') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(Role.ADMIN) findOne(@Param('id') id: string) { return this.usersService.findById(id); } @Patch(':id') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(Role.ADMIN) update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.usersService.update(id, updateUserDto); } @Delete(':id') @UseGuards(JwtAuthGuard, RolesGuard) @Roles(Role.ADMIN) remove(@Param('id') id: string) { return this.usersService.remove(id); } @Post('gdpr-consent') @UseGuards(JwtAuthGuard) updateGdprConsent(@GetUser('id') userId: string) { return this.usersService.updateGdprConsent(userId); } @Get('export-data') @UseGuards(JwtAuthGuard) exportUserData(@GetUser('id') userId: string) { return this.usersService.exportUserData(userId); } } ``` ### 7.2 Module Projets Implémenter le module de gestion des projets avec les opérations CRUD et les relations avec les utilisateurs, les personnes et les groupes. ### 7.3 Module Personnes Implémenter le module de gestion des personnes avec les opérations CRUD et les attributs spécifiés (niveau technique, genre, âge, etc.). ### 7.4 Module Groupes Implémenter le module de gestion des groupes avec les opérations CRUD et les algorithmes de création automatique de groupes équilibrés. ### 7.5 Module Tags Implémenter le module de gestion des tags avec les opérations CRUD et la gestion des types de tags (PROJECT, PERSON). ## 8. Communication en Temps Réel ### 8.1 Module WebSockets Implémenter le module WebSockets selon le plan détaillé dans le document WEBSOCKET_IMPLEMENTATION_PLAN.md. ### 8.2 Gateways WebSocket Implémenter les gateways WebSocket (Projets, Groupes, Notifications) selon le plan détaillé dans le document WEBSOCKET_IMPLEMENTATION_PLAN.md. ### 8.3 Service WebSocket Implémenter le service WebSocket selon le plan détaillé dans le document WEBSOCKET_IMPLEMENTATION_PLAN.md. ## 9. Sécurité et Conformité RGPD ### 9.1 Sécurité #### 9.1.1 Protection contre les Attaques Courantes - Implémenter la protection CSRF pour les opérations sensibles - Configurer les en-têtes de sécurité (Content-Security-Policy, X-XSS-Protection, etc.) - Utiliser des paramètres préparés avec DrizzleORM pour prévenir les injections SQL - Mettre en place le rate limiting pour prévenir les attaques par force brute #### 9.1.2 Gestion des Tokens - Implémenter la révocation des tokens JWT - Configurer la rotation des clés de signature - Mettre en place la validation complète des tokens (signature, expiration, émetteur) ### 9.2 Conformité RGPD #### 9.2.1 Gestion du Consentement - Implémenter l'enregistrement du timestamp d'acceptation RGPD - Mettre en place le renouvellement du consentement tous les 13 mois #### 9.2.2 Droits des Utilisateurs - Implémenter l'export des données personnelles - Mettre en place la suppression de compte avec option de conservation ou suppression des projets ## 10. Tests et Documentation ### 10.1 Tests #### 10.1.1 Tests Unitaires Écrire des tests unitaires pour les services et les contrôleurs en utilisant Jest. #### 10.1.2 Tests E2E Développer des tests end-to-end pour les API en utilisant Supertest. ### 10.2 Documentation #### 10.2.1 Documentation API Générer la documentation API avec Swagger en utilisant les décorateurs NestJS. #### 10.2.2 Documentation Technique Documenter l'architecture, les modèles de données et les flux d'interaction. ## 11. Déploiement ### 11.1 Conteneurisation Créer un Dockerfile pour le backend : ```dockerfile FROM node:20-alpine AS builder WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN npm install -g pnpm && pnpm install COPY . . RUN pnpm build FROM node:20-alpine WORKDIR /app COPY --from=builder /app/package.json /app/pnpm-lock.yaml ./ COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules EXPOSE 3000 CMD ["node", "dist/main"] ``` ### 11.2 CI/CD Configurer un workflow CI/CD avec GitHub Actions pour l'intégration et le déploiement continus. ## 12. Calendrier d'Implémentation 1. **Semaine 1: Configuration et Base de Données** - Configuration de l'environnement - Mise en place de la base de données avec DrizzleORM - Définition du schéma et création des migrations 2. **Semaine 2: Authentification et Utilisateurs** - Implémentation de l'authentification GitHub OAuth - Développement du module utilisateurs - Mise en place de la gestion des JWT 3. **Semaine 3: Modules Principaux** - Développement des modules projets, personnes et groupes - Implémentation des opérations CRUD - Mise en place des relations entre entités 4. **Semaine 4: Fonctionnalités Avancées** - Implémentation des WebSockets pour la communication en temps réel - Développement des algorithmes de création de groupes - Mise en place des fonctionnalités de sécurité et de conformité RGPD 5. **Semaine 5: Tests et Finalisation** - Écriture des tests unitaires et e2e - Documentation de l'API - Optimisation des performances et correction des bugs