From 537e215dd0dd4a6d3be67427122f74f121b8b650 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Minelli?= <michael@minelli.me>
Date: Fri, 30 Jun 2023 23:13:30 +0200
Subject: [PATCH] EnonceCreate => Refactor code and enonce name availability
 check

---
 .../commander/enonce/EnonceCreateCommand.ts   | 61 +++----------------
 NodeApp/src/managers/DojoBackendManager.ts    | 15 ++++-
 NodeApp/src/managers/GitlabManager.ts         | 47 ++++++++++++++
 NodeApp/src/types/ApiRoutes.ts                |  1 +
 4 files changed, 70 insertions(+), 54 deletions(-)

diff --git a/NodeApp/src/commander/enonce/EnonceCreateCommand.ts b/NodeApp/src/commander/enonce/EnonceCreateCommand.ts
index b4591ee..ec43c65 100644
--- a/NodeApp/src/commander/enonce/EnonceCreateCommand.ts
+++ b/NodeApp/src/commander/enonce/EnonceCreateCommand.ts
@@ -28,8 +28,8 @@ class EnonceCreateCommand extends CommanderCommand {
         this.command
         .description('create a new repository for an enonce')
         .requiredOption('-n, --name <name>', 'name of the enonce')
-        .option('-i, --members_id <ids...>', 'list of members ids (teaching staff) to add to the repository')
-        .option('-u, --members_username <usernames...>', 'list of members username (teaching staff) to add to the repository')
+        .option('-i, --members_id <ids...>', 'list of gitlab members ids (teaching staff) to add to the repository')
+        .option('-u, --members_username <usernames...>', 'list of gitlab members username (teaching staff) to add to the repository')
         .option('-t, --template <string>', 'id or url of the template (http(s) and ssh urls are possible)')
         .action(this.commandAction.bind(this));
     }
@@ -44,53 +44,6 @@ class EnonceCreateCommand extends CommanderCommand {
         return (await GitlabManager.testToken(true)).every(result => result);
     }
 
