diff --git a/ExpressAPI/prisma/schema.prisma b/ExpressAPI/prisma/schema.prisma index 8d7143ac874fd4324ce2d1c043f65c2f6e27ba68..b5725fc3c15b590bfb632338f2a681ee60c571ff 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 0000000000000000000000000000000000000000..f404fadc6a264a6c89c71b4e0f883c374985c07a --- /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 0000000000000000000000000000000000000000..6c7fd6067c81a33cc7a76fda5c50ce87160c1fcc --- /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 011d2efc5643f66cefb4da435b26e4579accfc32..716f30bc52acfa037364c9d91ef1dc81e54022d2 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 3a0b733103af4604e10f917ec3edc4c7f56b3b66..17d026a253327907355176e847a6ac4a7047922f 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',