From d25f1dc35fbe39cd9fe2a7218333117991454467 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Minelli?= <michael@minelli.me>
Date: Wed, 9 Aug 2023 19:46:46 +0200
Subject: [PATCH] ExerciceRoutes => Add create result route

---
 ExpressAPI/src/helpers/DojoValidators.ts | 19 +++++++++
 ExpressAPI/src/routes/ExerciceRoutes.ts  | 52 ++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/ExpressAPI/src/helpers/DojoValidators.ts b/ExpressAPI/src/helpers/DojoValidators.ts
index 7f9cdf4..617c556 100644
--- a/ExpressAPI/src/helpers/DojoValidators.ts
+++ b/ExpressAPI/src/helpers/DojoValidators.ts
@@ -4,6 +4,7 @@ import { CustomValidator, ErrorMessage, FieldMessageFactory, Meta } from 'expres
 import { BailOptions, ValidationChain }                             from 'express-validator/src/chain';
 import GitlabManager                                                from '../managers/GitlabManager';
 import express                                                      from 'express';
+import ExerciceHelper                                               from '../shared/helpers/ExerciceHelper';
 
 
 declare type DojoMeta = Meta & {
@@ -81,6 +82,24 @@ class DojoValidators {
                                                                           return value;
                                                                       }
                                                                   });
+
+    readonly exerciceResultsValidator = this.toValidatorSchemaOptions({
+                                                                          bail        : true,
+                                                                          errorMessage: 'Results: not provided or invalid format',
+                                                                          options     : (value, {
+                                                                              req,
+                                                                              path
+                                                                          }) => {
+                                                                              return new Promise((resolve, reject) => {
+                                                                                  const results = this.getParamValue(req, path);
+                                                                                  if ( results ) {
+                                                                                      ExerciceHelper.validateResultFile(results, false).isValid ? resolve(true) : reject();
+                                                                                  } else {
+                                                                                      reject();
+                                                                                  }
+                                                                              });
+                                                                          }
+                                                                      });
 }
 
 
diff --git a/ExpressAPI/src/routes/ExerciceRoutes.ts b/ExpressAPI/src/routes/ExerciceRoutes.ts
index 265212d..6a397e6 100644
--- a/ExpressAPI/src/routes/ExerciceRoutes.ts
+++ b/ExpressAPI/src/routes/ExerciceRoutes.ts
@@ -24,6 +24,9 @@ import GitlabFile                     from '../shared/types/Gitlab/GitlabFile';
 import EnonceFile                     from '../shared/types/Dojo/EnonceFile';
 import GitlabTreeFileType             from '../shared/types/Gitlab/GitlabTreeFileType';
 import JSON5                          from 'json5';
+import ExerciceResultsFile            from '../shared/types/Dojo/ExerciceResultsFile';
+import fs                             from 'fs';
+import path                           from 'path';
 
 
 class ExerciceRoutes implements RoutesManager {
@@ -35,10 +38,39 @@ class ExerciceRoutes implements RoutesManager {
         }
     };
 
+    private readonly resultValidator: ExpressValidator.Schema = {
+        exitCode     : {
+            isInt: true,
+            toInt: true
+        },
+        commit       : {
+            trim           : true,
+            notEmpty       : true,
+            customSanitizer: DojoValidators.jsonSanitizer
+        },
+        results      : {
+            trim           : true,
+            notEmpty       : true,
+            custom         : DojoValidators.exerciceResultsValidator,
+            customSanitizer: DojoValidators.jsonSanitizer
+        },
+        files        : {
+            trim           : true,
+            notEmpty       : true,
+            customSanitizer: DojoValidators.jsonSanitizer
+        },
+        archiveBase64: {
+            isBase64: true,
+            notEmpty: true
+        }
+    };
+
     registerOnBackend(backend: Express) {
         backend.post('/enonces/:enonceNameOrUrl/exercices', SecurityMiddleware.check(true, SecurityCheckType.ENONCE_IS_PUBLISHED), ParamsValidatorMiddleware.validate(this.exerciceValidator), this.createExercice.bind(this));
 
         backend.get('/exercices/:exerciceId/enonce', SecurityMiddleware.check(false, SecurityCheckType.EXERCICE_SECRET), this.getEnonce.bind(this));
+
+        backend.post('/exercices/:exerciceId/results', SecurityMiddleware.check(false, SecurityCheckType.EXERCICE_SECRET), ParamsValidatorMiddleware.validate(this.resultValidator), this.createResult.bind(this));
     }
 
     private getExerciceName(enonce: Enonce, members: Array<GitlabUser>, suffix: number): string {
@@ -170,6 +202,26 @@ class ExerciceRoutes implements RoutesManager {
             immutable : immutableFiles
         });
     }
+
+    private async createResult(req: express.Request, res: express.Response) {
+        const params: { exitCode: number, commit: any, results: ExerciceResultsFile, files: any, archiveBase64: string } = req.body;
+        const exercice: Exercice = req.boundParams.exercice!;
+
+        const result = await db.result.create({
+                                                  data: {
+                                                      exerciceId: exercice.id,
+                                                      exitCode  : params.exitCode,
+                                                      success   : params.results.success,
+                                                      commit    : params.commit,
+                                                      results   : params.results as unknown as Prisma.JsonObject,
+                                                      files     : params.files
+                                                  }
+                                              });
+
+        fs.writeFileSync(path.join(Config.getResultsFolder(exercice), `${ result.dateTime.toISOString().replace(':', '-') }.tar.gz`), params.archiveBase64, 'base64');
+
+        req.session.sendResponse(res, StatusCodes.OK);
+    }
 }
 
 
-- 
GitLab