Ver Fonte

(fix) version 1.0.3

formation há 4 anos atrás
pai
commit
5d0e007104
23 ficheiros alterados com 597 adições e 169 exclusões
  1. 1 1
      angular-client/src/app/components/admin/assistance/assistance.component.html
  2. 2 1
      angular-client/src/app/components/admin/assistance/assistance.component.scss
  3. 9 7
      angular-client/src/app/components/admin/assistance/assistance.component.ts
  4. 1 1
      angular-client/src/app/components/admin/assistance/response-contact/response-contact.component.html
  5. 1 1
      angular-client/src/app/components/admin/statistic/statistic.component.ts
  6. 8 8
      angular-client/src/app/components/admin/users/users-edit/users-edit.component.html
  7. 16 11
      angular-client/src/app/components/admin/users/users-list/users-list.component.ts
  8. 1 0
      angular-client/src/app/components/login/lost-password/lost-password.component.ts
  9. 5 5
      angular-client/src/app/components/shared/contact/formulaire/formulaire.component.ts
  10. 2 0
      angular-client/src/app/components/shared/contact/map/map.component.ts
  11. 5 2
      angular-client/src/app/components/shared/navbar/navbar.component.html
  12. 4 0
      angular-client/src/app/components/shared/navbar/navbar.component.scss
  13. 4 1
      angular-client/src/app/services/statistic.service.ts
  14. 1 1
      angular-client/src/app/services/users.service.ts
  15. 0 88
      express-server/admin/admin.js
  16. 2 2
      express-server/config/config.json
  17. 5 2
      express-server/controllers/auth.js
  18. 5 4
      express-server/controllers/contact.js
  19. 14 24
      express-server/controllers/gain.js
  20. 8 7
      express-server/controllers/statistique.js
  21. 50 2
      express-server/lib/db.js
  22. 1 1
      express-server/middleware/authorize.js
  23. 452 0
      express-server/report.20210711.192955.12984.0.001.json

+ 1 - 1
angular-client/src/app/components/admin/assistance/assistance.component.html

@@ -1,4 +1,4 @@
-<div class="container navtop">
+<div class="container navtop assistance">
 
     <div mat-dialog-actions class="row justify-content-center my-2">
        

+ 2 - 1
angular-client/src/app/components/admin/assistance/assistance.component.scss

@@ -1,4 +1,5 @@
 .navtop{
     margin-top: 7em;
     margin-bottom: 4em;
-  }
+    min-height: 250px;
+  }

+ 9 - 7
angular-client/src/app/components/admin/assistance/assistance.component.ts

