diff --git a/ExpressAPI/assets/OpenAPI/OpenAPI.yaml b/ExpressAPI/assets/OpenAPI/OpenAPI.yaml index ce850f1b013a4a1db1a046826bab542ce65690d6..ee331c56f8f99afbf3c871e03a38830d0e9e5224 100644 --- a/ExpressAPI/assets/OpenAPI/OpenAPI.yaml +++ b/ExpressAPI/assets/OpenAPI/OpenAPI.yaml @@ -303,9 +303,21 @@ paths: type: boolean default: false description: Whether or not to use the Sonar integration to validate the assignment and exercise solutions + language: + type: string + default: other + description: Main programming language of the assignment + examples: + - java + - python + - csharp + - js + - c + - other required: - name + - language - members responses: '200': @@ -445,6 +457,35 @@ paths: $ref: '#/components/schemas/User' default: $ref: '#/components/responses/ERROR' + /assignments/languages: + get: + tags: + - Assignment + summary: Get all supported languages for assignments + description: | + This route can be used to get the list of all supported programming languages for which an assignment can be created. + security: + - Clients_Token: [ ] + responses: + '200': + description: OK + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/DojoBackendResponse' + - type: object + properties: + data: + type: array + items: + type: string + '401': + $ref: '#/components/responses/UNAUTHORIZED' + '404': + $ref: '#/components/responses/NOT_FOUND' + default: + $ref: '#/components/responses/ERROR' /exercises/{exerciseId}/assignment: get: tags: diff --git a/ExpressAPI/prisma/migrations/20240311145203_add_language_to_assignment/migration.sql b/ExpressAPI/prisma/migrations/20240311145203_add_language_to_assignment/migration.sql index 94b1ce8d80cf6b7eadb879931946d9f9cb66df5f..e0ed08ccbd69cbb8462f21f6e0488398612be04c 100644 --- a/ExpressAPI/prisma/migrations/20240311145203_add_language_to_assignment/migration.sql +++ b/ExpressAPI/prisma/migrations/20240311145203_add_language_to_assignment/migration.sql @@ -1,2 +1,2 @@ -- AlterTable -ALTER TABLE `Assignment` ADD COLUMN `language` ENUM('abap', 'ada', 'asm', 'bash', 'bqn', 'c', 'caml', 'cloudformation', 'csharp', 'css', 'cuda', 'dart', 'delphi', 'docker', 'erlang', 'f', 'fsharp', 'flex', 'fortran', 'futhark', 'go', 'groovy', 'haskell', 'hepial', 'json', 'jsp', 'java', 'js', 'julia', 'kotlin', 'kubernetes', 'latex', 'lisp', 'lua', 'matlab', 'objc', 'ocaml', 'pascal', 'pearl', 'perl', 'php', 'postscript', 'powershell', 'prolog', 'promela', 'python', 'r', 'ruby', 'rust', 'scala', 'sql', 'smalltalk', 'swift', 'terraform', 'text', 'ts', 'tsql', 'typst', 'vba', 'vbnet', 'web', 'xml', 'yaml', 'other') NOT NULL DEFAULT 'other'; +ALTER TABLE `Assignment` ADD COLUMN `language` ENUM('abap', 'ada', 'asm', 'bash', 'bqn', 'c', 'caml', 'cloudformation', 'cpp', 'csharp', 'css', 'cuda', 'dart', 'delphi', 'docker', 'erlang', 'f', 'fsharp', 'flex', 'fortran', 'futhark', 'go', 'groovy', 'haskell', 'hepial', 'json', 'jsp', 'java', 'js', 'julia', 'kotlin', 'kubernetes', 'latex', 'lisp', 'lua', 'matlab', 'objc', 'ocaml', 'pascal', 'pearl', 'perl', 'php', 'postscript', 'powershell', 'prolog', 'promela', 'python', 'r', 'ruby', 'rust', 'scala', 'sql', 'smalltalk', 'swift', 'terraform', 'text', 'ts', 'tsql', 'typst', 'vba', 'vbnet', 'web', 'xml', 'yaml', 'other') NOT NULL DEFAULT 'other'; diff --git a/ExpressAPI/prisma/schema.prisma b/ExpressAPI/prisma/schema.prisma index 677ea6a8b91a917100b77ef7c858b2746cfad3fe..12188c2dd5b8b104ddfa6e0c76078b311972a18d 100644 --- a/ExpressAPI/prisma/schema.prisma +++ b/ExpressAPI/prisma/schema.prisma @@ -83,6 +83,7 @@ enum Language { c caml cloudformation + cpp csharp css cuda diff --git a/ExpressAPI/src/helpers/DojoValidators.ts b/ExpressAPI/src/helpers/DojoValidators.ts index 38465417c46274cff0e46ee3dbdc2929cb17f05b..85b50edbd61d3c77f93431274c5b2059a791e322 100644 --- a/ExpressAPI/src/helpers/DojoValidators.ts +++ b/ExpressAPI/src/helpers/DojoValidators.ts @@ -9,6 +9,7 @@ import Json5FileValidator from '../sha import ExerciseResultsFile from '../shared/types/Dojo/ExerciseResultsFile'; import ParamsCallbackManager from '../middlewares/ParamsCallbackManager'; import ExerciseManager from '../managers/ExerciseManager'; +import { Language } from '@prisma/client'; declare type DojoMeta = Meta & { @@ -134,6 +135,23 @@ class DojoValidators { }); } }); + + readonly supportedLanguageValidator = this.toValidatorSchemaOptions({ + bail : true, + errorMessage: 'Unsupported language', + options : (_value, { + req, + path + }) => { + return new Promise((resolve, reject) => { + const language = this.getParamValue(req, path) as string; + if ( language ) { + (Object.values(Language).includes(language as keyof typeof Language) ? resolve(true) : reject()); + } + reject(); + }); + } + }); } diff --git a/ExpressAPI/src/routes/AssignmentRoutes.ts b/ExpressAPI/src/routes/AssignmentRoutes.ts index 7b192fcf855065660c8a6ef36f168996b9606a76..d76f386e80502dfbcd2aa7fc505e1677977d4f89 100644 --- a/ExpressAPI/src/routes/AssignmentRoutes.ts +++ b/ExpressAPI/src/routes/AssignmentRoutes.ts @@ -15,7 +15,7 @@ import GitlabRepository from '../shared/types/Gitlab/GitlabReposit import { AxiosError, HttpStatusCode } from 'axios'; import logger from '../shared/logging/WinstonLogger'; import DojoValidators from '../helpers/DojoValidators'; -import { Prisma } from '@prisma/client'; +import { Language, Prisma } from '@prisma/client'; import db from '../helpers/DatabaseHelper'; import { Assignment } from '../types/DatabaseTypes'; import AssignmentManager from '../managers/AssignmentManager'; @@ -49,6 +49,11 @@ class AssignmentRoutes implements RoutesManager { notEmpty : true, isBoolean: true, }, + language : { + trim : true, + notEmpty: true, + custom : DojoValidators.supportedLanguageValidator + } }; private readonly assignmentAddCorrigeValidator: ExpressValidator.Schema = { @@ -60,6 +65,8 @@ class AssignmentRoutes implements RoutesManager { }; registerOnBackend(backend: Express) { + backend.get('/assignments/languages', this.getLanguages.bind(this)); + backend.get('/assignments/:assignmentNameOrUrl', SecurityMiddleware.check(true), this.getAssignment.bind(this)); backend.post('/assignments', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.assignmentValidator), this.createAssignment.bind(this)); @@ -90,7 +97,7 @@ class AssignmentRoutes implements RoutesManager { private async createAssignment(req: express.Request, res: express.Response) { const params: { - name: string, members: Array<GitlabUser>, template: string, useSonar: string + name: string, members: Array<GitlabUser>, template: string, useSonar: string, language: string } = req.body; const useSonar = params.useSonar === 'true'; @@ -159,6 +166,7 @@ class AssignmentRoutes implements RoutesManager { gitlabLastInfo : repository as unknown as Prisma.JsonObject, gitlabLastInfoDate: new Date(), useSonar : useSonar, + language : Language[params.language as keyof typeof Language], staff : { connectOrCreate: [ ...params.members.map(gitlabUser => { return { @@ -252,6 +260,10 @@ class AssignmentRoutes implements RoutesManager { } }; } + + private async getLanguages(req: express.Request, res: express.Response) { + req.session.sendResponse(res, StatusCodes.OK, Object.values(Language)); + } }