Explorar el Código

(feat) ajout des entités et de la structure pour nest Js

Brin AMONKONAN hace 1 año
padre
commit
a7463b914f
Se han modificado 36 ficheros con 1288 adiciones y 59 borrados
  1. 3 0
      .env
  2. 27 19
      docker-compose.yml
  3. 4 1
      gitignore
  4. 13 0
      monhopital-firebase-adminsdk.json
  5. 3 2
      node_app/eslint.config.mjs
  6. 14 0
      node_app/ormconfig.json
  7. 637 31
      node_app/package-lock.json
  8. 14 2
      node_app/package.json
  9. 0 1
      node_app/src/app.controller.ts
  10. 25 3
      node_app/src/app.module.ts
  11. 45 0
      node_app/src/auth.config.ts
  12. 18 0
      node_app/src/auth/auth.controller.spec.ts
  13. 14 0
      node_app/src/auth/auth.controller.ts
  14. 19 0
      node_app/src/auth/auth.module.ts
  15. 18 0
      node_app/src/auth/auth.service.spec.ts
  16. 13 0
      node_app/src/auth/auth.service.ts
  17. 8 0
      node_app/src/auth/decorators/current-user.decorator.ts
  18. 25 0
      node_app/src/auth/firebase.strategy.ts
  19. 16 0
      node_app/src/auth/guards/firebase-auth.guard.ts
  20. 4 0
      node_app/src/common/common.module.ts
  21. 15 0
      node_app/src/companies/compagny.entity.ts
  22. 12 0
      node_app/src/companies/companies.module.ts
  23. 19 0
      node_app/src/drivers/driver.entity.ts
  24. 12 0
      node_app/src/drivers/drivers.module.ts
  25. 13 0
      node_app/src/main.ts
  26. 30 0
      node_app/src/reservations/place.entity.ts
  27. 34 0
      node_app/src/reservations/reservation.entity.ts
  28. 12 0
      node_app/src/reservations/reservations.module.ts
  29. 18 0
      node_app/src/reservations/reservations.service.spec.ts
  30. 55 0
      node_app/src/reservations/reservations.service.ts
  31. 39 0
      node_app/src/trajets/trajet.entity.ts
  32. 12 0
      node_app/src/trajets/trajets.module.ts
  33. 28 0
      node_app/src/users/user.entity.ts
  34. 13 0
      node_app/src/users/users.module.ts
  35. 44 0
      node_app/src/vehicules/vehicule.entity.ts
  36. 12 0
      node_app/src/vehicules/vehicules.module.ts

+ 3 - 0
.env

