diff --git a/NodeApp/src/commander/assignment/AssignmentCommand.ts b/NodeApp/src/commander/assignment/AssignmentCommand.ts index 8d36acc5581688a025db51d1bad31052875c77d8..baa6ac7ce8c1fe628756e506060a34c239efba76 100644 --- a/NodeApp/src/commander/assignment/AssignmentCommand.ts +++ b/NodeApp/src/commander/assignment/AssignmentCommand.ts @@ -5,6 +5,7 @@ import AssignmentUnpublishCommand from './subcommands/AssignmentUnpublishComman import AssignmentCheckCommand from './subcommands/AssignmentCheckCommand.js'; import AssignmentRunCommand from './subcommands/AssignmentRunCommand.js'; import AssignmentCorrectionCommand from './subcommands/correction/AssignmentCorrectionCommand.js'; +import AssignmentExportCommand from './subcommands/AssignmentExportCommand.js'; class AssignmentCommand extends CommanderCommand { @@ -22,6 +23,7 @@ class AssignmentCommand extends CommanderCommand { AssignmentPublishCommand.registerOnCommand(this.command); AssignmentUnpublishCommand.registerOnCommand(this.command); AssignmentCorrectionCommand.registerOnCommand(this.command); + AssignmentExportCommand.registerOnCommand(this.command); } protected async commandAction(): Promise<void> { diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..0aaf0ae71749233a24d2d87ef01ff90bdacedc86 --- /dev/null +++ b/NodeApp/src/commander/assignment/subcommands/AssignmentExportCommand.ts @@ -0,0 +1,24 @@ +import CommanderCommand from '../../CommanderCommand.js'; +// import ExerciseRunHelper from '../../../helpers/Dojo/ExerciseRunHelper.js'; +// import GlobalHelper from '../../../helpers/GlobalHelper.js'; +import DojoBackendManager from '../../../managers/DojoBackendManager.js'; + + +class AssignmentExportCommand extends CommanderCommand { + protected commandName: string = 'export'; + + protected defineCommand() { + this.command + .description('create a new repository for an assignment') + .argument('<id or namespace>', 'name or url (http/s or ssh) of the assignment') + .action(this.commandAction.bind(this)); + } + + protected async commandAction(idOrNamespace: string): Promise<void> { + const tmp = DojoBackendManager.exportAssignment(idOrNamespace); + console.log(tmp); + } +} + + +export default new AssignmentExportCommand(); \ No newline at end of file diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts index a3fd87ee0f19d1db497c58c261e9c1a665cf80b9..07b9e80e2ed2616a7b46cee4080575f06e11c3b7 100644 --- a/NodeApp/src/managers/DojoBackendManager.ts +++ b/NodeApp/src/managers/DojoBackendManager.ts @@ -16,64 +16,64 @@ import GitlabPipelineStatus from '../shared/types/Gitlab/GitlabPipelineStatus.j class DojoBackendManager { private handleApiError(error: unknown, spinner: ora.Ora, verbose: boolean, defaultErrorMessage?: string, otherErrorHandler?: (error: AxiosError, spinner: ora.Ora, verbose: boolean) => void) { const unknownErrorMessage: string = 'unknown error'; - + if ( verbose ) { if ( error instanceof AxiosError ) { switch ( error.response?.data?.code ) { case DojoStatusCode.ASSIGNMENT_EXERCISE_NOT_RELATED: - spinner.fail(`The exercise does not belong to the assignment.`); - break; + spinner.fail(`The exercise does not belong to the assignment.`); + break; case DojoStatusCode.ASSIGNMENT_PUBLISH_NO_PIPELINE: - spinner.fail(`No pipeline found for this assignment.`); - break; + spinner.fail(`No pipeline found for this assignment.`); + break; case DojoStatusCode.ASSIGNMENT_PUBLISH_PIPELINE_FAILED: - spinner.fail((error.response?.data?.message as string | undefined) ?? `Last pipeline status is not "${ GitlabPipelineStatus.SUCCESS }".`); - break; + spinner.fail((error.response?.data?.message as string | undefined) ?? `Last pipeline status is not "${ GitlabPipelineStatus.SUCCESS }".`); + break; case 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.`); - break; + spinner.fail(`This exercise is already labelled as a correction. If you want to update it, please use the update command.`); + break; case DojoStatusCode.EXERCISE_CORRECTION_NOT_EXIST: - spinner.fail(`The exercise is not labelled as a correction so it's not possible to update it.`); - break; + spinner.fail(`The exercise is not labelled as a correction so it's not possible to update it.`); + break; case DojoStatusCode.ASSIGNMENT_NAME_CONFLICT: - spinner.fail(`Assignment creation error: The assignment name already exists. Please choose another name.`); - break; + spinner.fail(`Assignment creation error: The assignment name already exists. Please choose another name.`); + break; case DojoStatusCode.ASSIGNMENT_CREATION_GITLAB_ERROR: - spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment on GitLab (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); - break; + spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment on GitLab (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); + break; case DojoStatusCode.ASSIGNMENT_CREATION_INTERNAL_ERROR: - spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); - break; + spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); + break; case DojoStatusCode.MAX_EXERCISE_PER_ASSIGNMENT_REACHED: - spinner.fail(`The following users have reached the maximum number of exercise of this assignment : ${ ((error.response.data as DojoBackendResponse<Array<Gitlab.UserSchema>>).data).map(user => user.name).join(', ') }.`); - break; + spinner.fail(`The following users have reached the maximum number of exercise of this assignment : ${ ((error.response.data as DojoBackendResponse<Array<Gitlab.UserSchema>>).data).map(user => user.name).join(', ') }.`); + break; case DojoStatusCode.EXERCISE_CREATION_INTERNAL_ERROR: - spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); - break; + spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); + break; case DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR: - spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise on GitLab (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); - break; + spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise on GitLab (internal error message: ${ error.response?.data?.description ?? unknownErrorMessage }). Please try again later or contact an administrator.`); + break; case DojoStatusCode.GITLAB_TEMPLATE_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 (${ ClientsSharedConfig.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`); - break; + 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 (${ ClientsSharedConfig.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`); + break; case DojoStatusCode.GITLAB_TEMPLATE_ACCESS_UNAUTHORIZED: - spinner.fail(`Please check that the template have public/internal visibility or that your and Dojo account (${ ClientsSharedConfig.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`); - break; + spinner.fail(`Please check that the template have public/internal visibility or that your and Dojo account (${ ClientsSharedConfig.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`); + break; default: - if ( otherErrorHandler ) { - otherErrorHandler(error, spinner, verbose); - } else { - spinner.fail(defaultErrorMessage ?? 'Unknown error'); - } - break; + if ( otherErrorHandler ) { + otherErrorHandler(error, spinner, verbose); + } else { + spinner.fail(defaultErrorMessage ?? 'Unknown error'); + } + break; } } else { spinner.fail(defaultErrorMessage ?? 'Unknown error'); } } } - - + + public async login(gitlabTokens: GitlabToken): Promise<User | undefined> { try { return (await axios.post<DojoBackendResponse<User>>(DojoBackendHelper.getApiUrl(ApiRoute.LOGIN), { @@ -84,15 +84,15 @@ class DojoBackendManager { return undefined; } } - - + + public async refreshTokens(refreshToken: string): Promise<GitlabToken> { return (await axios.post<DojoBackendResponse<GitlabToken>>(DojoBackendHelper.getApiUrl(ApiRoute.REFRESH_TOKENS), { refreshToken: refreshToken })).data.data; } - - + + public async getAssignment(nameOrUrl: string): Promise<Assignment | undefined> { try { return (await axios.get<DojoBackendResponse<Assignment>>(DojoBackendHelper.getApiUrl(ApiRoute.ASSIGNMENT_GET, { assignmentNameOrUrl: nameOrUrl }))).data.data; @@ -100,128 +100,136 @@ class DojoBackendManager { return undefined; } } - - + + 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(DojoBackendHelper.getApiUrl(ApiRoute.GITLAB_CHECK_TEMPLATE_ACCESS, { gitlabProjectId: idOrNamespace })); - + if ( verbose ) { spinner.succeed('Template access granted'); } - + return true; } catch ( error ) { this.handleApiError(error, spinner, verbose, `Template error: ${ error }`); - + return false; } } - + public async createAssignment(name: string, members: Array<Gitlab.UserSchema>, 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>>(DojoBackendHelper.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 ) { this.handleApiError(error, spinner, verbose, `Assignment creation error: unknown error`); - + throw error; } } - + public async createExercise(assignmentName: string, members: Array<Gitlab.UserSchema>, verbose: boolean = true): Promise<Exercise> { const spinner: ora.Ora = ora('Creating exercise...'); - + if ( verbose ) { spinner.start(); } - + try { const response = await axios.post<DojoBackendResponse<Exercise>>(DojoBackendHelper.getApiUrl(ApiRoute.EXERCISE_CREATE, { assignmentNameOrUrl: assignmentName }), { members: JSON.stringify(members) }); - + if ( verbose ) { spinner.succeed(`Exercise successfully created`); } - + return response.data.data; } catch ( error ) { this.handleApiError(error, spinner, verbose, `Exercise creation error: unknown error`); - + throw error; } } - + 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>>(DojoBackendHelper.getApiUrl(publish ? ApiRoute.ASSIGNMENT_PUBLISH : ApiRoute.ASSIGNMENT_UNPUBLISH, { assignmentNameOrUrl: assignment.name }), {}); - + if ( verbose ) { spinner.succeed(`Assignment ${ assignment.name } successfully ${ publish ? 'published' : 'unpublished' }`); } - + return; } catch ( error ) { this.handleApiError(error, spinner, verbose, `Assignment visibility change error: ${ 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.bind(axios) : axios.post.bind(axios); const route = isUpdate ? ApiRoute.ASSIGNMENT_CORRECTION_UPDATE : ApiRoute.ASSIGNMENT_CORRECTION_LINK; - + await axiosFunction(DojoBackendHelper.getApiUrl(route, { assignmentNameOrUrl: assignment.name, exerciseIdOrUrl : exerciseIdOrUrl }), { - exerciseIdOrUrl: exerciseIdOrUrl - }); - + exerciseIdOrUrl: exerciseIdOrUrl + }); + if ( verbose ) { spinner.succeed(`Correction ${ isUpdate ? 'updated' : 'linked' }`); } - + return true; } catch ( error ) { this.handleApiError(error, spinner, verbose, `Correction ${ isUpdate ? 'update' : 'link' } error: ${ error }`); - + return false; } } + + public async exportAssignment(idOrNamespace: string) { + try { + return (await axios.get<DojoBackendResponse<null>>(DojoBackendHelper.getApiUrl(ApiRoute.ASSIGNMENT_ARCHIVE, { assignmentNameOrUrl: idOrNamespace}))).data.data; + } catch ( error ) { + return undefined; + } + } }