From 58266dfc04e7280d8990d2b6a7eb5aa5ac925220 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Minelli?= <michael@minelli.me>
Date: Wed, 28 Jun 2023 22:20:03 +0200
Subject: [PATCH] Add DojoBackendManager

---
 NodeApp/src/managers/DojoBackendManager.ts | 92 ++++++++++++++++++++++
 NodeApp/src/managers/HttpManager.ts        | 27 ++-----
 NodeApp/src/managers/SessionManager.ts     |  9 ++-
 NodeApp/src/types/ApiRoutes.ts             |  9 +++
 4 files changed, 114 insertions(+), 23 deletions(-)
 create mode 100644 NodeApp/src/managers/DojoBackendManager.ts
 create mode 100644 NodeApp/src/types/ApiRoutes.ts

diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts
new file mode 100644
index 0000000..36d62b0
--- /dev/null
+++ b/NodeApp/src/managers/DojoBackendManager.ts
@@ -0,0 +1,92 @@
+import axios, { AxiosError } from 'axios';
+import Config                from '../config/Config';
+import ora                   from 'ora';
+import ApiRoutes             from '../types/ApiRoutes';
+import { StatusCodes }       from 'http-status-codes';
+import Enonce                from '../types/Enonce';
+import GitlabUser            from '../shared/types/Gitlab/GitlabUser';
+
+
+class DojoBackendManager {
+    constructor() { }
+
+    private static _instance: DojoBackendManager;
+
+    public static get instance(): DojoBackendManager {
+        if ( !DojoBackendManager._instance ) {
+            DojoBackendManager._instance = new DojoBackendManager();
+        }
+
+        return DojoBackendManager._instance;
+    }
+
+    public getApiUrl(route: ApiRoutes): string {
+        return `${ Config.apiURL }${ route }`;
+    }
+
+    public async checkTemplateAccess(idOrNamespace: string, verbose: boolean = true): Promise<boolean> {
+        const spinner: ora.Ora = ora('Checking template access');
+
+        if ( verbose ) {
+            spinner.start();
+        }
+
+        try {
+            await axios.get(this.getApiUrl(ApiRoutes.GITLAB_CHECK_TEMPLATE_ACCESS).replace('{{id}}', idOrNamespace));
+
+            if ( verbose ) {
+                spinner.succeed('Template access granted');
+            }
+
+            return true;
+        } catch ( error ) {
+            if ( verbose ) {
+                if ( error instanceof AxiosError ) {
+                    if ( error.response ) {
+                        if ( error.response.status === StatusCodes.NOT_FOUND ) {
+                            spinner.fail(`Template not found or access denied. Please check the template ID or url. Also, please check that the template have public/internal visibility or that your and Dojo account (${ Config.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`);
+                        } else if ( error.response.status === StatusCodes.UNAUTHORIZED ) {
+                            spinner.fail(`Please check that the template have public/internal visibility or that your and Dojo account (${ Config.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`);
+                        } else {
+                            spinner.fail(`Template error: ${ error.response.statusText }`);
+                        }
+                    }
+                } else {
+                    spinner.fail(`Template error: ${ error }`);
+                }
+            }
+
+            return false;
+        }
+    }
+
+    public async createProject(name: string, members: Array<GitlabUser>, verbose: boolean = true): Promise<Enonce> {
+        const spinner: ora.Ora = ora('Creating enonce...');
+
+        if ( verbose ) {
+            spinner.start();
+        }
+
+        try {
+            const response = await axios.post<Enonce>(this.getApiUrl(ApiRoutes.ENONCE_CREATE), {
+                name   : name,
+                members: JSON.stringify(members)
+            });
+
+            return response.data;
+        } catch ( error ) {
+            if ( verbose ) {
+                if ( error instanceof AxiosError ) {
+                    spinner.fail(`Error...`);
+                } else {
+                    spinner.fail(`Error...`);
+                }
+            }
+
+            throw error;
+        }
+    }
+}
+
+
+export default DojoBackendManager.instance;
diff --git a/NodeApp/src/managers/HttpManager.ts b/NodeApp/src/managers/HttpManager.ts
index dbb044c..8f579e5 100644
--- a/NodeApp/src/managers/HttpManager.ts
+++ b/NodeApp/src/managers/HttpManager.ts
@@ -4,13 +4,10 @@ import SessionManager                 from './SessionManager';
 import FormData                       from 'form-data';
 import logger                         from '../shared/logging/WinstonLogger';
 import GitlabManager                  from './GitlabManager';