@@ -0,0 +1,3 @@
+FIREBASE_PROJECT_ID=monhopital
+FIREBASE_CLIENT_EMAIL=firebase-adminsdk-8gixa@monhopital.iam.gserviceaccount.com
+FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCTmdIetvaCr9b+\n8yfmeFeL8iCaHeSVMlDicms171htwB6RtTi+66hLbEUQoPAlA7MXVDatFpwDS/pw\n/KAdZFxTKjDIO4/CmWxZn+eJZ/fD41EghWDyjVyXb+DwLmKVGAJLtW0iGxU2yyB5\nXbc5aLCxFFBcXv2nASS0RbYuL9Nk4wjTMq4MZZZ4n3oJ/Ru2Sp4ftg0NRe8lMiuy\nL+Xzzqivqha5b/AJh5JBQXTmilatORk2ZRzKtRqehtObEjWbkilEx5FS1rpSlgHS\nQKijWXzAs+IxufieOX/1Usa3KxlSbA2UqdxfYQnn2NfKg0GzXqruzOkJju5HsIAI\nDY+BSnXJAgMBAAECggEAQtw/8Ufh/KsYkd6lqWHEDpG8sPNvkyH6v8kixYjJHtYT\nQt+7d8iaMKg31OOCRNIbMysjpV6Dh37IUJwvD4FhzQ5kkJ9ibL1A9oxXvseI1YRI\nQJoKo3Tjh3nXhBUO9QiuKYtihzuLbYmwCSopkGja+SwBhwZEkn0TGlIlx2BEuwLo\nffz0nl8GL9jhY2v2JUm1zmhMIFRqXuAM/cWSYmtsgtQBlXwK9I2Drzt111ClryrP\nELC8cz7ZSibSZQi3sECAqKfenT6Pymicb6qMsUEGze4IkJyhAC55iF2eVJPc0d+J\nCQKzqrKyHf58aJ2VwOAR5bUzE1CxeqAIwCjfm08QHQKBgQC1pJrEGwSumzZvWC6r\n9VfQLqigfq1NfEJ+dm0Z4v1qK4hNKk1kR9j3MiBtgAE5N6yqK8T5oN4gZnWa3VFf\nO8F9GI/T0QQ9L334rTfQL79WtTpJVhtH3zmws1503kjMCP4IGv7xWXQliAdJaMBP\nHGbZZ1K3m4r8vgygkHcn7F4A2wKBgQDQBb/lFcw+aNKbMVDvzIoXQ7kgbNKbyPE6\n49U3FLmxzrpLp5gGqMy9+h8UVCwhR+jodkEzw3Gu+NlP4y1spyDRfAEtpMDy3w10\nzeEC6ha4aJUKcnUABZF6Fi5iDqyrjx7IW3H7LgVFkfmiQfnf99FgtC3/28rDn9ui\n9uEcPQVDKwKBgQCPG0U3tZWlvvFPHel/Xwc1JF2EPOlqv7hfjAv+tiAzcmKrcOWS\nWSyt7JcxzgSowJ1PYLaKeVwnqLGFNlKythCF70D5f5ZYYj9cGZR8d/HGbXejaayK\nnmsENPz5FFvELF1/o00yduiT3SzogBfq/BRnugioUWpaH50xL0BBeu7AuwKBgQCO\nVYDJlLKdeUexXHsOuRs7c+E1qIAqi8FTFBUNjSbJ3LNnlJLW66S70Gp3lGhllTht\n5owSiQY+PJMksEKid3BjJcAApRxIkgo5A62UOuu03gosjcg0bZruuEKgYX4QHOtp\nF/jTbte4lHsEZLQ+ZOhkjKR0zsTcOYMk7Ft24OG65QKBgQCb0Jw4ZXfy6L00Hhui\nIR1VZDL7tvX2OArhcuJLn+btGHKD/ZythWZYsyWdktXWWWO5Q28T05wQlb41QINf\nwZQ0xhUS1ESkCtcTS+GFSXbWNj2GsRiB4J84FmTLj/RX5uZbJGpZAnMcLpmzGHFw\nhxJoNoNm0XlG4hrjZzIsk0fFSg==\n-----END PRIVATE KEY-----\n"

+ 27 - 19
docker-compose.yml

@@ -54,6 +54,8 @@ services:
     image: node:latest
     container_name: node_server
     working_dir: /usr/src/app
+    depends_on:
+      - postgresql
     environment:
       - NODE_ENV=development
     ports:
@@ -62,6 +64,10 @@ services:
       - ./node_app:/usr/src/app
       - /app/node_modules
     command: ["npm", "run", "start"]
+    networks:
+      - gogs-network
+      - sonarnet
+
 
   # Serveur PHP
   app:
@@ -80,6 +86,8 @@ services:
       POSTGRES_USER: sonar
       POSTGRES_PASSWORD: sonar_pass
       POSTGRES_DB: sonarqube
+    ports:
+      - "5432:5432"
     volumes:
       - postgresql-data:/var/lib/postgresql/data
     networks:
@@ -168,25 +176,25 @@ services:
       - jenkins_home:/var/jenkins_home
 
   # Serveur de qualité de code SonarQube
-  sonarqube:
-    image: sonarqube:lts-community
-    container_name: sonarqube_server
-    restart: always
-    depends_on:
-      - postgresql
-    ports:
-      - "9000:9000"
-    environment:
-      SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"
-      SONAR_JDBC_URL: jdbc:postgresql://postgresql:5432/sonarqube
-      SONAR_JDBC_USERNAME: user
-      SONAR_JDBC_PASSWORD: user
-    volumes:
-      - sonarqube_data:/opt/sonarqube/data
-      - sonarqube_extensions:/opt/sonarqube/extensions
-      - sonarqube_logs:/opt/sonarqube/logs
-    networks:
-      - sonarnet
+  #sonarqube:
+    #image: sonarqube:lts-community
+    #container_name: sonarqube_server
+    #restart: always
+    #depends_on:
+    #  - postgresql
+    #ports:
+    #  - "9000:9000"
+    #environment:
+      #SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"
+      #SONAR_JDBC_URL: jdbc:postgresql://postgresql:5432/sonarqube
+      #SONAR_JDBC_USERNAME: user
+      #SONAR_JDBC_PASSWORD: user
+    #volumes:
+    #  - sonarqube_data:/opt/sonarqube/data
+    #  - sonarqube_extensions:/opt/sonarqube/extensions
+    #  - sonarqube_logs:/opt/sonarqube/logs
+    #networks:
+    #  - sonarnet
 
 networks:
   monitoring:

+ 4 - 1
gitignore

@@ -1,4 +1,7 @@
 /node_module
 /dist
 /node_app/node_module
-/node_app/dist
+/node_app/dist
+monhopital-firebase-adminsdk.json
+.env
+.env.prod

+ 13 - 0
monhopital-firebase-adminsdk.json

@@ -0,0 +1,13 @@
+{
+  "type": "service_account",
+  "project_id": "monhopital",
+  "private_key_id": "1002158efa1ed0f290ee1100ee9b6f73887bbf5e",
+  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCTmdIetvaCr9b+\n8yfmeFeL8iCaHeSVMlDicms171htwB6RtTi+66hLbEUQoPAlA7MXVDatFpwDS/pw\n/KAdZFxTKjDIO4/CmWxZn+eJZ/fD41EghWDyjVyXb+DwLmKVGAJLtW0iGxU2yyB5\nXbc5aLCxFFBcXv2nASS0RbYuL9Nk4wjTMq4MZZZ4n3oJ/Ru2Sp4ftg0NRe8lMiuy\nL+Xzzqivqha5b/AJh5JBQXTmilatORk2ZRzKtRqehtObEjWbkilEx5FS1rpSlgHS\nQKijWXzAs+IxufieOX/1Usa3KxlSbA2UqdxfYQnn2NfKg0GzXqruzOkJju5HsIAI\nDY+BSnXJAgMBAAECggEAQtw/8Ufh/KsYkd6lqWHEDpG8sPNvkyH6v8kixYjJHtYT\nQt+7d8iaMKg31OOCRNIbMysjpV6Dh37IUJwvD4FhzQ5kkJ9ibL1A9oxXvseI1YRI\nQJoKo3Tjh3nXhBUO9QiuKYtihzuLbYmwCSopkGja+SwBhwZEkn0TGlIlx2BEuwLo\nffz0nl8GL9jhY2v2JUm1zmhMIFRqXuAM/cWSYmtsgtQBlXwK9I2Drzt111ClryrP\nELC8cz7ZSibSZQi3sECAqKfenT6Pymicb6qMsUEGze4IkJyhAC55iF2eVJPc0d+J\nCQKzqrKyHf58aJ2VwOAR5bUzE1CxeqAIwCjfm08QHQKBgQC1pJrEGwSumzZvWC6r\n9VfQLqigfq1NfEJ+dm0Z4v1qK4hNKk1kR9j3MiBtgAE5N6yqK8T5oN4gZnWa3VFf\nO8F9GI/T0QQ9L334rTfQL79WtTpJVhtH3zmws1503kjMCP4IGv7xWXQliAdJaMBP\nHGbZZ1K3m4r8vgygkHcn7F4A2wKBgQDQBb/lFcw+aNKbMVDvzIoXQ7kgbNKbyPE6\n49U3FLmxzrpLp5gGqMy9+h8UVCwhR+jodkEzw3Gu+NlP4y1spyDRfAEtpMDy3w10\nzeEC6ha4aJUKcnUABZF6Fi5iDqyrjx7IW3H7LgVFkfmiQfnf99FgtC3/28rDn9ui\n9uEcPQVDKwKBgQCPG0U3tZWlvvFPHel/Xwc1JF2EPOlqv7hfjAv+tiAzcmKrcOWS\nWSyt7JcxzgSowJ1PYLaKeVwnqLGFNlKythCF70D5f5ZYYj9cGZR8d/HGbXejaayK\nnmsENPz5FFvELF1/o00yduiT3SzogBfq/BRnugioUWpaH50xL0BBeu7AuwKBgQCO\nVYDJlLKdeUexXHsOuRs7c+E1qIAqi8FTFBUNjSbJ3LNnlJLW66S70Gp3lGhllTht\n5owSiQY+PJMksEKid3BjJcAApRxIkgo5A62UOuu03gosjcg0bZruuEKgYX4QHOtp\nF/jTbte4lHsEZLQ+ZOhkjKR0zsTcOYMk7Ft24OG65QKBgQCb0Jw4ZXfy6L00Hhui\nIR1VZDL7tvX2OArhcuJLn+btGHKD/ZythWZYsyWdktXWWWO5Q28T05wQlb41QINf\nwZQ0xhUS1ESkCtcTS+GFSXbWNj2GsRiB4J84FmTLj/RX5uZbJGpZAnMcLpmzGHFw\nhxJoNoNm0XlG4hrjZzIsk0fFSg==\n-----END PRIVATE KEY-----\n",
+  "client_email": "firebase-adminsdk-8gixa@monhopital.iam.gserviceaccount.com",
+  "client_id": "117273044218610720790",
+  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+  "token_uri": "https://oauth2.googleapis.com/token",
+  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-8gixa%40monhopital.iam.gserviceaccount.com",
+  "universe_domain": "googleapis.com"
+}

