diff --git a/NodeApp/src/commander/assignment/AssignmentCommand.ts b/NodeApp/src/commander/assignment/AssignmentCommand.ts index 90ae6167deaece3339766cc3f8a7b090263d2e79..b54c2cb00fcd0622f818ed9c621b823d9b7699e4 100644 --- a/NodeApp/src/commander/assignment/AssignmentCommand.ts +++ b/NodeApp/src/commander/assignment/AssignmentCommand.ts @@ -1,9 +1,10 @@ -import CommanderCommand from '../CommanderCommand'; -import AssignmentCreateCommand from './subcommands/AssignmentCreateCommand'; -import AssignmentPublishCommand from './subcommands/AssignmentPublishCommand'; -import AssignmentUnpublishCommand from './subcommands/AssignmentUnpublishCommand'; -import AssignmentCheckCommand from './subcommands/AssignmentCheckCommand'; -import AssignmentRunCommand from './subcommands/AssignmentRunCommand'; +import CommanderCommand from '../CommanderCommand'; +import AssignmentCreateCommand from './subcommands/AssignmentCreateCommand'; +import AssignmentPublishCommand from './subcommands/AssignmentPublishCommand'; +import AssignmentUnpublishCommand from './subcommands/AssignmentUnpublishCommand'; +import AssignmentCheckCommand from './subcommands/AssignmentCheckCommand'; +import AssignmentRunCommand from './subcommands/AssignmentRunCommand'; +import AssignmentCorrectionCommand from './subcommands/correction/AssignmentCorrectionCommand'; class AssignmentCommand extends CommanderCommand { @@ -20,6 +21,7 @@ class AssignmentCommand extends CommanderCommand { AssignmentRunCommand.registerOnCommand(this.command); AssignmentPublishCommand.registerOnCommand(this.command); AssignmentUnpublishCommand.registerOnCommand(this.command); + AssignmentCorrectionCommand.registerOnCommand(this.command); } protected async commandAction(): Promise<void> { } diff --git a/NodeApp/src/commander/assignment/subcommands/correction/AssignmentCorrectionCommand.ts b/NodeApp/src/commander/assignment/subcommands/correction/AssignmentCorrectionCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..3f30a994e7fdcd0a773401db5daa36abba861579 --- /dev/null +++ b/NodeApp/src/commander/assignment/subcommands/correction/AssignmentCorrectionCommand.ts @@ -0,0 +1,23 @@ +import CommanderCommand from '../../../CommanderCommand'; +import AssignmentCorrectionLinkCommand from './subcommands/AssignmentCorrectionLinkCommand'; +import AssignmentCorrectionUpdateCommand from './subcommands/AssignmentCorrectionUpdateCommand'; + + +class AssignmentCorrectionCommand extends CommanderCommand { + protected commandName: string = 'correction'; + + protected defineCommand() { + this.command + .description('manage corrections of an assignment'); + } + + protected defineSubCommands() { + AssignmentCorrectionLinkCommand.registerOnCommand(this.command); + AssignmentCorrectionUpdateCommand.registerOnCommand(this.command); + } + + protected async commandAction(): Promise<void> { } +} + + +export default new AssignmentCorrectionCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionLinkCommand.ts b/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionLinkCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..5d173206038be1262127faf618b74cb874022ffa --- /dev/null +++ b/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionLinkCommand.ts @@ -0,0 +1,10 @@ +import AssignmentCorrectionLinkUpdateCommand from './AssignmentCorrectionLinkUpdateCommand'; + + +class AssignmentCorrectionLinkCommand extends AssignmentCorrectionLinkUpdateCommand { + protected commandName: string = 'link'; + protected isUpdate: boolean = false; +} + + +export default new AssignmentCorrectionLinkCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionLinkUpdateCommand.ts b/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionLinkUpdateCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..cd7b4f8897678e3e43fe2bd6973a76f0ac61db94 --- /dev/null +++ b/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionLinkUpdateCommand.ts @@ -0,0 +1,62 @@ +import CommanderCommand from '../../../../CommanderCommand'; +import chalk from 'chalk'; +import ora from 'ora'; +import DojoBackendManager from '../../../../../managers/DojoBackendManager'; +import SessionManager from '../../../../../managers/SessionManager'; +import Assignment from '../../../../../sharedByClients/models/Assignment'; + + +abstract class AssignmentCorrectionLinkUpdateCommand extends CommanderCommand { + protected abstract isUpdate: boolean; + + protected defineCommand() { + this.command + .description(this.isUpdate ? 'update a correction of an assignment' : 'link an exercise repo as a correction for an assignment') + .argument('<string>', 'id or url of the exercise that is the correction') + .requiredOption('-a, --assignment <string>', 'id or url of the assignment of the correction') + .action(this.commandAction.bind(this)); + } + + protected async commandAction(exerciseIdOrUrl: string, options: { assignment: string }): Promise<void> { + let assignment!: Assignment | undefined; + + // Check access + { + console.log(chalk.cyan('Please wait while we check access...')); + + const assignmentGetSpinner: ora.Ora = ora('Checking if assignment exists').start(); + assignment = await DojoBackendManager.getAssignment(options.assignment); + if ( !assignment ) { + assignmentGetSpinner.fail(`The assignment doesn't exists`); + return; + } + assignmentGetSpinner.succeed(`The assignment exists`); + + + const assignmentAccessSpinner: ora.Ora = ora('Checking assignment access').start(); + if ( assignment.staff.find(staff => staff.id === SessionManager.profile?.id) === undefined ) { + assignmentAccessSpinner.fail(`You are not in the staff of the assignment`); + return; + } + assignmentAccessSpinner.succeed(`You are in the staff of the assignment`); + + + const assignmentPublishedSpinner: ora.Ora = ora('Checking assignment').start(); + if ( !assignment.published ) { + assignmentPublishedSpinner.fail(`Assignment is not published`); + return; + } + assignmentPublishedSpinner.succeed(`Assignment is published`); + } + + // Link the exercise + { + console.log(chalk.cyan('Please wait while we link the exercise...')); + + await DojoBackendManager.linkUpdateCorrection(exerciseIdOrUrl, assignment, this.isUpdate); + } + } +} + + +export default AssignmentCorrectionLinkUpdateCommand; \ No newline at end of file diff --git a/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionUpdateCommand.ts b/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionUpdateCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..88a9f48dfdce248137c857f945116e0be51d171e --- /dev/null +++ b/NodeApp/src/commander/assignment/subcommands/correction/subcommands/AssignmentCorrectionUpdateCommand.ts @@ -0,0 +1,10 @@ +import AssignmentCorrectionLinkUpdateCommand from './AssignmentCorrectionLinkUpdateCommand'; + + +class AssignmentCorrectionUpdateCommand extends AssignmentCorrectionLinkUpdateCommand { + protected commandName: string = 'update'; + protected isUpdate: boolean = true; +} + + +export default new AssignmentCorrectionUpdateCommand(); \ No newline at end of file diff --git a/NodeApp/src/helpers/AccessesHelper.ts b/NodeApp/src/helpers/AccessesHelper.ts index e49e5819e59c74042fb5f23f79ace5587ae128c3..c9ff5e1bdaa823ca011eba7fa057e1c0b949a74e 100644 --- a/NodeApp/src/helpers/AccessesHelper.ts +++ b/NodeApp/src/helpers/AccessesHelper.ts @@ -3,25 +3,34 @@ import GitlabManager from '../managers/GitlabManager'; class AccessesHelper { - async checkStudent(): Promise<boolean> { + async checkStudent(testGitlab: boolean = false): Promise<boolean> { const sessionResult = await SessionManager.testSession(true, [ 'student' ]); if ( !sessionResult ) { return false; } - return (await GitlabManager.testToken(true)).every(result => result); + if ( testGitlab ) { + return (await GitlabManager.testToken(true)).every(result => result); + } else { + return true; + } } - - async checkTeachingStaff(): Promise<boolean> { + + async checkTeachingStaff(testGitlab: boolean = false): Promise<boolean> { const sessionResult = await SessionManager.testSession(true, [ 'teachingStaff' ]); if ( !sessionResult || !sessionResult.teachingStaff ) { return false; } - return (await GitlabManager.testToken(true)).every(result => result); + if ( testGitlab ) { + return (await GitlabManager.testToken(true)).every(result => result); + } else { + return true; + } } } + export default new AccessesHelper(); \ No newline at end of file diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts index b8e8a41ec1beb1172244b281c61d658dc2c923ec..fcd749df9a44d151c202498cb8d5a8dfe5f2df2a 100644 --- a/NodeApp/src/managers/DojoBackendManager.ts +++ b/NodeApp/src/managers/DojoBackendManager.ts @@ -192,6 +192,49 @@ class DojoBackendManager { 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; + } + } } diff --git a/NodeApp/src/shared b/NodeApp/src/shared index 75f67b647da34337f3b220cacf78b2115d6022bc..9e3f29d2f313ef96944a199da0db39f1827c496a 160000 --- a/NodeApp/src/shared +++ b/NodeApp/src/shared @@ -1 +1 @@ -Subproject commit 75f67b647da34337f3b220cacf78b2115d6022bc +Subproject commit 9e3f29d2f313ef96944a199da0db39f1827c496a diff --git a/NodeApp/src/sharedByClients b/NodeApp/src/sharedByClients index 098c6d20f6ed84240c086b979b56afd598fdfea4..4377a70c3c731a5426fc0d4c88c9e8858f0c5361 160000 --- a/NodeApp/src/sharedByClients +++ b/NodeApp/src/sharedByClients @@ -1 +1 @@ -Subproject commit 098c6d20f6ed84240c086b979b56afd598fdfea4 +Subproject commit 4377a70c3c731a5426fc0d4c88c9e8858f0c5361