From 1ef8b8e830f9ad761a71a827ed3ac1ca03ea7324 Mon Sep 17 00:00:00 2001 From: "vincent.steinman" <vincent.steinmann@etu.hesge.ch> Date: Mon, 5 Feb 2024 19:10:22 +0100 Subject: [PATCH] start route --- ExpressAPI/prisma/schema.prisma | 2 +- ExpressAPI/src/managers/TagsManager.ts | 39 +++++++++++++ ExpressAPI/src/routes/TagsRoutes.ts | 70 +++++++++++++++++++++++ ExpressAPI/src/types/DatabaseTypes.ts | 9 ++- ExpressAPI/src/types/SecurityCheckType.ts | 1 + 5 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 ExpressAPI/src/managers/TagsManager.ts create mode 100644 ExpressAPI/src/routes/TagsRoutes.ts diff --git a/ExpressAPI/prisma/schema.prisma b/ExpressAPI/prisma/schema.prisma index 8d7143a..b5725fc 100644 --- a/ExpressAPI/prisma/schema.prisma +++ b/ExpressAPI/prisma/schema.prisma @@ -4,7 +4,7 @@ generator client { datasource db { provider = "mysql" - url = env("DATABASE_URL") + url = env("mysql://root:9buz7f312479g6234f1gnioubervw79b8z@localhost:59231/dojo") } enum UserRole { diff --git a/ExpressAPI/src/managers/TagsManager.ts b/ExpressAPI/src/managers/TagsManager.ts new file mode 100644 index 0000000..f404fad --- /dev/null +++ b/ExpressAPI/src/managers/TagsManager.ts @@ -0,0 +1,39 @@ +import { Prisma } from '@prisma/client'; +import { Assignment, User } from '../types/DatabaseTypes'; +import db from '../helpers/DatabaseHelper'; + + +class TagsManager { + async isUserAllowedToAccessTag(tag: Tags, user: User): Promise<boolean> { + if ( !tag.staff ) { + tag.staff = await db.assignment.findUnique({ + where: { + name: tag.name + } + }).staff() ?? []; + } + return tag.staff.findIndex(staff => staff.id === user.id) !== -1; + } + + async getByName(name: string, include: Prisma.TagInclude | undefined = undefined): Promise<Tag | undefined> { + return await db.assignment.findUnique({ + where : { + name: name + }, include: include + }) as unknown as Tag ?? undefined; + } + + getByGitlabLink(gitlabLink: string, include: Prisma.AssignmentInclude | undefined = undefined): Promise<Assignment | undefined> { + const name = gitlabLink.replace('.git', '').split('/').pop()!; + + return this.getByName(name, include); + } + + get(nameOrUrl: string, include: Prisma.AssignmentInclude | undefined = undefined): Promise<Assignment | undefined> { + // We can use the same function for both name and url because the name is the last part of the url and the name extraction from the url doesn't corrupt the name + return this.getByGitlabLink(nameOrUrl, include); + } +} + + +export default new TagManager(); diff --git a/ExpressAPI/src/routes/TagsRoutes.ts b/ExpressAPI/src/routes/TagsRoutes.ts new file mode 100644 index 0000000..6c7fd60 --- /dev/null +++ b/ExpressAPI/src/routes/TagsRoutes.ts @@ -0,0 +1,70 @@ +import { Express } from 'express-serve-static-core'; +import express from 'express'; +import * as ExpressValidator from 'express-validator'; +import { StatusCodes } from 'http-status-codes'; +import RoutesManager from '../express/RoutesManager'; +import ParamsValidatorMiddleware from '../middlewares/ParamsValidatorMiddleware'; +import SecurityMiddleware from '../middlewares/SecurityMiddleware'; +import SecurityCheckType from '../types/SecurityCheckType'; +import GitlabUser from '../shared/types/Gitlab/GitlabUser'; +import GitlabManager from '../managers/GitlabManager'; +import Config from '../config/Config'; +import GitlabMember from '../shared/types/Gitlab/GitlabMember'; +import GitlabAccessLevel from '../shared/types/Gitlab/GitlabAccessLevel'; +import GitlabRepository from '../shared/types/Gitlab/GitlabRepository'; +import { AxiosError, HttpStatusCode } from 'axios'; +import logger from '../shared/logging/WinstonLogger'; +import DojoValidators from '../helpers/DojoValidators'; +import { Prisma } from '@prisma/client'; +import db from '../helpers/DatabaseHelper'; +import { Assignment } from '../types/DatabaseTypes'; +import AssignmentManager from '../managers/AssignmentManager'; +import GitlabVisibility from '../shared/types/Gitlab/GitlabVisibility'; +import fs from 'fs'; +import path from 'path'; +import SharedAssignmentHelper from '../shared/helpers/Dojo/SharedAssignmentHelper'; +import GlobalHelper from '../helpers/GlobalHelper'; +import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode'; +import TagsManager from 'src/managers/TagsManager'; + + +class TagRoutes implements RoutesManager { + private readonly tagsValidator: ExpressValidator.Schema = { + name: { + trim: true, + notEmpty: true + }, + type: { + custom: { + options: (value: string) => Object.values(TagType).includes(value), + errorMessage: 'Invalid tag type' + } + } + }; + + registerOnBackend(backend: Express) { + backend.post('/tags', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.tagsValidator), this.addTag.bind(this)); + backend.delete('/tags', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.tagsValidator), this.deleteTag.bind(this)); + backend.get('/tags/proposals', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.tagsValidator), this.getSubmittedTag.bind(this)); + backend.post('/tags/proposals', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.tagsValidator), this.SubmitTag.bind(this)); + backend.patch('/tags/proposals/{tagProposalName}', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), ParamsValidatorMiddleware.validate(this.tagsValidator), this.validateTag.bind(this)); + } + + private async addTag(req: express.Request, res: express.Response) { + + } + private async deleteTag(req: express.Request, res: express.Response) { + + } + private async getSubmittedTag(req: express.Request, res: express.Response) { + + } + private async SubmitTag(req: express.Request, res: express.Response) { + + } + private async validateTag(req: express.Request, res: express.Response) { + + } +} + +export default new TagRoutes(); diff --git a/ExpressAPI/src/types/DatabaseTypes.ts b/ExpressAPI/src/types/DatabaseTypes.ts index 011d2ef..716f30b 100644 --- a/ExpressAPI/src/types/DatabaseTypes.ts +++ b/ExpressAPI/src/types/DatabaseTypes.ts @@ -24,6 +24,12 @@ const resultBase = Prisma.validator<Prisma.ResultDefaultArgs>()({ exercise: true } }); +// const tagsBase = Prisma.validator<Prisma.TagsDefaultArgs>()({ +// include: { +// name: true, +// type: true, +// } +// }); export type User = Prisma.UserGetPayload<typeof userBase> & { @@ -37,4 +43,5 @@ export type Exercise = Prisma.ExerciseGetPayload<typeof exerciseBase> & { export type Assignment = Prisma.AssignmentGetPayload<typeof assignmentBase> & { corrections: LazyVal<Array<Exercise>> } -export type Result = Prisma.ResultGetPayload<typeof resultBase> \ No newline at end of file +export type Result = Prisma.ResultGetPayload<typeof resultBase> +// export type Tags = Prisma.ResultGetPayload<typeof tagsBase> \ No newline at end of file diff --git a/ExpressAPI/src/types/SecurityCheckType.ts b/ExpressAPI/src/types/SecurityCheckType.ts index 3a0b733..17d026a 100644 --- a/ExpressAPI/src/types/SecurityCheckType.ts +++ b/ExpressAPI/src/types/SecurityCheckType.ts @@ -1,5 +1,6 @@ enum SecurityCheckType { TEACHING_STAFF = 'teachingStaff', + ADMIN = 'admin', ASSIGNMENT_STAFF = 'assignmentStaff', ASSIGNMENT_IS_PUBLISHED = 'assignmentIsPublished', EXERCISE_SECRET = 'exerciseSecret', -- GitLab