+ 3 - 2
node_app/eslint.config.mjs

@@ -29,7 +29,8 @@ export default tseslint.config(
     rules: {
       '@typescript-eslint/no-explicit-any': 'off',
       '@typescript-eslint/no-floating-promises': 'warn',
-      '@typescript-eslint/no-unsafe-argument': 'warn'
+      '@typescript-eslint/no-unsafe-argument': 'warn',
+      '@typescript-eslint/no-unsafe-member-access': 'warn',
     },
   },
-);
+);

+ 14 - 0
node_app/ormconfig.json

@@ -0,0 +1,14 @@
+{
+  "type": "postgres",
+  "host": "localhost",
+  "port": 5432,
+  "username": "your_db_username",
+  "password": "your_db_password",
+  "database": "your_db_name",
+  "entities": ["dist/**/*.entity{.ts,.js}"],
+  "migrations": ["dist/migrations/*{.ts,.js}"],
+  "cli": {
+    "migrationsDir": "src/migrations"
+  },
+  "synchronize": false
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 637 - 31
node_app/package-lock.json


+ 14 - 2
node_app/package.json

@@ -21,10 +21,22 @@
   },
   "dependencies": {
     "@nestjs/common": "^11.0.6",
+    "@nestjs/config": "^4.0.0",
     "@nestjs/core": "^11.0.6",
+    "@nestjs/passport": "^11.0.5",
     "@nestjs/platform-express": "^11.0.6",
+    "@nestjs/swagger": "^11.0.3",
+    "@nestjs/typeorm": "^11.0.0",
+    "firebase-admin": "^13.0.2",
+    "jsonwebtoken": "^9.0.2",
+    "passport": "^0.7.0",
+    "passport-firebase-jwt": "^1.2.1",
+    "passport-jwt": "^4.0.1",
+    "pg": "^8.13.1",
     "reflect-metadata": "^0.2.2",
-    "rxjs": "^7.8.1"
+    "rxjs": "^7.8.1",
+    "swagger-ui-express": "^5.0.1",
+    "typeorm": "^0.3.20"
   },
   "devDependencies": {
     "@eslint/eslintrc": "^3.2.0",
@@ -36,7 +48,7 @@
     "@swc/core": "^1.10.7",
     "@types/express": "^5.0.0",
     "@types/jest": "^29.5.14",
-    "@types/node": "^22.10.7",
+    "@types/node": "^22.12.0",
     "@types/supertest": "^6.0.2",
     "eslint": "^9.18.0",
     "eslint-config-prettier": "^10.0.1",

+ 0 - 1
node_app/src/app.controller.ts

@@ -1,6 +1,5 @@
 import { Controller, Get } from '@nestjs/common';
 import { AppService } from './app.service';
-
 @Controller()
 export class AppController {
   constructor(private readonly appService: AppService) {}

+ 25 - 3
node_app/src/app.module.ts

@@ -1,10 +1,32 @@
 import { Module } from '@nestjs/common';
 import { AppController } from './app.controller';
 import { AppService } from './app.service';
+import { AuthModule } from './auth/auth.module';
+import { AuthConfig } from './auth.config';
+import { CompaniesModule } from './companies/companies.module';
+import { UsersModule } from './users/users.module';
+import { DriversModule } from './drivers/drivers.module';
+import { VehiculesModule } from './vehicules/vehicules.module';
+import { TrajetsModule } from './trajets/trajets.module';
+import { ReservationsModule } from './reservations/reservations.module';
+import { CommonModule } from './common/common.module';
 
 @Module({
-  imports: [],
+  imports: [
+    AuthModule,
+    CompaniesModule,
+    UsersModule,
+    DriversModule,
+    VehiculesModule,
+    TrajetsModule,
+    ReservationsModule,
+    CommonModule,
+  ],
   controllers: [AppController],
-  providers: [AppService],
+  providers: [AppService, AuthConfig],
 })
-export class AppModule {}
+export class AppModule {
+  constructor(public authConfig: AuthConfig) {
+    this.authConfig.configurePassport();
+  }
+}

+ 45 - 0
node_app/src/auth.config.ts

@@ -0,0 +1,45 @@
+import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';
+import { PassportStatic } from 'passport';
+import { Injectable } from '@nestjs/common';
+import * as admin from 'firebase-admin';
+
+@Injectable()
+export class AuthConfig {
+  constructor(private readonly passport: PassportStatic) {
+    this.initializeFirebase();
+    this.configurePassport();
+  }
+
+  private initializeFirebase() {
+    const serviceAccount = require('path/to/your/serviceAccountKey.json');
+    admin.initializeApp({
+      credential: admin.credential.cert(serviceAccount),
+    });
+  }
+
+  public configurePassport() {
+    // remettre en private
+    this.passport.use(
+      new JwtStrategy(
+        {
+          jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
+          secretOrKeyProvider: (request, rawJwtToken, done) => {
+            admin
+              .auth()
+              .verifyIdToken(rawJwtToken)
+              .then((decodedToken) => {
+                done(null, decodedToken);
+              })
+              .catch((error) => {
+                done(error, false);
+              });
+          },
+        },
+        (jwtPayload, done) => {
+          // Vérifiez le payload JWT et retournez l'utilisateur
+          return done(null, jwtPayload);
+        },
+      ),
+    );
+  }
+}

+ 18 - 0
node_app/src/auth/auth.controller.spec.ts

@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AuthController } from './auth.controller';
+
+describe('AuthController', () => {
+  let controller: AuthController;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      controllers: [AuthController],
+    }).compile();
+
+    controller = module.get<AuthController>(AuthController);
+  });
+
+  it('should be defined', () => {
+    expect(controller).toBeDefined();
+  });
+});