+import { StatusCodes }                from 'http-status-codes';
 
 
 class HttpManager {
-    private _API_BASE_URL!: string;
-    public LOGIN_URL!: string;
-    public TEST_SESSION_URL!: string;
-
     public handleCommandErrors: boolean = true;
 
     private static _instance: HttpManager;
@@ -23,16 +20,7 @@ class HttpManager {
         return HttpManager._instance;
     }
 
-    private constructor() {
-
-    }
-
-    set API_BASE_URL(url: string) {
-        this._API_BASE_URL = url;
-
-        this.LOGIN_URL = `${ this._API_BASE_URL }/login`;
-        this.TEST_SESSION_URL = `${ this._API_BASE_URL }/test_session`;
-    }
+    private constructor() { }
 
     registerAxiosInterceptor() {
         this.registerRequestInterceptor();
@@ -45,13 +33,12 @@ class HttpManager {
                 config.headers = { ...config.headers, ...(config.data as FormData).getHeaders() } as AxiosRequestHeaders;
             }
 
-            if ( SessionManager.isLogged && config.url && config.url.indexOf(Config.apiURL) !== -1 ) {
-                config.headers = {
-                    ...config.headers,
-                    'Content-Type': 'multipart/form-data'
-                } as AxiosRequestHeaders;
+            if ( config.url && (config.url.indexOf(Config.apiURL) !== -1) ) {
+                config.headers['Content-Type'] = 'multipart/form-data';
 
-                config.headers.Authorization = 'Bearer ' + SessionManager.token;
+                if ( SessionManager.isLogged ) {
+                    config.headers.Authorization = 'Bearer ' + SessionManager.token;
+                }
             }
 
             if ( GitlabManager.isLogged && config.url && config.url.indexOf(Config.gitlab.apiURL) !== -1 ) {
diff --git a/NodeApp/src/managers/SessionManager.ts b/NodeApp/src/managers/SessionManager.ts
index 2f0f9ab..2525d55 100644
--- a/NodeApp/src/managers/SessionManager.ts
+++ b/NodeApp/src/managers/SessionManager.ts
@@ -6,6 +6,9 @@ import axios, { AxiosError } from 'axios';
 import HttpManager           from './HttpManager';
 import ora                   from 'ora';
 import Permissions           from '../types/Permissions';
+import ApiRoutes             from '../types/ApiRoutes';
+import DojoBackendManager    from './DojoBackendManager';
+import { StatusCodes }       from 'http-status-codes';
 
 
 class SessionManager {
@@ -54,7 +57,7 @@ class SessionManager {
         try {
             this.profile = new User();
 
-            const response = await axios.post(HttpManager.LOGIN_URL, {
+            const response = await axios.post(DojoBackendManager.getApiUrl(ApiRoutes.LOGIN), {
                 user    : user,
                 password: password
             });
@@ -83,7 +86,7 @@ class SessionManager {
         const hasPermission = (permissionPredicate: () => boolean, verboseText: string): boolean => {
             const spinner: ora.Ora = ora({
                                              text  : verboseText,
-                                             indent: 4
+                                             indent: 8
                                          });
 
             let isAllowed: boolean = this.profile.id !== -1 && permissionPredicate();
@@ -119,7 +122,7 @@ class SessionManager {
         }
 
         try {
-            await axios.get(HttpManager.TEST_SESSION_URL, {});
+            await axios.get(DojoBackendManager.getApiUrl(ApiRoutes.TEST_SESSION), {});
 
             if ( verbose ) {
                 spinner.succeed(`The session is valid`);
diff --git a/NodeApp/src/types/ApiRoutes.ts b/NodeApp/src/types/ApiRoutes.ts
new file mode 100644
index 0000000..74237bd
--- /dev/null
+++ b/NodeApp/src/types/ApiRoutes.ts
@@ -0,0 +1,9 @@
+enum ApiRoutes {
+    LOGIN                        = '/login',
+    TEST_SESSION                 = '/test_session',
+    GITLAB_CHECK_TEMPLATE_ACCESS = '/gitlab/project/{{id}}/checkTemplateAccess',
+    ENONCE_CREATE                = '/enonces',
+}
+
+
+export default ApiRoutes;
\ No newline at end of file
-- 
GitLab