diff --git a/NodeApp/src/commander/user/UserCommand.ts b/NodeApp/src/commander/user/UserCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..f25d7e172db5dc30c3e70fe5582e3eefdfbe22b3 --- /dev/null +++ b/NodeApp/src/commander/user/UserCommand.ts @@ -0,0 +1,22 @@ +import CommanderCommand from '../CommanderCommand'; +import UserChangeRoleCommand from './subcommands/UserChangeRoleCommand'; +import UserListCommand from './subcommands/UserListCommand'; + +class UserCommand extends CommanderCommand { + protected commandName: string = 'user'; + + protected defineCommand() { + this.command + .description('manage user'); + } + + protected defineSubCommands() { + UserListCommand.registerOnCommand(this.command); + UserChangeRoleCommand.registerOnCommand(this.command); + } + + protected async commandAction(): Promise<void> { } +} + + +export default new UserCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/user/subcommands/UserChangeRoleCommand.ts b/NodeApp/src/commander/user/subcommands/UserChangeRoleCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..d646dcea8b13bf82fe8456e73446f5cc19b63ca1 --- /dev/null +++ b/NodeApp/src/commander/user/subcommands/UserChangeRoleCommand.ts @@ -0,0 +1,45 @@ +import chalk from "chalk"; +import CommanderCommand from "../../CommanderCommand"; +import DojoBackendManager from "../../../managers/DojoBackendManager"; +import ora from "ora"; +import { StatusCodes } from "http-status-codes"; + +class UserChangeRoleCommand extends CommanderCommand { + protected commandName : string = 'role'; + + protected defineCommand(): void { + this.command + .description('change the role of an user') + .arguments('<userId> <newRole>', ) + .action(this.commandAction.bind(this)); + } + + protected async commandAction(id: string, newRole : string): Promise<void> { + { + // if ( !await AccessesHelper.checkTeachingStaff() ) { + // return; + // } + + console.log(chalk.cyan('Please wait while we are changing the role of the user...')); + // TODO : newRole -> type UserRole + const upd = await DojoBackendManager.updUserRole(id, newRole); + + if (!upd) { + return; + } + + const oraInfo = (message: string) => { + ora({ + text: message, + indent: 4 + }).start().info(); + }; + if (upd.status == StatusCodes.OK) { + + oraInfo(`${chalk.green('Modification success')}`); + } + } + } +} + +export default new UserChangeRoleCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/user/subcommands/UserListCommand.ts b/NodeApp/src/commander/user/subcommands/UserListCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..511cbd0acb8bfd4322eb8197518712935b6cde44 --- /dev/null +++ b/NodeApp/src/commander/user/subcommands/UserListCommand.ts @@ -0,0 +1,39 @@ +import chalk from "chalk"; +import CommanderCommand from "../../CommanderCommand"; +import DojoBackendManager from "../../../managers/DojoBackendManager"; +import User from "../../../sharedByClients/models/User"; +import ora from "ora"; + +class UserListCommand extends CommanderCommand { + protected commandName : string = 'list'; + + protected defineCommand(): void { + this.command + .description('list all the user') + .option('-v, --verbose', 'verbose mode - display principal container output in live') + .action(this.commandAction.bind(this)); + } + + protected async commandAction(): Promise<void> { + let users : User[] = []; + // Retrieve data + { + console.log(chalk.cyan('Please wait while we are retrieving the users...')); + users = await DojoBackendManager.getAllUsers(); + users.forEach(user => { + const oraInfo = (message: string) => { + ora({ + text: message, + indent: 4 + }).start().info(); + }; + + oraInfo(`${chalk.magenta('Id:')} ${user.id}`); + oraInfo(`${chalk.magenta('Mail:')} ${user.gitlabUsername}`); + oraInfo(`${chalk.magenta('Role:')} ${user.role}`); + }); + } + } +} + +export default new UserListCommand(); \ No newline at end of file diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts index fcd749df9a44d151c202498cb8d5a8dfe5f2df2a..c2faab9199b7fa0004d67e2870f7b37585f2c45c 100644 --- a/NodeApp/src/managers/DojoBackendManager.ts +++ b/NodeApp/src/managers/DojoBackendManager.ts @@ -16,8 +16,8 @@ class DojoBackendManager { public getApiUrl(route: ApiRoute): string { return `${ ClientsSharedConfig.apiURL }${ route }`; } - - + + public async login(gitlabTokens: GitlabToken): Promise<User | undefined> { try { return (await axios.post<DojoBackendResponse<User>>(this.getApiUrl(ApiRoute.LOGIN), { @@ -28,15 +28,14 @@ class DojoBackendManager { return undefined; } } - - + public async refreshTokens(refreshToken: string): Promise<GitlabToken> { return (await axios.post<DojoBackendResponse<GitlabToken>>(this.getApiUrl(ApiRoute.REFRESH_TOKENS), { refreshToken: refreshToken })).data.data; } - - + + public async getAssignment(nameOrUrl: string): Promise<Assignment | undefined> { try { return (await axios.get<DojoBackendResponse<Assignment>>(this.getApiUrl(ApiRoute.ASSIGNMENT_GET).replace('{{nameOrUrl}}', encodeURIComponent(nameOrUrl)))).data.data; @@ -44,22 +43,36 @@ class DojoBackendManager { return undefined; } } - - + + public async getUserAssignments(id : string) : Promise<User> { + return (await axios.get<DojoBackendResponse<User>>(this.getApiUrl(ApiRoute.USER_ASSIGNMENTS).replace('{{userId}}', id))).data.data; + } + + public async updUserRole(id: string, newRole : string) { + return await axios.patch<DojoBackendResponse<User>>(this.getApiUrl(ApiRoute.USER_CHANGE_ROLE).replace('{{userId}}', id), { + newRole: newRole + }); + + } + + public async delAssignment() : Promise<Assignment[]> { + return (await axios.get<DojoBackendResponse<Assignment[]>>(this.getApiUrl(ApiRoute.ASSIGNMENT_DEL))).data.data; + } + 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(ApiRoute.GITLAB_CHECK_TEMPLATE_ACCESS).replace('{{id}}', idOrNamespace)); - + if ( verbose ) { spinner.succeed('Template access granted'); } - + return true; } catch ( error ) { if ( verbose ) { @@ -77,28 +90,28 @@ class DojoBackendManager { spinner.fail(`Template error: ${ error }`); } } - + return false; } } - + public async createAssignment(name: string, members: Array<GitlabUser>, templateIdOrNamespace: string | null, verbose: boolean = true): Promise<Assignment> { const spinner: ora.Ora = ora('Creating assignment...'); - + if ( verbose ) { spinner.start(); } - + try { const response = await axios.post<DojoBackendResponse<Assignment>>(this.getApiUrl(ApiRoute.ASSIGNMENT_CREATE), Object.assign({ - name : name, - members: JSON.stringify(members) - }, templateIdOrNamespace ? { template: templateIdOrNamespace } : {})); - + name : name, + members: JSON.stringify(members) + }, templateIdOrNamespace ? { template: templateIdOrNamespace } : {})); + if ( verbose ) { spinner.succeed(`Assignment successfully created`); } - + return response.data.data; } catch ( error ) { if ( verbose ) { @@ -118,25 +131,25 @@ class DojoBackendManager { spinner.fail(`Assignment creation error: unknown error`); } } - + throw error; } } - + public async createExercise(assignmentName: string, members: Array<GitlabUser>, verbose: boolean = true): Promise<Exercise> { const spinner: ora.Ora = ora('Creating exercise...'); - + if ( verbose ) { spinner.start(); } - + try { const response = await axios.post<DojoBackendResponse<Exercise>>(this.getApiUrl(ApiRoute.EXERCISE_CREATE).replace('{{nameOrUrl}}', encodeURIComponent(assignmentName)), { members: JSON.stringify(members) }); - + if ( verbose ) { spinner.succeed(`Exercise successfully created`); } - + return response.data.data; } catch ( error ) { if ( verbose ) { @@ -160,25 +173,38 @@ class DojoBackendManager { spinner.fail(`Exercise creation error: unknown error`); } } - + throw error; } } - + + public async deleteExercise(verbose: boolean = true) { + const spinner: ora.Ora = ora('Deleting exercise...'); + + if ( verbose ) { + spinner.start(); + } + } + + public async getAllUsers(): Promise<User[]> { + return (await axios.get<DojoBackendResponse<User[]>>(this.getApiUrl(ApiRoute.USER_GET))).data.data; + } + + public async changeAssignmentPublishedStatus(assignment: Assignment, publish: boolean, verbose: boolean = true) { const spinner: ora.Ora = ora('Changing published status...'); - + if ( verbose ) { spinner.start(); } - + try { await axios.patch<DojoBackendResponse<null>>(this.getApiUrl(publish ? ApiRoute.ASSIGNMENT_PUBLISH : ApiRoute.ASSIGNMENT_UNPUBLISH).replace('{{nameOrUrl}}', encodeURIComponent(assignment.name)), {}); - + if ( verbose ) { spinner.succeed(`Assignment ${ assignment.name } successfully ${ publish ? 'published' : 'unpublished' }`); } - + return; } catch ( error ) { if ( verbose ) { @@ -188,53 +214,10 @@ class DojoBackendManager { spinner.fail(`Assignment visibility change error: unknown error`); } } - + throw error; } } - - public async linkUpdateCorrection(exerciseIdOrUrl: string, assignment: Assignment, isUpdate: boolean, verbose: boolean = true): Promise<boolean> { - const spinner: ora.Ora = ora(`${ isUpdate ? 'Updating' : 'Linking' } correction`); - - if ( verbose ) { - spinner.start(); - } - - try { - const axiosFunction = isUpdate ? axios.patch : axios.post; - const route = isUpdate ? ApiRoute.ASSIGNMENT_CORRECTION_UPDATE : ApiRoute.ASSIGNMENT_CORRECTION_LINK; - - await axiosFunction(this.getApiUrl(route).replace('{{assignmentNameOrUrl}}', encodeURIComponent(assignment.name)).replace('{{exerciseIdOrUrl}}', encodeURIComponent(exerciseIdOrUrl)), { - exerciseIdOrUrl: exerciseIdOrUrl - }); - - if ( verbose ) { - spinner.succeed(`Correction ${ isUpdate ? 'updated' : 'linked' }`); - } - - return true; - } catch ( error ) { - if ( verbose ) { - if ( error instanceof AxiosError ) { - if ( error.response?.data ) { - if ( error.response.data.code === DojoStatusCode.ASSIGNMENT_EXERCISE_NOT_RELATED ) { - spinner.fail(`The exercise does not belong to the assignment.`); - } else if ( error.response.data.code === DojoStatusCode.EXERCISE_CORRECTION_ALREADY_EXIST ) { - spinner.fail(`This exercise is already labelled as a correction. If you want to update it, please use the update command.`); - } else if ( error.response.data.code === DojoStatusCode.EXERCISE_CORRECTION_NOT_EXIST ) { - spinner.fail(`The exercise is not labelled as a correction so it's not possible to update it.`); - } - } else { - spinner.fail(`Correction ${ isUpdate ? 'update' : 'link' } error: ${ error.response?.statusText }`); - } - } else { - spinner.fail(`Correction ${ isUpdate ? 'update' : 'link' } error: ${ error }`); - } - } - - return false; - } - } }