+ 14 - 0
node_app/src/auth/auth.controller.ts

@@ -0,0 +1,14 @@
+import { Controller, Post, UseGuards } from '@nestjs/common';
+import { FirebaseAuthGuard } from './guards/firebase-auth.guard';
+import { CurrentUser } from './decorators/current-user.decorator';
+import { AuthGuard } from '@nestjs/passport';
+
+@Controller('auth')
+export class AuthController {
+  @Post('login')
+  @UseGuards(FirebaseAuthGuard) // protéger ma route
+  @UseGuards(AuthGuard('firebase-jwt'))
+  login(@CurrentUser() user: unknown) {
+    return { user };
+  }
+}

+ 19 - 0
node_app/src/auth/auth.module.ts

@@ -0,0 +1,19 @@
+import { Module } from '@nestjs/common';
+import { AuthController } from './auth.controller';
+import { AuthService } from './auth.service';
+import { JwtModule } from '@nestjs/jwt';
+import { UsersModule } from '../users/users.module';
+
+@Module({
+  imports: [
+    JwtModule.register({
+      secret: 'your-secret-key',
+      signOptions: { expiresIn: '60m' },
+    }),
+    UsersModule,
+  ],
+  controllers: [AuthController],
+  providers: [AuthService],
+  exports: [AuthService],
+})
+export class AuthModule {}

+ 18 - 0
node_app/src/auth/auth.service.spec.ts

@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+  let service: AuthService;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      providers: [AuthService],
+    }).compile();
+
+    service = module.get<AuthService>(AuthService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+});

+ 13 - 0
node_app/src/auth/auth.service.ts

@@ -0,0 +1,13 @@
+import { Injectable } from '@nestjs/common';
+import * as admin from 'firebase-admin';
+
+@Injectable()
+export class AuthService {
+  async generateCustomToken(uid: string): Promise<string> {
+    return admin.auth().createCustomToken(uid);
+  }
+
+  async verifyToken(token: string): Promise<admin.auth.DecodedIdToken> {
+    return admin.auth().verifyIdToken(token);
+  }
+}

