diff --git a/ExpressAPI/src/controllers/Session.ts b/ExpressAPI/src/controllers/Session.ts index 18d02a63fc5486fa200dfe1ddcc419ce7b95e939..ff9a4fcd33c8907b7f1292ab55ebfcd276dd4c1b 100644 --- a/ExpressAPI/src/controllers/Session.ts +++ b/ExpressAPI/src/controllers/Session.ts @@ -54,7 +54,11 @@ class Session { } catch {} return { - timestamp: (new Date()).toISOString(), code: code, description: descriptionOverride ? descriptionOverride : reasonPhrase, sessionToken: Session.getToken(profileJson), data: data + timestamp : (new Date()).toISOString(), + code : code, + description : descriptionOverride ? descriptionOverride : reasonPhrase, + sessionToken: Session.getToken(profileJson), + data : data }; } diff --git a/ExpressAPI/src/express/API.ts b/ExpressAPI/src/express/API.ts index f7cfe2a622c0d342194ab42bee4b807d2b57b1ee..d9040027335181ab03ad25d9cf4bb42cfc5ed49e 100644 --- a/ExpressAPI/src/express/API.ts +++ b/ExpressAPI/src/express/API.ts @@ -40,7 +40,8 @@ class API implements WorkerTask { run() { this.server = this.backend.listen(Config.api.port, '0.0.0.0', () => { const { - port, address + port, + address } = this.server!.address() as AddressInfo; logger.info(`Server started on http://${ address }:${ port }`); }); diff --git a/ExpressAPI/src/helpers/DojoValidators.ts b/ExpressAPI/src/helpers/DojoValidators.ts index 2648d0aeab27a070c615e6e8fb8cc9e318daec2e..7f9cdf4f5787b840678e5df6ed701620aa2c5279 100644 --- a/ExpressAPI/src/helpers/DojoValidators.ts +++ b/ExpressAPI/src/helpers/DojoValidators.ts @@ -46,24 +46,28 @@ class DojoValidators { }); readonly templateUrlValidator = this.toValidatorSchemaOptions({ - bail: true, errorMessage: 'Template doesn\'t exist or you don\'t have access to it', options: (value, { - req, path - }) => { - return new Promise((resolve, reject) => { - const template = this.getParamValue(req, path); - if ( template ) { - GitlabManager.checkTemplateAccess(template, req).then((templateAccess) => { - templateAccess !== StatusCodes.OK ? reject() : resolve(true); - }); - } - resolve(true); - }); - } + bail : true, + errorMessage: 'Template doesn\'t exist or you don\'t have access to it', + options : (value, { + req, + path + }) => { + return new Promise((resolve, reject) => { + const template = this.getParamValue(req, path); + if ( template ) { + GitlabManager.checkTemplateAccess(template, req).then((templateAccess) => { + templateAccess !== StatusCodes.OK ? reject() : resolve(true); + }); + } + resolve(true); + }); + } }); readonly templateUrlSanitizer = this.toValidatorSchemaOptions({ options: (value, { - req, path + req, + path }) => { try { const template = this.getParamValue(req, path); diff --git a/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts b/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts index 84325a559cf1c816d23b36295c9ce4a5d4be5251..9315569e912f7acb2ef0084bf926e90c0d56d9a0 100644 --- a/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts +++ b/ExpressAPI/src/helpers/Prisma/Extensions/UserResultExtension.ts @@ -9,16 +9,19 @@ export default Prisma.defineExtension(client => { return client.$extends({ result: { user: { - isTeachingStaff : { + isTeachingStaff: { needs: { role: true - }, compute(user) { + }, + compute(user) { return Config.permissions.teachingStaff.includes(user.role!); } - }, gitlabProfile: { + }, + gitlabProfile : { needs: { gitlabId: true - }, compute(user) { + }, + compute(user) { return new LazyVal<GitlabUser | undefined>(() => { return GitlabManager.getUserById(user.gitlabId); }); diff --git a/ExpressAPI/src/managers/EnonceManager.ts b/ExpressAPI/src/managers/EnonceManager.ts index 0a6606beb5cae99804a3636fc605d93ee67e5ad2..7c8b612cae69bebb9de77125719c639e424054d5 100644 --- a/ExpressAPI/src/managers/EnonceManager.ts +++ b/ExpressAPI/src/managers/EnonceManager.ts @@ -17,9 +17,10 @@ class EnonceManager { async getByName(name: string, include: Prisma.EnonceInclude | undefined = undefined): Promise<Enonce | undefined> { return await db.enonce.findUnique({ - where : { + where : { name: name - }, include: include + }, + include: include }) as unknown as Enonce ?? undefined; } diff --git a/ExpressAPI/src/managers/ExerciceManager.ts b/ExpressAPI/src/managers/ExerciceManager.ts index bcf0990c5b0f6e8223dfc9ca1496e0db504296f1..698e16f2da86c1776b636af0b70a4faa9b00de38 100644 --- a/ExpressAPI/src/managers/ExerciceManager.ts +++ b/ExpressAPI/src/managers/ExerciceManager.ts @@ -6,9 +6,10 @@ import db from '../helpers/DatabaseHelper'; class ExerciceManager { async get(id: string, include: Prisma.ExerciceInclude | undefined = undefined): Promise<Exercice | undefined> { return await db.exercice.findUnique({ - where : { + where : { id: id - }, include: include + }, + include: include }) as unknown as Exercice ?? undefined; } } diff --git a/ExpressAPI/src/managers/GitlabManager.ts b/ExpressAPI/src/managers/GitlabManager.ts index b1639775454dccf1c105290ab8c63d9aa9dbe63c..6aa86c56055b509008a619aec678375c712d70b5 100644 --- a/ExpressAPI/src/managers/GitlabManager.ts +++ b/ExpressAPI/src/managers/GitlabManager.ts @@ -50,7 +50,14 @@ class GitlabManager { async createRepository(name: string, description: string, visibility: string, initializeWithReadme: boolean, namespace: number, sharedRunnersEnabled: boolean, wikiEnabled: boolean, import_url: string): Promise<GitlabRepository> { const response = await axios.post<GitlabRepository>(this.getApiUrl(GitlabRoutes.REPOSITORY_CREATE), { - name: name, description: description, import_url: import_url, initialize_with_readme: initializeWithReadme, namespace_id: namespace, shared_runners_enabled: sharedRunnersEnabled, visibility: visibility, wiki_enabled: wikiEnabled + name : name, + description : description, + import_url : import_url, + initialize_with_readme: initializeWithReadme, + namespace_id : namespace, + shared_runners_enabled: sharedRunnersEnabled, + visibility : visibility, + wiki_enabled : wikiEnabled }); return response.data; @@ -58,7 +65,11 @@ class GitlabManager { async forkRepository(forkId: number, name: string, path: string, description: string, visibility: string, namespace: number): Promise<GitlabRepository> { const response = await axios.post<GitlabRepository>(this.getApiUrl(GitlabRoutes.REPOSITORY_FORK).replace('{{id}}', String(forkId)), { - name: name, path: path, description: description, namespace_id: namespace, visibility: visibility + name : name, + path : path, + description : description, + namespace_id: namespace, + visibility : visibility }); return response.data; @@ -76,7 +87,8 @@ class GitlabManager { async addRepositoryMember(repoId: number, userId: number, accessLevel: GitlabAccessLevel): Promise<GitlabMember> { const response = await axios.post<GitlabMember>(this.getApiUrl(GitlabRoutes.REPOSITORY_MEMBER_ADD).replace('{{id}}', String(repoId)), { - user_id: userId, access_level: accessLevel + user_id : userId, + access_level: accessLevel }); return response.data; @@ -84,7 +96,11 @@ class GitlabManager { async addRepositoryVariable(repoId: number, key: string, value: string, isProtected: boolean, isMasked: boolean): Promise<GitlabMember> { const response = await axios.post<GitlabMember>(this.getApiUrl(GitlabRoutes.REPOSITORY_VARIABLES_ADD).replace('{{id}}', String(repoId)), { - key: key, variable_type: 'env_var', value: value, protected: isProtected, masked: isMasked + key : key, + variable_type: 'env_var', + value : value, + protected : isProtected, + masked : isMasked }); return response.data; @@ -105,7 +121,8 @@ class GitlabManager { // Check if the user and dojo are members (with at least reporter access) of the project const members = await this.getRepositoryMembers(idOrNamespace); const isUsersAtLeastReporter = { - user: false, dojo: false + user: false, + dojo: false }; members.forEach(member => { if ( member.access_level >= GitlabAccessLevel.REPORTER ) { @@ -122,7 +139,11 @@ class GitlabManager { async protectBranch(repoId: number, branchName: string, allowForcePush: boolean, allowedToMerge: GitlabAccessLevel, allowedToPush: GitlabAccessLevel, allowedToUnprotect: GitlabAccessLevel): Promise<GitlabMember> { const response = await axios.post<GitlabMember>(this.getApiUrl(GitlabRoutes.REPOSITORY_BRANCHES_PROTECT).replace('{{id}}', String(repoId)), { - name: branchName, allow_force_push: allowForcePush, merge_access_level: allowedToMerge.valueOf(), push_access_level: allowedToPush.valueOf(), unprotect_access_level: allowedToUnprotect.valueOf() + name : branchName, + allow_force_push : allowForcePush, + merge_access_level : allowedToMerge.valueOf(), + push_access_level : allowedToPush.valueOf(), + unprotect_access_level: allowedToUnprotect.valueOf() }); return response.data; @@ -131,7 +152,10 @@ class GitlabManager { async getRepositoryTree(repoId: number, recursive: boolean = true, branch: string = 'main'): Promise<Array<GitlabTreeFile>> { let address: string | undefined = this.getApiUrl(GitlabRoutes.REPOSITORY_TREE).replace('{{id}}', String(repoId)); let params: any = { - pagination: 'keyset', recursive: recursive, per_page: 100, ref: branch + pagination: 'keyset', + recursive : recursive, + per_page : 100, + ref : branch }; let results: Array<GitlabTreeFile> = []; diff --git a/ExpressAPI/src/managers/UserManager.ts b/ExpressAPI/src/managers/UserManager.ts index bf2e7a5212d091a9a1db6f2b5239bcae9246b7b2..615cbcb37cb5c5b6ec06731c50a1acd391260956 100644 --- a/ExpressAPI/src/managers/UserManager.ts +++ b/ExpressAPI/src/managers/UserManager.ts @@ -7,25 +7,28 @@ import { User } from '../types/DatabaseTypes'; class UserManager { async getByMail(mail: string, include: Prisma.UserInclude | undefined = undefined): Promise<User | undefined> { return await db.user.findUnique({ - where : { + where : { mail: mail - }, include: include + }, + include: include }) as unknown as User ?? undefined; } async getById(id: number, include: Prisma.UserInclude | undefined = undefined): Promise<User | undefined> { return await db.user.findUnique({ - where : { + where : { id: id - }, include: include + }, + include: include }) as unknown as User ?? undefined; } async getByGitlabId(gitlabId: number, returnIdIfUndefined: boolean = true, include: Prisma.UserInclude | undefined = undefined): Promise<User | number | undefined> { return await db.user.findUnique({ - where : { + where : { gitlabId: gitlabId - }, include: include + }, + include: include }) as unknown as User ?? (returnIdIfUndefined ? gitlabId : undefined); } @@ -35,7 +38,8 @@ class UserManager { if ( typeof user === 'number' && createIfNotExist ) { user = (await db.user.create({ data: { - firstname: gitlabUser.name, gitlabId: gitlabUser.id + firstname: gitlabUser.name, + gitlabId : gitlabUser.id } })).id; } diff --git a/ExpressAPI/src/middlewares/ParamsCallbackManager.ts b/ExpressAPI/src/middlewares/ParamsCallbackManager.ts index c7893d6f85fcfe4ba88fc7d67cbd0bf827466b6b..64a7bda72a9445ce4b755b4e48013fe5df57c3b9 100644 --- a/ExpressAPI/src/middlewares/ParamsCallbackManager.ts +++ b/ExpressAPI/src/middlewares/ParamsCallbackManager.ts @@ -27,18 +27,22 @@ class ParamsCallbackManager { initBoundParams(req: express.Request) { if ( !req.boundParams ) { req.boundParams = { - enonce: undefined, exercice: undefined + enonce : undefined, + exercice: undefined }; } } register(backend: Express) { this.listenParam('enonceNameOrUrl', backend, (EnonceManager.get as GetFunction).bind(EnonceManager), [ { - exercices: true, staff: true + exercices: true, + staff : true } ], 'enonce'); this.listenParam('exerciceId', backend, (ExerciceManager.get as GetFunction).bind(ExerciceManager), [ { - enonce: true, members: true, results: true + enonce : true, + members: true, + results: true } ], 'exercice'); } } diff --git a/ExpressAPI/src/routes/EnonceRoutes.ts b/ExpressAPI/src/routes/EnonceRoutes.ts index 6d371861c6845c1d5bbbcca7d28d918ac92a3b35..ddff650df3e4330e579b4d086ba4b3a86d2bb35c 100644 --- a/ExpressAPI/src/routes/EnonceRoutes.ts +++ b/ExpressAPI/src/routes/EnonceRoutes.ts @@ -24,12 +24,19 @@ import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibil class EnonceRoutes implements RoutesManager { private readonly enonceValidator: ExpressValidator.Schema = { - name : { - trim: true, notEmpty: true - }, members : { - trim: true, notEmpty: true, customSanitizer: DojoValidators.jsonSanitizer - }, template: { - trim: true, custom: DojoValidators.templateUrlValidator, customSanitizer: DojoValidators.templateUrlSanitizer + name : { + trim : true, + notEmpty: true + }, + members : { + trim : true, + notEmpty : true, + customSanitizer: DojoValidators.jsonSanitizer + }, + template: { + trim : true, + custom : DojoValidators.templateUrlValidator, + customSanitizer: DojoValidators.templateUrlSanitizer } }; @@ -102,12 +109,20 @@ class EnonceRoutes implements RoutesManager { const enonce: Enonce = await db.enonce.create({ data: { - name: repository.name, gitlabId: repository.id, gitlabLink: repository.web_url, gitlabCreationInfo: repository as unknown as Prisma.JsonObject, gitlabLastInfo: repository as unknown as Prisma.JsonObject, gitlabLastInfoDate: new Date(), staff: { + name : repository.name, + gitlabId : repository.id, + gitlabLink : repository.web_url, + gitlabCreationInfo: repository as unknown as Prisma.JsonObject, + gitlabLastInfo : repository as unknown as Prisma.JsonObject, + gitlabLastInfoDate: new Date(), + staff : { connectOrCreate: [ ...params.members.map(gitlabUser => { return { - create : { - gitlabId: gitlabUser.id, firstname: gitlabUser.name - }, where: { + create: { + gitlabId : gitlabUser.id, + firstname: gitlabUser.name + }, + where : { gitlabId: gitlabUser.id } }; @@ -133,11 +148,12 @@ class EnonceRoutes implements RoutesManager { await GitlabManager.changeRepositoryVisibility(req.boundParams.enonce!.gitlabId, publish ? GitlabVisibility.INTERNAL : GitlabVisibility.PRIVATE); await db.enonce.update({ - where : { + where: { name: req.boundParams.enonce!.name - }, data: { - published: publish - } + }, + data : { + published: publish + } }); req.session.sendResponse(res, StatusCodes.OK); diff --git a/ExpressAPI/src/routes/ExerciceRoutes.ts b/ExpressAPI/src/routes/ExerciceRoutes.ts index bb736cd4971a2aba5623ef547a5dabecf88603da..1300354945dde7391b4faf8502689f38498061d7 100644 --- a/ExpressAPI/src/routes/ExerciceRoutes.ts +++ b/ExpressAPI/src/routes/ExerciceRoutes.ts @@ -29,7 +29,9 @@ import hjson from 'hjson'; class ExerciceRoutes implements RoutesManager { private readonly exerciceValidator: ExpressValidator.Schema = { members: { - trim: true, notEmpty: true, customSanitizer: DojoValidators.jsonSanitizer + trim : true, + notEmpty : true, + customSanitizer: DojoValidators.jsonSanitizer } }; @@ -97,12 +99,23 @@ class ExerciceRoutes implements RoutesManager { const exercice: Exercice = await db.exercice.create({ data: { - id: exerciceId, enonceName: enonce.name, name: repository.name, secret: secret, gitlabId: repository.id, gitlabLink: repository.web_url, gitlabCreationInfo: repository as unknown as Prisma.JsonObject, gitlabLastInfo: repository as unknown as Prisma.JsonObject, gitlabLastInfoDate: new Date(), members: { + id : exerciceId, + enonceName : enonce.name, + name : repository.name, + secret : secret, + gitlabId : repository.id, + gitlabLink : repository.web_url, + gitlabCreationInfo: repository as unknown as Prisma.JsonObject, + gitlabLastInfo : repository as unknown as Prisma.JsonObject, + gitlabLastInfoDate: new Date(), + members : { connectOrCreate: [ ...params.members.map(gitlabUser => { return { - create : { - gitlabId: gitlabUser.id, firstname: gitlabUser.name - }, where: { + create: { + gitlabId : gitlabUser.id, + firstname: gitlabUser.name + }, + where : { gitlabId: gitlabUser.id } }; @@ -152,7 +165,9 @@ class ExerciceRoutes implements RoutesManager { })); return req.session.sendResponse(res, StatusCodes.OK, { - enonce: (req.boundParams.exercice as Exercice).enonce, enonceFile: dojoEnonceFile, immutable: immutableFiles + enonce : (req.boundParams.exercice as Exercice).enonce, + enonceFile: dojoEnonceFile, + immutable : immutableFiles }); } } diff --git a/ExpressAPI/src/routes/SessionRoutes.ts b/ExpressAPI/src/routes/SessionRoutes.ts index e3569e3e06d12ec8f22b9c32815124f4558bb50b..eb329d88b7ccfe6f026a755a7f213bee0ddf1cb7 100644 --- a/ExpressAPI/src/routes/SessionRoutes.ts +++ b/ExpressAPI/src/routes/SessionRoutes.ts @@ -12,10 +12,13 @@ import { User } from '../types/DatabaseTypes'; class SessionRoutes implements RoutesManager { private readonly loginValidator: ExpressValidator.Schema = { - user : { - trim: true, notEmpty: true - }, password: { - trim: true, notEmpty: true + user : { + trim : true, + notEmpty: true + }, + password: { + trim : true, + notEmpty: true } }; diff --git a/ExpressAPI/src/types/DatabaseTypes.ts b/ExpressAPI/src/types/DatabaseTypes.ts index 50443639229d30eee65150b3f98ee5a130fb7ece..4627dcb73f3d36015985266c0c57ff7fbcb68453 100644 --- a/ExpressAPI/src/types/DatabaseTypes.ts +++ b/ExpressAPI/src/types/DatabaseTypes.ts @@ -8,12 +8,15 @@ const userBase = Prisma.validator<Prisma.UserArgs>()({ }); const enonceBase = Prisma.validator<Prisma.EnonceArgs>()({ include: { - exercices: true, staff: true + exercices: true, + staff : true } }); const exerciceBase = Prisma.validator<Prisma.ExerciceArgs>()({ include: { - enonce: true, members: true, results: true + enonce : true, + members: true, + results: true } }); const resultBase = Prisma.validator<Prisma.ResultArgs>()({