@@ -15,7 +15,7 @@ export class AssistanceComponent implements OnInit {
   constructor(private contactService: ContactService, public dialog: MatDialog) { }
 
   ngOnInit(): void {
-    this.subscribeToGetOpenMessage()
+    this.subscribeToGetOpenMessage();
   }
 
   listOpenMessage : Contact[];
@@ -23,25 +23,27 @@ export class AssistanceComponent implements OnInit {
   //sbscribe statistic
   subscribeToGetOpenMessage() {
     this.contactService.getOpenMessage().subscribe((res) => {
-       this.listOpenMessage = res
+       this.listOpenMessage = res;
+       console.log(JSON.stringify(this.listOpenMessage));
     })
   }
 
   subscribeToGetCloseMessage() {
     this.contactService.getColseMessage().subscribe((res) => {
-       this.listOpenMessage = res
+       this.listOpenMessage = res;
+       console.log(JSON.stringify(this.listOpenMessage));
     })
   }
 
 
   responseMessage($event){
-     console.log($event)
-     this.openResponseContact($event)
+     this.openResponseContact($event);
+     console.log($event);
   }
 
   closeMessage($event){
-     console.log('qsdqsd',$event)
-    this.openDialog($event)
+    this.openDialog($event);
+    console.log(JSON.stringify($event));;
   }
 
 

+ 1 - 1
angular-client/src/app/components/admin/assistance/response-contact/response-contact.component.html

@@ -19,7 +19,7 @@
 
 <div mat-dialog-actions class="row justify-content-center mt-2">
        
-    <button mat-raised-button class="btn mr-2" color="primary" (click)="sendResponse()" >Modifier</button>
+    <button mat-raised-button class="btn mr-2" color="primary" (click)="sendResponse()" >Répondre</button>
     <button mat-raised-button class="btn ml-2" cdkFocusInitial color="primary" (click)="onNoClick()">Annuler</button>
    
   </div>

+ 1 - 1
angular-client/src/app/components/admin/statistic/statistic.component.ts

@@ -34,7 +34,6 @@ export class StatisticComponent implements OnInit {
     this.StatisticService.getStatistic().subscribe((res) => {
       
       this.statisticArray = res.data;
-      
     
 
       this.barChartData = [
@@ -43,6 +42,7 @@ export class StatisticComponent implements OnInit {
         { data: this.statisticArray.map(res => res.served), label: 'server' }
       ];
       
+      
 })
     
     

+ 8 - 8
angular-client/src/app/components/admin/users/users-edit/users-edit.component.html

@@ -1,9 +1,9 @@
 <div mat-dialog-content class="text-center">
-    {{data}}
-    </div>
-    <div mat-dialog-actions class="row justify-content-center mt-3">
-        
-      <button mat-raised-button class="btn mr-2" color="primary" (click)="onConfirm()" >Oui</button>
-      <button mat-raised-button class="btn ml-2" cdkFocusInitial color="primary" (click)="onNoClick()">Non</button>
-     
-    </div>
+  {{data}}
+  </div>
+  <div mat-dialog-actions class="row justify-content-center mt-3">
+      
+    <button mat-raised-button class="btn mr-2" color="primary" (click)="onConfirm()" >Oui</button>
+    <button mat-raised-button class="btn ml-2" cdkFocusInitial color="primary" (click)="onNoClick()">Non</button>
+   
+  </div>

+ 16 - 11
angular-client/src/app/components/admin/users/users-list/users-list.component.ts

@@ -56,21 +56,26 @@ export class UsersListComponent {
   }
 
   // edit user 
-  editUser(element): void {
+  editUser(element : User): void {
+    console.log(JSON.stringify(element))
     const dialogRef = this.dialog.open(UsersEditComponent, {
-      width: '350px',
-      height: '140px',
-      data: "Souhaitez-vous supprimer cet utilisateur ?"
+      width: '550px',
+      height: '340px',
+      data: "Souhaitez-vous modifier cet utilisateur ?"
     });
 
+    let bloqued = {isActive : false }
+
     dialogRef.afterClosed().subscribe(result => {
-      // if (result) {
-      //   this.bookService.cancelBook(this._book.id).subscribe(
-      //     response => {
-      //       this.openDialog()
-      //     }
-      //   )
-      // }
+      if (result) {
+        console.log(JSON.stringify(result))
+        this.usersService.editOneUser(element._id, bloqued ).subscribe(
+          response => {
+            // this.openDialog()
+            console.log(response)
+          }
+        )
+      }
     });
   }
 

+ 1 - 0
angular-client/src/app/components/login/lost-password/lost-password.component.ts

@@ -53,6 +53,7 @@ export class LostPasswordComponent implements OnInit {
     this.loading = true;
     this.authService.lostPassword(this.formGroup.value).subscribe(
       data => {
+        console.log(JSON.stringify(data));
         this.loading = false;
         this.openDialog(data)
       },

+ 5 - 5
angular-client/src/app/components/shared/contact/formulaire/formulaire.component.ts

@@ -72,15 +72,15 @@ export class FormulaireComponent implements OnInit {
     this.loading = true;
     this.contactService.sendMsgContact(this.formGroup.value).subscribe(
       data => {
-        console.log(data)
-        this.response = data.message
+        console.log(data);
+        this.response = data.message;
         this.loading = false;
-        this.openDialog()
+        this.openDialog();
       },
       err => {
         this.loading = false;
-        console.log(err.error.message)
-        this.authService.openSnackBar(err.error.message)
+        console.log(err.error.message);
+        this.authService.openSnackBar(err.error.message);
       });
   }
 

+ 2 - 0
angular-client/src/app/components/shared/contact/map/map.component.ts

@@ -30,8 +30,10 @@ export class MapComponent implements OnInit {
    
    
     this.restaurantsService.getRestaurants().subscribe((data: any) => {
+      console.log('test resto', data)
       data.forEach( (res : Restaurant ) => {
         var marker = L.marker([res.latitude, res.longitude], {icon: myIcon}).addTo(macarte);
+  
 
         marker.bindPopup(`<h5 style="text-align: center"><b>${res.name}</b></h5>  <b> adresse : </b>${res.adress}`,
         { maxWidth: 130 , minWidth:120}

+ 5 - 2
angular-client/src/app/components/shared/navbar/navbar.component.html

@@ -21,7 +21,7 @@
       <a class="navbtn" mat-button routerLink="/statistique" *ngIf="isLogged">Statistique</a>
       <a class="navbtn" mat-button routerLink="/emailing" *ngIf="isLogged">Emailing</a>
       <a class="navbtn" mat-button routerLink="/assistance" *ngIf="isLogged">Assistance</a>
-      <a class="navbtn" mat-button routerLink="/users" *ngIf="isLogged">Employés</a>
+      <!--<a class="navbtn" mat-button routerLink="/users" *ngIf="isLogged">Employés</a>-->
       <a class="navbtn" mat-button routerLink="/contact" >Contact</a>
       <a class="navbtn" mat-icon-button color="basic" aria-label="" (click)="logOut()" *ngIf="isLogged">
         <mat-icon>power_settings_new</mat-icon>
@@ -85,7 +85,10 @@
     <mat-sidenav-content fxFlexFill class="fatboar-sidenav-content">
       
      <router-outlet></router-outlet>
-     <app-footer></app-footer>
+     <div class="footer">
+      <app-footer></app-footer>
+     </div>
+
       
     </mat-sidenav-content>
   

+ 4 - 0
angular-client/src/app/components/shared/navbar/navbar.component.scss

@@ -53,3 +53,7 @@ a{
     margin-left: 3.4em;
    }
 }
+
+.footer {
+  margin-top: 8rem;
+}

+ 4 - 1
angular-client/src/app/services/statistic.service.ts

@@ -25,7 +25,10 @@ private headers = new HttpHeaders(
 getStatistic(): Observable<StatisticResponse> {
 //  return this.http.get<StatisticResponse>('assets/data/stat.json');
 const options = { headers: this.headers};
- return this.http.get<StatisticResponse>('http://localhost:4000/api/tickets/stats',options);
+ let data = this.http.get<StatisticResponse>('http://localhost:4000/api/tickets/stats',options);
+ console.log(JSON.stringify(data));
+ return data;
+ 
 }
 
 

+ 1 - 1
angular-client/src/app/services/users.service.ts

@@ -33,7 +33,7 @@ getOneUser(id: string): Observable <User> {
 
 
 // edit user
-editOneUser(id: string, body): Observable <User> {
+editOneUser(id: string, body: { isActive: boolean; }): Observable <User> {
   return this.http.patch<User>(`${this.apiUrl}/api/users/${id}`, body);
 }
 

+ 0 - 88
express-server/admin/admin.js

@@ -1,88 +0,0 @@
-
-const role = require('../lib/role');
-const bcrypt = require('bcrypt');
-const { User } = require('../models/user.model');
-const jwt = require('jsonwebtoken');
-const config = require('../config/config.json');
-var validator = require('validator');
-
-
-
-//inscription admin
-
-console.log('process.argv =>', process.argv)
-
-const email = process.argv[2];
-const password = process.argv[3];
-console.log('email =>', email);
-console.log('password =>', password);
-
-const user = new User();
-user.role = role.Admin;
-user.email = email;
-//user.password = await bcrypt.hash(password, 12) 
-user.password = password;
-console.log('User =>', user)
-
-user.save().then(() => {
-    const token = jwt.sign({ _id: user._id, email: user.email, role: user.role }, config.secret_key, { expiresIn: '10 h' });
-    res.status(201).json(
-        { success: true, token, expireIn: `${new Date().getTime() + 120000}` });
-
-})
-.catch((err) => console.log('Mon message => ', err))
-
-
-// exports.signup = async (req, res, next) => {
-
-//     try {
-
-//         // génère une exception
-//         if (!req.body.firstname) { throw new Error('Nom introuvable') }
-//         if (!req.body.lastname) { throw new Error('Prénom introuvable') }
-//         if (!req.body.email) { throw new Error('Adresse email introuvable') }
-//         if (!req.body.birthday) { throw new Error('Date de naissance introuvable') }
-//         if (!req.body.phonenumber) { throw new Error('Numéro de téléphone introuvable') }
-//         if (!req.body.adress) { throw new Error('Adresse introuvable') }
-//         if (!validator.isEmail(req.body.email)) { throw new Error('Adresse email invalide') }
-//         if (isNaN(Date.parse(req.body.birthday)) || (Date.parse(req.body.birthday)) > 1073692800000) { throw new Error('Date de naissance invalide') }
-
-
-//         const user = await User.findOne({ email: req.body.email }, { email: 1 })
-
-//         if (user) {
-//             res.status(401).json({ success: false, message: 'Adresse email existe déja veuillez renseigner une autre adresse email' })
-//         } else {
-
-//             bcrypt.hash(req.body.password, 12)
-//                 .then(hash => {
-//                     const user = new User({
-//                         firstname: req.body.firstname,
-//                         lastname: req.body.lastname,
-//                         email: req.body.email,
-//                         role: role.Client,
-//                         birthday: req.body.birthday,
-//                         phonenumber: req.body.phonenumber,
-//                         adress: req.body.adress,
-//                         isActive: true,
-//                         isGain: false,
-//                         password: hash
-//                     });
-
-//                     user.save()
-//                         .then(() => {
-//                             const token = jwt.sign({ userId: user._id, email: user.email, role: user.role }, config.secret_key, { expiresIn: '10 h' })
-//                             res.status(201).json(
-//                                 { success: true, token, expireIn: `${new Date().getTime() + 120000}` })
-//                         })
-//                         .catch((err) => res.status(500).json({ success: false, message: err.message }))
-//                 })
-//                 .catch(() => res.status(400).json({ success: false, message: 'Erreur dans le mot de passe' }));
-//         }
-
-//     }
-//     catch (err) {
-//         res.status(400).json({ success: false, message: err.message })
-//     }
-
-// };

+ 2 - 2
express-server/config/config.json

@@ -3,8 +3,8 @@
     "secret_key": "api-fatboar-henri",
     "reset_password_key": "passwordkey-fatboar_key",
     "email": {
-        "user": "atangana29@gmail.com",
-        "pass": "carmelo",
+        "user": "fatboard.info@gmail.com",
+        "pass": "evryfrance2021",
         "port" : 465,
         "host" :"smtp.gmail.com"
     },

+ 5 - 2
express-server/controllers/auth.js

@@ -106,6 +106,7 @@ exports.forgotPassword = async (req, res, next) => {
 
     try {
 
+        //console.log(JSON.stringify(req.body));
         // génère une exception
         if (!req.body.email) { throw new Error('Adresse email introuvable') }
         if (!validator.isEmail(req.body.email)) { throw new Error('Adresse email invalide') }
@@ -117,11 +118,13 @@ exports.forgotPassword = async (req, res, next) => {
             auth: { user: config.email.user, pass: config.email.pass },
             tls: { rejectUnauthorized: false }
         });
+        console.log("JSON.stringify(smtpTransport)");
 
         User.findOne({ email: req.body.email })
             .then((user) => {
 
                 if (!user) {
+                    console.log("user found");
                     return res.status(404).json({ success: false, message: 'Utilisateur non trouvé avec cette adresse email' });
                 }
 
@@ -134,10 +137,10 @@ exports.forgotPassword = async (req, res, next) => {
                     html: `<h3>Cliquez sur ce lien pour rénisialiser votre mot de passe</h3>
                                <p>${config.reset_password_url}/${token}</p> `
                 };
-
+               
                 user.updateOne({ resetLink: token })
                     .then(() => {
-
+                        console.log("debut d envoi");
                         smtpTransport.sendMail(mailOptions)
                             .then(() => res.status(200).json({ success: true, message: `Un e-mail vous a été envoyé pour réinitialiser votre mot de passe` }))
                             .catch((e) => res.status(500).json({ success: false, message: `${e}` }))

+ 5 - 4
express-server/controllers/contact.js

@@ -1,5 +1,6 @@
 const { Contact } = require('../models/contact.model');
 const nodemailer = require('nodemailer');
+var validator = require('validator');
 const  config  = require('../config/config.json');
 
 
@@ -10,10 +11,10 @@ const  config  = require('../config/config.json');
 exports.addContact = async (req, res, next) => {
 
     try {
-
-        // génère une exception
-        if (!req.body.email) { throw new Error('Adresse email introuvable') }
-        if (!validator.isEmail(req.body.email)) { throw new Error('Adresse email invalide') }
+         // génère une exception
+         if (!req.body.email) { throw new Error('Adresse email introuvable') }
+         if (!validator.isEmail(req.body.email)) { throw new Error('Adresse email invalide') }
+         
 
         const contact = new Contact({
             lastname: req.body.lastname,

+ 14 - 24
express-server/controllers/gain.js

@@ -6,8 +6,8 @@ const { User } = require('../models/user.model');
 //consulter les gains
 exports.gain = async (req, res, next) => {
 
-    try {   
-        //Ticket.save(); console.log('Test début', Ticket.code);
+    try {
+        
         // génère une exception
         if (!req.query.id) { throw new Error(`Identifiant utilisateur introuvable`) }
         if (!req.body.code) { throw new Error(`Code introuvable`) }
@@ -16,50 +16,40 @@ exports.gain = async (req, res, next) => {
 
         
         User.findById(req.query.id)
-            .then((user) => { 
-                 Ticket.findOne({ code: req.body.code })
-                    .then((ticket) => { 
-                    console.log('Tickets list :', ticket) 
-                    res.status(200).send(ticket);
-                    return;
-                    //  for (i = 0; i < 50; i++) {
-                    //      const ticke = new Ticket({
-                    //          code: req.body.code + i,
-                    //          isUsed: true,
-                    //          gains: "30% de réduction dessert et un menu du jour",
-                    //          date_used: new Date(),
-                    //          index: 'index',
-                    //          isServed: true
-                    //     });
-                        
-                    //      ticke.save();
-                    //  }
+            .then((user) => {
 
+                Ticket.findOne({ code: req.body.code })
+                      .then((ticket) => {
+                        
                         if (ticket) {
                             if (ticket.isUsed === false) {
 
                                 ticket.isUsed = true;
                                 ticket.date_used = new Date();
+                                res.send(ticket);
+                                
 
                                 ticket.save()
-                                    .then((ticket) => {
+                                      .then((ticket) => {
                                         user.isGain = true;
                                         user.gains.push(ticket);
                                         user.save()
                                             .then(() => res.status(200).send(ticket))
                                             .catch(() => res.status(500).json({ success: false, message: `Erreur dans le serveur` }))
                                     })
-                                    .catch(() => res.status(500).json({ success: false, message: `Erreur dans le serveur` }))
+                                      .catch(() => res.status(500).json({ success: false, message: `Erreur dans le serveur` }))
 
                             } else { res.status(400).json({ success: false, message: `Le code a déjà été utilisé` }) }
                         } else { res.status(400).json({ success: false, message: `Le code est erroné` }) }
 
                     })
-                    .catch(() => res.status(500).json({ success: false, message: `Erreur dans le serveur` }));
+                       .catch(() => res.status(500).json({ success: false, message: `Erreur dans le serveur` }));
+                       return;
 
             })
             .catch(() => res.status(404).json({ success: false, message: `Utilisateur non trouvé` }))
 
     }
     catch (err) { res.status(400).json({ success: false, message: err.message }) }
-};
+    
+};

+ 8 - 7
express-server/controllers/statistique.js

@@ -8,30 +8,32 @@ exports.getStatistique = async (req, res, next) => {
 
     //une entrée ou un dessert au choix
     const e_ou_d_c_total = await Ticket.countDocuments({ gains: 'une entrée ou un dessert au choix' })
+    console.log(JSON.stringify(e_ou_d_c_total));
     const e_ou_d_c_used = await Ticket.countDocuments({ gains: 'une entrée ou un dessert au choix', isUsed: true })
-    const e_ou_d_c_served = await Ticket.countDocuments({ gains: 'une entrée ou un dessert au choix', isUsed: true, isServed: true })
+    const e_ou_d_c_served = await Ticket.countDocuments({  gains: 'une entrée ou un dessert au choix', isServed: true })
+    console.log(JSON.stringify(e_ou_d_c_served));
 
     //un burger au choix
     const b_c_total = await Ticket.countDocuments({ gains: 'un burger au choix' })
     const b_c_used = await Ticket.countDocuments({ gains: 'un burger au choix', isUsed: true })
-    const b_c_served = await Ticket.countDocuments({ gains: 'un burger au choix', isUsed: true, isServed: true })
+    const b_c_served = await Ticket.countDocuments({ gains: 'un burger au choix',  isServed: true })
 
 
     //un menu du jour
     const m_j_total = await Ticket.countDocuments({ gains: 'un menu du jour' })
     const m_j_used = await Ticket.countDocuments({ gains: 'un menu du jour', isUsed: true })
-    const m_j_served = await Ticket.countDocuments({ gains: 'un menu du jour', isUsed: true, isServed: true })
+    const m_j_served = await Ticket.countDocuments({ gains: 'un menu du jour',  isServed: true })
 
     //un menu au choix
     const m_c_total = await Ticket.countDocuments({ gains: 'un menu au choix' })
     const m_c_used = await Ticket.countDocuments({ gains: 'un menu au choix', isUsed: true })
-    const m_c_served = await Ticket.countDocuments({ gains: 'un menu au choix', isUsed: true, isServed: true })
+    const m_c_served = await Ticket.countDocuments({ gains: 'un menu au choix',  isServed: true })
 
 
     //70% de réduction
     const r_total = await Ticket.countDocuments({ gains: '70% de réduction' })
     const r_used = await Ticket.countDocuments({ gains: '70% de réduction', isUsed: true })
-    const r_served = await Ticket.countDocuments({ gains: '70% de réduction', isUsed: true, isServed: true })
+    const r_served = await Ticket.countDocuments({ gains: '70% de réduction',  isServed: true })
 
 
     res.status(200).json({
@@ -42,9 +44,8 @@ exports.getStatistique = async (req, res, next) => {
       { gain: 'un menu au choix', used: m_c_used, served: m_c_served, total: m_c_total },
       { gain: '70% de réduction', used: r_used, served: r_served, total: r_total }
       ]
-      
     })
-    
+
   }
   catch (err) {
     res.status(500).json({ success: false, message: err.message })

+ 50 - 2
express-server/lib/db.js

@@ -1,6 +1,10 @@
 const mongoose = require('mongoose');
 const  config  = require('../config/config.json');
-
+//const { Ticket } = require('../models/ticket.model');
+//const { Restaurant} = require('../models/restaurant.model');
+// const { User } = require('../models/user.model');
+ //const bcrypt = require('bcrypt');
+// const Role = require('../lib/role');
 const db = config.url;
 
 //var db = 'mongodb://database_preprod:27017/mean-fatboar-db';
@@ -14,4 +18,48 @@ mongoose.connect(db, {useNewUrlParser: true, useUnifiedTopology: true })
 });
 
 
-module.exports = mongoose.connection;
+module.exports = mongoose.connection;
+
+// let min = 999999999;
+// let max = 10000000000;
+// for (i = 0; i < 2; i++) {
+//     let code = Math.floor(Math.random() * (max - min + 1)) + min;
+     
+//          const ticke = new Ticket({
+//              code: code,
+//              isUsed: false,
+//              gains: "un menu du jour",
+//              date_used: new Date(),
+//              index: 'index',
+//              isServed: true
+//         });
+        
+//          ticke.save();
+//      }
+// const resto = new Restaurant({
+//     "index": 5,
+//     "name": "FatBoar 5",
+//     "adress": "20 Rue Houdart, 95700 Roissy-en-France, France",
+//     "longitude": 2.515081,
+//     "latitude": 49.002317
+//   });
+//   resto.save();
+
+// const salt = bcrypt.genSaltSync(12);
+//  password = bcrypt.hashSync('Pass@123', 12);
+//  console.log('fgfg', password);
+// let date = new Date(1997, 1 , 12 , 20, 40);
+ 
+//  const user = new User({
+//                       firstname: " adrien",
+//                       lastname: "xxxxxxx",
+//                       email: "adrien@hotmail.fr",
+//                       role: 'admin',
+//                       birthday: date,
+//                       phonenumber: '0680705876',
+//                       isActive: true,
+//                       password: password
+//                   });
+                  
+
+//  user.save();

+ 1 - 1
express-server/middleware/authorize.js

@@ -6,7 +6,7 @@ module.exports = authorize
 function authorize(roles = []) {
 
     // roles param  (Role.Client or 'client') 
-    // ([Role.Admin, Role.Client] or ['admin', 'clinet'])
+    // ([Role.Admin, Role.Client] or ['admin', 'client'])
 
     if (typeof roles === 'string') { roles = [roles] }
 

Diff do ficheiro suprimidas por serem muito extensas
+ 452 - 0
express-server/report.20210711.192955.12984.0.001.json