+ 8 - 0
node_app/src/auth/decorators/current-user.decorator.ts

@@ -0,0 +1,8 @@
+import { createParamDecorator, ExecutionContext } from '@nestjs/common';
+
+export const CurrentUser = createParamDecorator(
+  (data: unknown, ctx: ExecutionContext) => {
+    const request = ctx.switchToHttp().getRequest();
+    return request.user;
+  },
+);

+ 25 - 0
node_app/src/auth/firebase.strategy.ts

@@ -0,0 +1,25 @@
+import { Injectable } from '@nestjs/common';
+import { PassportStrategy } from '@nestjs/passport';
+import { Strategy, ExtractJwt } from 'passport-firebase-jwt';
+import * as admin from 'firebase-admin';
+
+@Injectable()
+export class FirebaseStrategy extends PassportStrategy(Strategy, 'firebase') {
+  constructor() {
+    super({
+      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
+    });
+    admin.initializeApp({
+      credential: admin.credential.cert({
+        projectId: process.env.FIREBASE_PROJECT_ID,
+        clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
+        privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
+      }),
+    });
+  }
+
+  async validate(token: string) {
+    const decodedToken = await admin.auth().verifyIdToken(token, true);
+    return decodedToken;
+  }
+}

+ 16 - 0
node_app/src/auth/guards/firebase-auth.guard.ts

@@ -0,0 +1,16 @@
+import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
+import { Observable } from 'rxjs';
+import { Reflector } from '@nestjs/core';
+
+@Injectable()
+export class FirebaseAuthGuard implements CanActivate {
+  constructor(private reflector: Reflector) {}
+
+  canActivate(
+    context: ExecutionContext,
+  ): boolean | Promise<boolean> | Observable<boolean> {
+    const request = context.switchToHttp().getRequest();
+    // L'utilisateur est attaché par FirebaseStrategy
+    return !!request.user;
+  }
+}

+ 4 - 0
node_app/src/common/common.module.ts

@@ -0,0 +1,4 @@
+import { Module } from '@nestjs/common';
+
+@Module({})
+export class CommonModule {}

+ 15 - 0
node_app/src/companies/compagny.entity.ts

@@ -0,0 +1,15 @@
+import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
+
+@Entity()
+export class Compagny {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column({ unique: true })
+  name: string;
+
+  @Column()
+  address: string;
+
+  //un manager pour gérer la compagnie
+}

+ 12 - 0
node_app/src/companies/companies.module.ts

@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { CompaniesService } from './companies.service';
+import { CompaniesController } from './companies.controller';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { Company } from './company.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([Company])],
+  providers: [CompaniesService],
+  controllers: [CompaniesController],
+})
+export class CompaniesModule {}

+ 19 - 0
node_app/src/drivers/driver.entity.ts

@@ -0,0 +1,19 @@
+import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
+
+@Entity()
+export class Driver {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column({ unique: true })
+  name: string;
+
+  @Column()
+  address: string;
+
+  @Column()
+  telephone: string;
+
+  // est lié à une companie ou est sa propre compagne, à un gérant (manager)
+  // est utilisateur
+}

+ 12 - 0
node_app/src/drivers/drivers.module.ts

@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { DriversService } from './drivers.service';
+import { DriversController } from './drivers.controller';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { Driver } from './driver.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([Driver])],
+  providers: [DriversService],
+  controllers: [DriversController],
+})
+export class DriversModule {}

+ 13 - 0
node_app/src/main.ts

@@ -1,8 +1,21 @@
 import { NestFactory } from '@nestjs/core';
 import { AppModule } from './app.module';
+import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
 
 async function bootstrap() {
   const app = await NestFactory.create(AppModule);
+
+  // Configuration Swagger
+  const config = new DocumentBuilder()
+    .setTitle('API NestJS avec Swagger')
+    .setDescription('Documentation de l’API NestJS avec Swagger')
+    .setVersion('1.0')
+    .addBearerAuth() // Pour l'authentification avec JWT si nécessaire
+    .build();
+
+  const document = SwaggerModule.createDocument(app, config);
+  SwaggerModule.setup('api', app, document);
+
   await app.listen(process.env.PORT ?? 3000);
 }
 

+ 30 - 0
node_app/src/reservations/place.entity.ts

