diff --git a/ExpressAPI/prisma/migrations/20240521164109_add_correction_description/migration.sql b/ExpressAPI/prisma/migrations/20240521164109_add_correction_description/migration.sql new file mode 100644 index 0000000000000000000000000000000000000000..4589378e38d35f2a1b284028249242510f9d74d5 --- /dev/null +++ b/ExpressAPI/prisma/migrations/20240521164109_add_correction_description/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE `Exercise` ADD COLUMN `correctionDescription` VARCHAR(80) NULL; diff --git a/ExpressAPI/prisma/schema.prisma b/ExpressAPI/prisma/schema.prisma index f60367392fbfdcdf104a78dea1e20a0101bdddb9..8d7143ac874fd4324ce2d1c043f65c2f6e27ba68 100644 --- a/ExpressAPI/prisma/schema.prisma +++ b/ExpressAPI/prisma/schema.prisma @@ -50,7 +50,8 @@ model Exercise { gitlabLastInfo Json @db.Json gitlabLastInfoDate DateTime - correctionCommit Json? @db.Json + correctionCommit Json? @db.Json + correctionDescription String? @db.VarChar(80) assignment Assignment @relation(fields: [assignmentName], references: [name], onDelete: NoAction, onUpdate: Cascade) diff --git a/ExpressAPI/src/helpers/Prisma/Extensions/AssignmentResultExtension.ts b/ExpressAPI/src/helpers/Prisma/Extensions/AssignmentResultExtension.ts index 41919c8bed823c362208784142904bea7ddd8720..c67786c40acf2ca121db4d585af2941d2fe9a286 100644 --- a/ExpressAPI/src/helpers/Prisma/Extensions/AssignmentResultExtension.ts +++ b/ExpressAPI/src/helpers/Prisma/Extensions/AssignmentResultExtension.ts @@ -30,7 +30,7 @@ export default Prisma.defineExtension(client => { assignment: { corrections: { compute(assignment) { - return new LazyVal<Array<Partial<Exercise>> | undefined>(() => getCorrections(assignment)); + return new LazyVal<Array<Partial<Exercise>> | undefined>(() => assignment.published ? getCorrections(assignment) : []); } } } diff --git a/ExpressAPI/src/managers/GitlabManager.ts b/ExpressAPI/src/managers/GitlabManager.ts index 4c25d86bbc393db36d3c7aa21643eec862618aed..bd2746ab4323f39d16b3ab7cee410c463b42ddfe 100644 --- a/ExpressAPI/src/managers/GitlabManager.ts +++ b/ExpressAPI/src/managers/GitlabManager.ts @@ -62,6 +62,15 @@ class GitlabManager extends SharedGitlabManager { } } + async getRepositoryCommit(repoId: number, commitSha: string): Promise<CommitSchema | undefined> { + try { + return await this.api.Commits.show(repoId, commitSha); + } catch ( e ) { + logger.error(JSON.stringify(e)); + return undefined; + } + } + async createRepository(name: string, description: string, visibility: 'public' | 'internal' | 'private', initializeWithReadme: boolean, namespace: number, sharedRunnersEnabled: boolean, wikiEnabled: boolean, importUrl: string): Promise<ProjectSchema> { try { return await this.api.Projects.create({ diff --git a/ExpressAPI/src/routes/AssignmentRoutes.ts b/ExpressAPI/src/routes/AssignmentRoutes.ts index 951afe1c72bf4f59af1ebf37397ae6966233d0d1..583e6aac9fe552695b38bc8ad6972b4ecf28b15d 100644 --- a/ExpressAPI/src/routes/AssignmentRoutes.ts +++ b/ExpressAPI/src/routes/AssignmentRoutes.ts @@ -48,6 +48,14 @@ class AssignmentRoutes implements RoutesManager { trim : true, notEmpty: true, custom : DojoValidators.exerciseIdOrUrlValidator + }, + commit : { + trim : true, + notEmpty: false + }, + description : { + trim : true, + notEmpty: false } }; @@ -60,6 +68,7 @@ class AssignmentRoutes implements RoutesManager { backend.post('/assignments/:assignmentNameOrUrl/corrections', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), ParamsValidatorMiddleware.validate(this.assignmentAddCorrigeValidator), this.linkUpdateAssignmentCorrection(false).bind(this) as RequestHandler); backend.patch('/assignments/:assignmentNameOrUrl/corrections/:exerciseIdOrUrl', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.linkUpdateAssignmentCorrection(true).bind(this) as RequestHandler); + backend.delete('/assignments/:assignmentNameOrUrl/corrections/:exerciseIdOrUrl', SecurityMiddleware.check(true, SecurityCheckType.ASSIGNMENT_STAFF), this.unlinkAssignmentCorrection.bind(this) as RequestHandler); } // Get an assignment by its name or gitlab url @@ -229,9 +238,9 @@ class AssignmentRoutes implements RoutesManager { return req.session.sendResponse(res, StatusCodes.BAD_REQUEST, undefined, 'This exercise is not a correction', DojoStatusCode.EXERCISE_CORRECTION_NOT_EXIST); } - const lastCommit = await GitlabManager.getRepositoryLastCommit(req.boundParams.exercise!.gitlabId); + const commit: Gitlab.CommitSchema | undefined = req.body.commit ? await GitlabManager.getRepositoryCommit(req.boundParams.exercise!.gitlabId, req.body.commit as string) : await GitlabManager.getRepositoryLastCommit(req.boundParams.exercise!.gitlabId); - if ( lastCommit ) { + if ( commit ) { if ( !isUpdate && SharedConfig.production ) { //Disable in dev env because gitlab dev group is private and we can't change visibility of sub projects await GitlabManager.changeRepositoryVisibility(req.boundParams.exercise!.gitlabId, 'internal'); } @@ -240,17 +249,45 @@ class AssignmentRoutes implements RoutesManager { where: { id: req.boundParams.exercise!.id }, - data : { - correctionCommit: lastCommit - } + data : Object.assign({ + correctionCommit: commit + }, isUpdate && req.body.description === undefined ? {} : { + correctionDescription: req.body.description + }) }); return req.session.sendResponse(res, StatusCodes.OK); } else { - return req.session.sendResponse(res, StatusCodes.INTERNAL_SERVER_ERROR, undefined, 'No last commit found'); + return req.session.sendResponse(res, StatusCodes.NOT_FOUND, undefined, 'Commit not found'); } }; } + + private async unlinkAssignmentCorrection(req: express.Request, res: express.Response) { + if ( req.boundParams.exercise?.assignmentName !== req.boundParams.assignment?.name ) { + return req.session.sendResponse(res, StatusCodes.BAD_REQUEST, undefined, 'The exercise does not belong to the assignment', DojoStatusCode.ASSIGNMENT_EXERCISE_NOT_RELATED); + } + + if ( !req.boundParams.exercise?.isCorrection ) { + return req.session.sendResponse(res, StatusCodes.BAD_REQUEST, undefined, 'This exercise is not a correction', DojoStatusCode.EXERCISE_CORRECTION_NOT_EXIST); + } + + if ( SharedConfig.production ) { //Disable in dev env because gitlab dev group is private and we can't change visibility of sub projects + await GitlabManager.changeRepositoryVisibility(req.boundParams.exercise.gitlabId, 'private'); + } + + await db.exercise.update({ + where: { + id: req.boundParams.exercise.id + }, + data : { + correctionCommit : Prisma.DbNull, + correctionDescription: null + } + }); + + return req.session.sendResponse(res, StatusCodes.OK); + } }