-    private async fetchMembers(options: any): Promise<Array<GitlabUser> | false> {
-        if ( options.members_id || options.members_username ) {
-            ora('Checking Gitlab members:').start().info();
-        }
-
-        let members: Array<GitlabUser> = [];
-
-        async function getMembers<T>(context: any, functionName: string, paramsToSearch: Array<T>): Promise<boolean> {
-            const result = await (context[functionName] as (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<GitlabUser | undefined>>)(paramsToSearch, true, 8);
-
-            if ( result.every(user => user) ) {
-                members = members.concat(result as Array<GitlabUser>);
-                return true;
-            } else {
-                return false;
-            }
-        }
-
-        let result = true;
-
-        if ( options.members_id ) {
-            ora({
-                    text  : 'Fetching members by id:',
-                    indent: 4
-                }).start().info();
-
-            result = await getMembers(GitlabManager, 'getUsersById', options.members_id);
-        }
-
-        if ( options.members_username ) {
-            ora({
-                    text  : 'Fetching members by username:',
-                    indent: 4
-                }).start().info();
-
-            result = result && await getMembers(GitlabManager, 'getUsersByUsername', options.members_username);
-        }
-
-        if ( !result ) {
-            return false;
-        }
-
-        members = members.reduce((unique, user) => (unique.findIndex(uniqueUser => uniqueUser.id === user.id) !== -1 ? unique : [ ...unique, user ]), Array<GitlabUser>());
-
-        return members;
-    }
-
     protected async commandAction(options: any): Promise<void> {
         let members!: Array<GitlabUser> | false;
         let templateIdOrNamespace: string | null = null;
@@ -103,11 +56,18 @@ class EnonceCreateCommand extends CommanderCommand {
                 return;
             }
 
-            members = await this.fetchMembers(options);
+            members = await GitlabManager.fetchMembers(options);
             if ( !members ) {
                 return;
             }
 
+            const enonceGetSpinner: ora.Ora = ora('Checking enonce name availability').start();
+            if ( await DojoBackendManager.getEnonce(options.name) ) {
+                enonceGetSpinner.fail(`Enonce name "${ options.name }" is already taken. Please choose another one.`);
+                return;
+            }
+            enonceGetSpinner.succeed(`Enonce name "${ options.name }" is available`);
+
             if ( options.template ) {
                 templateIdOrNamespace = options.template;
 
@@ -135,7 +95,6 @@ class EnonceCreateCommand extends CommanderCommand {
                         }).start().info();
                 };
 
-                oraInfo(`Dojo ID: ${ enonce.id }`);
                 oraInfo(`Name: ${ enonce.name }`);
                 oraInfo(`Web URL: ${ enonce.gitlabCreationInfo.web_url }`);
                 oraInfo(`HTTP Repo: ${ enonce.gitlabCreationInfo.http_url_to_repo }`);
diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts
index 48746d2..f5fcb4f 100644
--- a/NodeApp/src/managers/DojoBackendManager.ts
+++ b/NodeApp/src/managers/DojoBackendManager.ts
@@ -25,6 +25,15 @@ class DojoBackendManager {
         return `${ Config.apiURL }${ route }`;
     }
 
+    public async getEnonce(nameOrUrl: string): Promise<Enonce | undefined> {
+        try {
+            return await axios.get(this.getApiUrl(ApiRoutes.ENONCE_GET).replace('{{nameOrUrl}}', decodeURIComponent(nameOrUrl)));
+        } catch ( error ) {
+            return undefined;
+        }
+    }
+
+
     public async checkTemplateAccess(idOrNamespace: string, verbose: boolean = true): Promise<boolean> {
         const spinner: ora.Ora = ora('Checking template access');
 
@@ -84,13 +93,13 @@ class DojoBackendManager {
                 if ( error instanceof AxiosError ) {
                     if ( error.response ) {
                         if ( error.response.status === StatusCodes.CONFLICT ) {
-                            spinner.fail(`The template name is already used. Please choose another name.`);
+                            spinner.fail(`The enonce name is already used. Please choose another one.`);
                         } else {
-                            spinner.fail(`Template creation error: ${ error.response.statusText }`);
+                            spinner.fail(`Enonce creation error: ${ error.response.statusText }`);
                         }
                     }
                 } else {
-                    spinner.fail(`Template creation error: unknown error`);
+                    spinner.fail(`Enonce creation error: unknown error`);
                 }
             }
 
diff --git a/NodeApp/src/managers/GitlabManager.ts b/NodeApp/src/managers/GitlabManager.ts
index b0d17ba..bb12aeb 100644
--- a/NodeApp/src/managers/GitlabManager.ts
+++ b/NodeApp/src/managers/GitlabManager.ts
@@ -164,6 +164,53 @@ class GitlabManager {
     public async getRepository(repoId: number): Promise<any> {
         return await axios.get(`${ Config.gitlab.apiURL }/projects/${ repoId }`);
     }
+
+    public async fetchMembers(options: any): Promise<Array<GitlabUser> | false> {
+        if ( options.members_id || options.members_username ) {
+            ora('Checking Gitlab members:').start().info();
+        }
+
+        let members: Array<GitlabUser> = [];
+
+        async function getMembers<T>(context: any, functionName: string, paramsToSearch: Array<T>): Promise<boolean> {
+            const result = await (context[functionName] as (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<GitlabUser | undefined>>)(paramsToSearch, true, 8);
+
+            if ( result.every(user => user) ) {
+                members = members.concat(result as Array<GitlabUser>);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        let result = true;
+
+        if ( options.members_id ) {
+            ora({
+                    text  : 'Fetching members by id:',
+                    indent: 4
+                }).start().info();
+
+            result = await getMembers(this, 'getUsersById', options.members_id);
+        }
+
+        if ( options.members_username ) {
+            ora({
+                    text  : 'Fetching members by username:',
+                    indent: 4
+                }).start().info();
+
+            result = result && await getMembers(this, 'getUsersByUsername', options.members_username);
+        }
+
+        if ( !result ) {
+            return false;
+        }
+
+        members = members.reduce((unique, user) => (unique.findIndex(uniqueUser => uniqueUser.id === user.id) !== -1 ? unique : [ ...unique, user ]), Array<GitlabUser>());
+
+        return members;
+    }
 }
 
 
diff --git a/NodeApp/src/types/ApiRoutes.ts b/NodeApp/src/types/ApiRoutes.ts
index 74237bd..cc62f3f 100644
--- a/NodeApp/src/types/ApiRoutes.ts
+++ b/NodeApp/src/types/ApiRoutes.ts
@@ -2,6 +2,7 @@ enum ApiRoutes {
     LOGIN                        = '/login',
     TEST_SESSION                 = '/test_session',
     GITLAB_CHECK_TEMPLATE_ACCESS = '/gitlab/project/{{id}}/checkTemplateAccess',
+    ENONCE_GET                   = '/enonces/{{nameOrUrl}}',
     ENONCE_CREATE                = '/enonces',
 }
 
-- 
GitLab