@@ -0,0 +1,30 @@
+import { Vehicule } from 'src/vehicules/vehicule.entity';
+import {
+  Column,
+  Entity,
+  JoinColumn,
+  ManyToOne,
+  OneToMany,
+  PrimaryGeneratedColumn,
+} from 'typeorm';
+import { Reservation } from './reservation.entity';
+
+@Entity()
+export class Place {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column({ type: 'integer' })
+  numbreSiege: number; // Numéro du siège (exemple : 1, 2, 3...)
+
+  // Relation ManyToOne avec Vehicle (une place appartient à une voiture)
+  @ManyToOne(() => Vehicule, (vehicule) => vehicule.places, { eager: true })
+  @JoinColumn({ name: 'vehiculeId' })
+  vehicule: Vehicule;
+
+  // Relation OneToMany avec Reservation (une place peut avoir plusieurs réservations)
+  @OneToMany(() => Reservation, (reservation) => reservation.place, {
+    cascade: true,
+  })
+  reservations: Reservation[];
+}

+ 34 - 0
node_app/src/reservations/reservation.entity.ts

@@ -0,0 +1,34 @@
+import {
+  Column,
+  Entity,
+  JoinColumn,
+  ManyToOne,
+  PrimaryGeneratedColumn,
+} from 'typeorm';
+import { Place } from './place.entity';
+import { User } from 'src/users/user.entity';
+import { Trajet } from 'src/trajets/trajet.entity';
+
+@Entity()
+export class Reservation {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column({ type: 'datetime' })
+  dateAt: Date;
+
+  // Relation ManyToOne avec Place (une réservation est associée à une place)
+  @ManyToOne(() => Place, (place) => place.reservations, { eager: true })
+  @JoinColumn({ name: 'placeId' })
+  place: Place;
+
+  // Relation ManyToOne avec User (une réservation est faite par un utilisateur)
+  @ManyToOne(() => User, (user) => user.reservations, { eager: true })
+  @JoinColumn({ name: 'userId' })
+  user: User;
+
+  // Relation ManyToOne avec Trip (une réservation est associée à un trajet)
+  @ManyToOne(() => Trajet, (trajet) => trajet.reservations, { eager: true })
+  @JoinColumn({ name: 'trajetId' })
+  trajet: Trajet;
+}

+ 12 - 0
node_app/src/reservations/reservations.module.ts

@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { ReservationsService } from './reservations.service';
+import { ReservationsController } from './reservations.controller';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { Reservation } from './reservation.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([Reservation])],
+  providers: [ReservationsService],
+  controllers: [ReservationsController],
+})
+export class ReservationsModule {}

+ 18 - 0
node_app/src/reservations/reservations.service.spec.ts

@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { ReservationsService } from './reservations.service';
+
+describe('ReservationsService', () => {
+  let service: ReservationsService;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      providers: [ReservationsService],
+    }).compile();
+
+    service = module.get<ReservationsService>(ReservationsService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+});

+ 55 - 0
node_app/src/reservations/reservations.service.ts

@@ -0,0 +1,55 @@
+import { Injectable } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+import { Reservation } from './reservation.entity';
+import { Place } from './place.entity';
+import { Trajet } from '../trajets/trajet.entity';
+
+@Injectable()
+export class ReservationsService {
+  constructor(
+    @InjectRepository(Reservation)
+    private readonly reservationRepository: Repository<Reservation>,
+    @InjectRepository(Place)
+    private readonly placeRepository: Repository<Place>,
+    @InjectRepository(Trajet)
+    private readonly trajetRepository: Repository<Trajet>,
+  ) {}
+
+  async isPlaceAvailable(placeId: number, trajetId: number): Promise<boolean> {
+    const reservations = await this.reservationRepository.find({
+      where: {
+        place: { id: placeId },
+        trajet: { id: trajetId },
+      },
+    });
+
+    return reservations.length === 0; // Si aucune réservation n'existe pour cette place et ce trajet, elle est disponible
+  }
+
+  async createReservation(
+    userId: number,
+    placeId: number,
+    trajetId: number,
+  ): Promise<Reservation> {
+    const place = await this.placeRepository.findOne(placeId);
+    const trajet = await this.trajetRepository.findOne(trajetId);
+
+    if (!place || !trajet) {
+      throw new Error('Place or Trip not found');
+    }
+
+    if (!(await this.isPlaceAvailable(placeId, trajetId))) {
+      throw new Error('Place is already reserved for this trip');
+    }
+
+    const reservation = this.reservationRepository.create({
+      dateAt: new Date(),
+      user: { id: userId },
+      place,
+      trajet,
+    });
+
+    return this.reservationRepository.save(reservation);
+  }
+}

+ 39 - 0
node_app/src/trajets/trajet.entity.ts

@@ -0,0 +1,39 @@
+import { Reservation } from 'src/reservations/reservation.entity';
+import { Vehicule } from 'src/vehicules/vehicule.entity';
+import {
+  Column,
+  Entity,
+  JoinColumn,
+  ManyToOne,
+  OneToMany,
+  PrimaryGeneratedColumn,
+} from 'typeorm';
+
+@Entity()
+export class Trajet {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column({ type: 'datetime' })
+  departAt: Date;
+
+  @Column({ type: 'datetime' })
+  arriveAt: Date;
+
+  @Column()
+  depart: string;
+
+  @Column()
+  arrive: string;
+
+  // Relation ManyToOne avec Vehicle (un trajet est associé à une voiture)
+  @ManyToOne(() => Vehicule, (vehicule) => vehicule.trajets, { eager: true })
+  @JoinColumn({ name: 'vehiculeId' })
+  vehicule: Vehicule;
+
+  // Relation OneToMany avec Reservation (un trajet peut avoir plusieurs réservations)
+  @OneToMany(() => Reservation, (reservation) => reservation.trajet, {
+    cascade: true,
+  })
+  reservations: Reservation[];
+}

+ 12 - 0
node_app/src/trajets/trajets.module.ts

@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { TripsService } from './trips.service';
+import { TripsController } from './trips.controller';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { Trip } from './trip.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([Trip])],
+  providers: [TripsService],
+  controllers: [TripsController],
+})
+export class TrajetsModule {}

+ 28 - 0
node_app/src/users/user.entity.ts

@@ -0,0 +1,28 @@
+import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
+
+@Entity()
+export class User {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column()
+  name: string;
+
+  @Column()
+  otherName: string;
+
+  @Column()
+  address: string;
+
+  @Column()
+  telephone: string;
+
+  @Column()
+  email: string;
+
+  @Column()
+  password: string;
+
+  // est n'est pas un vehicule, une compagnie, une reservation, un voyage
+  // un utilisateur peut-être un chauffeur, un manager
+}

+ 13 - 0
node_app/src/users/users.module.ts

@@ -0,0 +1,13 @@
+import { Module } from '@nestjs/common';
+import { UsersService } from './users.service';
+import { UsersController } from './users.controller';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { User } from './user.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([User])],
+  providers: [UsersService],
+  controllers: [UsersController],
+  exports: [UsersService],
+})
+export class UsersModule {}

+ 44 - 0
node_app/src/vehicules/vehicule.entity.ts

@@ -0,0 +1,44 @@
+import { Place } from 'src/reservations/place.entity';
+import { Trajet } from 'src/trajets/trajet.entity';
+import {
+  Column,
+  Entity,
+  JoinColumn,
+  ManyToOne,
+  OneToMany,
+  PrimaryGeneratedColumn,
+} from 'typeorm';
+
+@Entity()
+export class Vehicule {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column({ type: 'integer' })
+  number_places: number;
+
+  @Column()
+  color: string;
+
+  @Column()
+  type: string;
+
+  @Column({ unique: true })
+  immatriculation: string; // Numéro d'immatriculation de la voiture
+
+  @Column()
+  model: string; // Modèle de la voiture
+
+  // Relation OneToMany avec Place (une voiture peut avoir plusieurs places)
+  @OneToMany(() => Place, (place) => place.vehicule, { cascade: true })
+  places: Place[];
+
+  @ManyToOne(() => Trajet, (trajet) => trajet.vehicule, { eager: true })
+  @JoinColumn({ name: 'vehiculeId' })
+  trajets: Trajet[];
+
+  // appartient à une compagnie,
+  // est gérer par un manager
+  // possède des utilisateurs (passagers)
+  // à un chauffeur ou plusieurs drivers,
+}

+ 12 - 0
node_app/src/vehicules/vehicules.module.ts

@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { VehiclesService } from './vehicles.service';
+import { VehiclesController } from './vehicles.controller';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { Vehicle } from './vehicle.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([Vehicle])],
+  providers: [VehiclesService],
+  controllers: [VehiclesController],
+})
+export class VehiculesModule {}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio