diff --git a/api/__tests__/routes/region.test.ts b/api/__tests__/routes/region.test.ts new file mode 100644 index 000000000..b5eb797ea --- /dev/null +++ b/api/__tests__/routes/region.test.ts @@ -0,0 +1,477 @@ +import { describe, test } from "@jest/globals"; +import { AuthenticationLevel, Testrunner } from "../utilities/Testrunner"; +import request from "supertest"; +import app from "../../src/main"; +import { + deleteDatabaseData, + initialiseDatabase, + restoreTables, +} from "../mock/database"; +import { + badRequestResponse, + forbiddenResponse, + notFoundResponse, +} from "../utilities/constants"; + +describe("Region tests", () => { + let runner: Testrunner; + + beforeAll(async () => { + const server = request(app); + runner = new Testrunner(server); + + await deleteDatabaseData(); + await initialiseDatabase(); + + runner.authLevel(AuthenticationLevel.SUPER_STUDENT); + }); + + afterEach(async () => { + await restoreTables(); + }); + + describe("Succesful requests", () => { + test("POST /region", async () => { + const newRegion = { + name: "new Region", + }; + + const expectedRegion = { + name: "new Region", + deleted: false, + users: [], + }; + + await runner.post({ + url: "/region", + data: newRegion, + expectedResponse: expectedRegion, + }); + }); + + test("GET /region", async () => { + const expected = [ + { + deleted: false, + id: 1, + name: "Region 1", + users: [ + { + id: 1, + region_id: 1, + user: { + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }, + ], + }, + { + deleted: false, + id: 2, + name: "Region 2", + users: [ + { + id: 2, + region_id: 2, + user: { + address_id: 2, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "superstudent@trottoir.be", + first_name: "Toon", + id: 2, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Superstudent", + phone: "9876543210", + student: false, + super_student: true, + }, + user_id: 2, + }, + ], + }, + { deleted: false, id: 3, name: "Region 3", users: [] }, + ]; + + await runner.get({ url: "/region", expectedData: expected }); + }); + + test("GET /region/:id", async () => { + const expected = [ + { id: 3, name: "Region 3", deleted: false, users: [] }, + ]; + + await runner.get({ url: "/region/3", expectedData: expected }); + }); + + test("PATCH /region/:id", async () => { + const newRegion = { + id: 3, + name: "Updated Region 3", + }; + + const expectedRegion = { + id: 3, + name: "Updated Region 3", + deleted: false, + users: [], + }; + + await runner.patch({ + url: "/region/3", + data: newRegion, + expectedResponse: expectedRegion, + }); + }); + + test("SOFT DELETE /region/:id", async () => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + await runner.delete({ url: "/region/1" }); + + // verify that the region is soft deleted (admin) + const expected = [ + { + deleted: true, + id: 1, + name: "Region 1", + users: [ + { + id: 1, + region_id: 1, + user: { + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }, + ], + }, + { + deleted: false, + id: 2, + name: "Region 2", + users: [ + { + id: 2, + region_id: 2, + user: { + address_id: 2, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "superstudent@trottoir.be", + first_name: "Toon", + id: 2, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Superstudent", + phone: "9876543210", + student: false, + super_student: true, + }, + user_id: 2, + }, + ], + }, + { deleted: false, id: 3, name: "Region 3", users: [] }, + ]; + await runner.get({ + url: "/region?deleted=true", + expectedData: expected, + }); + + runner.authLevel(AuthenticationLevel.SUPER_STUDENT); + // verify that the region is soft deleted (superstudent) + const expectedSuperStudent = [ + { + deleted: false, + id: 2, + name: "Region 2", + users: [ + { + id: 2, + region_id: 2, + user: { + address_id: 2, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "superstudent@trottoir.be", + first_name: "Toon", + id: 2, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Superstudent", + phone: "9876543210", + student: false, + super_student: true, + }, + user_id: 2, + }, + ], + }, + { deleted: false, id: 3, name: "Region 3", users: [] }, + ]; + await runner.get({ + url: "/region", + expectedData: expectedSuperStudent, + }); + }); + + test("DELETE /region/:id", async () => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + const regionHard = { + hardDelete: true, + }; + await runner.delete({ url: "/region/3", data: regionHard }); + + // verify that the region is truly deleted + const expected = [ + { + deleted: false, + id: 1, + name: "Region 1", + users: [ + { + id: 1, + region_id: 1, + user: { + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }, + ], + }, + { + deleted: false, + id: 2, + name: "Region 2", + users: [ + { + id: 2, + region_id: 2, + user: { + address_id: 2, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "superstudent@trottoir.be", + first_name: "Toon", + id: 2, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Superstudent", + phone: "9876543210", + student: false, + super_student: true, + }, + user_id: 2, + }, + ], + }, + ]; + await runner.get({ + url: "/region?deleted=true", + expectedData: expected, + }); + }); + }); + + describe("Unsuccesful requests", () => { + let runner: Testrunner; + beforeAll(async () => { + const server = request(app); + runner = new Testrunner(server); + + await deleteDatabaseData(); + await initialiseDatabase(); + }); + + describe("Must be correctly authorized to use any path", () => { + const newRegion = { + name: "new Region", + }; + + describe("Cannot reach any path without authorisation", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.UNAUTHORIZED); + }); + + test("Cannot reach GET /region", async () => { + await runner.get({ + url: "/region", + expectedData: [forbiddenResponse], + statusCode: 403, + }); + }); + + test("Cannot reach GET /region/:id", async () => { + await runner.get({ + url: "/region/1", + expectedData: [forbiddenResponse], + statusCode: 403, + }); + }); + + test("Cannot reach POST /region", async () => { + await runner.post({ + url: "/region", + data: newRegion, + expectedResponse: forbiddenResponse, + statusCode: 403, + }); + }); + + test("Cannot reach PATCH /region/:id", async () => { + await runner.patch({ + url: "/region/1", + data: newRegion, + expectedResponse: forbiddenResponse, + statusCode: 403, + }); + }); + + test("Cannot reach DELETE /region/:id", async () => { + await runner.delete({ + url: "/region/1", + statusCode: 403, + }); + }); + }); + + describe("Cannot reach any path as a student", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.STUDENT); + }); + + test("Cannot reach GET /region", async () => { + await runner.get({ + url: "/region", + expectedData: [forbiddenResponse], + statusCode: 403, + }); + }); + + test("Cannot reach POST /region", async () => { + await runner.post({ + url: "/region", + data: newRegion, + expectedResponse: forbiddenResponse, + statusCode: 403, + }); + }); + + test("Cannot reach PATCH /region/:id", async () => { + await runner.patch({ + url: "/region/1", + data: newRegion, + expectedResponse: forbiddenResponse, + statusCode: 403, + }); + }); + + test("Cannot reach DELETE /region/:id", async () => { + await runner.delete({ + url: "/region/1", + statusCode: 403, + }); + }); + }); + + describe("The requested path must exist", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + }); + + test("Find a nonexistent region", async () => { + await runner.get({ + url: "/region/50", + expectedData: [notFoundResponse], + statusCode: 404, + }); + }); + + test("Update a nonexistent region", async () => { + await runner.patch({ + url: "/region/50", + data: newRegion, + expectedResponse: notFoundResponse, + statusCode: 404, + }); + }); + test("Delete a nonexistent region", async () => { + await runner.delete({ url: "/region/50", statusCode: 404 }); + }); + }); + + describe("The type of region id must be correct", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + }); + + test("GET request", async () => { + await runner.get({ + url: "/region/wrongtype", + expectedData: [badRequestResponse], + statusCode: 400, + }); + }); + + test("PATCH request", async () => { + const newRegion = { + foo: "wrong name Region", + }; + + await runner.patch({ + url: "/region/wrongtype", + data: newRegion, + expectedResponse: badRequestResponse, + statusCode: 400, + }); + }); + + test("DELETE request", async () => { + await runner.delete({ + url: "/region/wrongtype", + statusCode: 400, + }); + }); + }); + }); + }); + + afterAll(() => { + app.close(); + }); +}); diff --git a/api/__tests__/routes/user_region.test.ts b/api/__tests__/routes/user_region.test.ts new file mode 100644 index 000000000..52b90f2b2 --- /dev/null +++ b/api/__tests__/routes/user_region.test.ts @@ -0,0 +1,412 @@ +import { describe, test } from "@jest/globals"; +import { AuthenticationLevel, Testrunner } from "../utilities/Testrunner"; +import request from "supertest"; +import app from "../../src/main"; +import { + deleteDatabaseData, + initialiseDatabase, + restoreTables, +} from "../mock/database"; +import { + badRequestResponse, + forbiddenResponse, + methodNotAllowedResponse, + notFoundResponse, +} from "../utilities/constants"; + +describe("User_region tests", () => { + let runner: Testrunner; + + beforeAll(async () => { + const server = request(app); + runner = new Testrunner(server); + + await deleteDatabaseData(); + await initialiseDatabase(); + + runner.authLevel(AuthenticationLevel.SUPER_STUDENT); + }); + + afterEach(async () => { + await restoreTables(); + }); + + describe("Succesful requests", () => { + test("POST /user_region", async () => { + const new_user_region = { + user_id: 1, + region_id: 3, + }; + + const expected = { + region: { deleted: false, id: 3, name: "Region 3" }, + region_id: 3, + user: { + address: { + city: "Sydney", + id: 1, + latitude: -33.865143, + longitude: 151.2099, + number: 42, + street: "Wallaby Way", + zip_code: 2000, + }, + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }; + await runner.post({ + url: "/user_region", + data: new_user_region, + expectedResponse: expected, + }); + + //check if user is added to region + + const expectedRegion = [ + { + deleted: false, + id: 3, + name: "Region 3", + users: [ + { + id: 3, + region_id: 3, + user: { + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }, + ], + }, + ]; + + await runner.get({ + url: "/region/3", + expectedData: expectedRegion, + }); + }); + + test("GET /user_region", async () => { + const expected = [ + { + id: 1, + region: { deleted: false, id: 1, name: "Region 1" }, + region_id: 1, + user: { + address: { + city: "Sydney", + id: 1, + latitude: -33.865143, + longitude: 151.2099, + number: 42, + street: "Wallaby Way", + zip_code: 2000, + }, + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }, + { + id: 2, + region: { deleted: false, id: 2, name: "Region 2" }, + region_id: 2, + user: { + address: { + city: "Ghent", + id: 2, + latitude: 51.04732, + longitude: 3.7282, + number: 25, + street: "Sint-Pietersnieuwstraat", + zip_code: 9000, + }, + address_id: 2, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "superstudent@trottoir.be", + first_name: "Toon", + id: 2, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Superstudent", + phone: "9876543210", + student: false, + super_student: true, + }, + user_id: 2, + }, + ]; + + await runner.get({ url: "/user_region", expectedData: expected }); + }); + + test("GET /user_region/:id", async () => { + const expected = [ + { + id: 1, + region: { deleted: false, id: 1, name: "Region 1" }, + region_id: 1, + user: { + address: { + city: "Sydney", + id: 1, + latitude: -33.865143, + longitude: 151.2099, + number: 42, + street: "Wallaby Way", + zip_code: 2000, + }, + address_id: 1, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "student@trottoir.be", + first_name: "Dirk", + id: 1, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Student", + phone: "0123456789", + student: true, + super_student: false, + }, + user_id: 1, + }, + ]; + + await runner.get({ url: "/user_region/1", expectedData: expected }); + }); + + test("DELETE /user_region/:id", async () => { + await runner.delete({ url: "/user_region/1" }); + + // verify that the user_region is truly deleted + const expected = [ + { + id: 2, + region: { deleted: false, id: 2, name: "Region 2" }, + region_id: 2, + user: { + address: { + city: "Ghent", + id: 2, + latitude: 51.04732, + longitude: 3.7282, + number: 25, + street: "Sint-Pietersnieuwstraat", + zip_code: 9000, + }, + address_id: 2, + admin: false, + date_added: "2023-05-04T12:00:00.000Z", + deleted: false, + email: "superstudent@trottoir.be", + first_name: "Toon", + id: 2, + last_login: "2023-05-04T12:00:00.000Z", + last_name: "De Superstudent", + phone: "9876543210", + student: false, + super_student: true, + }, + user_id: 2, + }, + ]; + await runner.get({ + url: "/user_region", + expectedData: expected, + }); + }); + }); + + describe("Unsuccesful requests", () => { + let runner: Testrunner; + beforeAll(async () => { + const server = request(app); + runner = new Testrunner(server); + + await deleteDatabaseData(); + await initialiseDatabase(); + }); + + describe("Must be correctly authorized to use any path", () => { + const new_user_region = { + user_id: 1, + region_id: 3, + }; + + describe("Cannot reach any path without authorisation", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.UNAUTHORIZED); + }); + + test("Cannot reach GET /user_region", async () => { + await runner.get({ + url: "/user_region", + expectedData: [forbiddenResponse], + statusCode: 403, + }); + }); + + test("Cannot reach GET /user_region/:id", async () => { + await runner.get({ + url: "/user_region/1", + expectedData: [forbiddenResponse], + statusCode: 403, + }); + }); + + test("Cannot reach POST /user_region", async () => { + await runner.post({ + url: "/user_region", + data: new_user_region, + expectedResponse: forbiddenResponse, + statusCode: 403, + }); + }); + + test("Cannot reach DELETE /user_region/:id", async () => { + await runner.delete({ + url: "/user_region/1", + statusCode: 403, + }); + }); + }); + describe("Cannot reach any path as a student", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.STUDENT); + }); + + test("Cannot reach GET /user_region", async () => { + await runner.get({ + url: "/user_region", + expectedData: [forbiddenResponse], + statusCode: 403, + }); + }); + + test("Cannot reach POST /user_region", async () => { + await runner.post({ + url: "/user_region", + data: new_user_region, + expectedResponse: forbiddenResponse, + statusCode: 403, + }); + }); + + test("Cannot reach DELETE /user_region/:id", async () => { + await runner.delete({ + url: "/user_region/1", + statusCode: 403, + }); + }); + + test("Cannot reach PATCH /user_region/:id", async () => { + await runner.patch({ + url: "/user_region/1", + data: new_user_region, + expectedResponse: methodNotAllowedResponse, + statusCode: 405, + }); + }); + }); + }); + describe("The requested path must exist", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + }); + + test("Find a nonexistent user_region", async () => { + await runner.get({ + url: "/user_region/50", + expectedData: [notFoundResponse], + statusCode: 404, + }); + }); + + test("Delete a nonexistent user_region", async () => { + await runner.delete({ + url: "/user_region/50", + statusCode: 404, + }); + }); + }); + describe("The type of user_region id must be correct", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + }); + + test("GET request", async () => { + await runner.get({ + url: "/user_region/wrongtype", + expectedData: [badRequestResponse], + statusCode: 400, + }); + }); + + test("DELETE request", async () => { + await runner.delete({ + url: "/user_region/wrongtype", + statusCode: 400, + }); + }); + }); + + describe("Method has to be allowed", () => { + beforeEach(() => { + runner.authLevel(AuthenticationLevel.ADMINISTRATOR); + }); + + test("PATCH /user_region/:id", async () => { + const new_user_region = { + user_id: 1, + region_id: 2, + }; + + await runner.patch({ + url: "/user_region/1", + data: new_user_region, + expectedResponse: methodNotAllowedResponse, + statusCode: 405, + }); + }); + }); + }); + + afterAll(() => { + app.close(); + }); +}); diff --git a/api/src/routes/region.ts b/api/src/routes/region.ts index ad34d66d4..c66a28b0b 100644 --- a/api/src/routes/region.ts +++ b/api/src/routes/region.ts @@ -4,9 +4,9 @@ import { Parser } from "../parser"; import { prisma } from "../prisma"; import { Auth } from "../auth/auth"; import { Prisma } from "@selab-2/groep-1-orm"; -import RegionInclude = Prisma.RegionInclude; import { RegionValidator } from "../validators/region.validator"; import { Validator } from "../validators/validator"; +import RegionInclude = Prisma.RegionInclude; export class RegionRouting extends Routing { private static includes: RegionInclude = { @@ -19,6 +19,11 @@ export class RegionRouting extends Routing { @Auth.authorization({ superStudent: true }) async getAll(req: CustomRequest, res: express.Response) { + let deleted: boolean | undefined = false; + if (req.user?.admin && Parser.bool(req.query["deleted"], false)) { + deleted = undefined; + } + const result = await prisma.region.findMany({ take: Parser.number(req.query["take"], 1024), skip: Parser.number(req.query["skip"], 0), @@ -32,6 +37,7 @@ export class RegionRouting extends Routing { }, } : {}, + deleted: deleted, }, include: RegionRouting.includes, }); @@ -76,11 +82,22 @@ export class RegionRouting extends Routing { @Auth.authorization({ superStudent: true }) async deleteOne(req: CustomRequest, res: express.Response) { - await prisma.region.delete({ - where: { - id: Parser.number(req.params["id"]), - }, - }); + if (Parser.bool(req.body["hardDelete"], false)) { + await prisma.region.delete({ + where: { + id: Parser.number(req.params["id"]), + }, + }); + } else { + await prisma.region.update({ + data: { + deleted: true, + }, + where: { + id: Parser.number(req.params["id"]), + }, + }); + } return res.status(200).json({}); } diff --git a/api/src/validators/action.validator.ts b/api/src/validators/action.validator.ts index 3080bd2a0..e28f9e06c 100644 --- a/api/src/validators/action.validator.ts +++ b/api/src/validators/action.validator.ts @@ -26,15 +26,19 @@ export class ActionValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - description: Joi.string().trim().min(1), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + description: Joi.string().trim().min(1), + }), + }, + undefined, + { reqContext: true }, + ); } createOneValidator() { diff --git a/api/src/validators/address.validator.ts b/api/src/validators/address.validator.ts index 9ec3636dc..9969504f8 100644 --- a/api/src/validators/address.validator.ts +++ b/api/src/validators/address.validator.ts @@ -26,20 +26,24 @@ export class AddressValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - street: Joi.string().min(1), - city: Joi.string().min(1), - zip_code: Joi.number().positive(), - number: Joi.number().positive(), - longitude: Joi.number().min(-180).max(180), - latitude: Joi.number().min(-90).max(90), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + street: Joi.string().min(1), + city: Joi.string().min(1), + zip_code: Joi.number().positive(), + number: Joi.number().positive(), + longitude: Joi.number().min(-180).max(180), + latitude: Joi.number().min(-90).max(90), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/building.validator.ts b/api/src/validators/building.validator.ts index f218cd9f9..7aa412810 100644 --- a/api/src/validators/building.validator.ts +++ b/api/src/validators/building.validator.ts @@ -44,22 +44,26 @@ export class BuildingValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - name: Joi.string().min(1), - ivago_id: Joi.string().min(1), - address_id: Joi.number().positive(), - manual_id: Joi.number().positive(), - syndicus_id: Joi.number().positive(), - deleted: Joi.bool(), - hash: Joi.string().forbidden(), - expected_time: Joi.number().positive(), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + name: Joi.string().min(1), + ivago_id: Joi.string().min(1), + address_id: Joi.number().positive(), + manual_id: Joi.number().positive(), + syndicus_id: Joi.number().positive(), + deleted: Joi.bool(), + hash: Joi.string().forbidden(), + expected_time: Joi.number().positive(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/garbage.validator.ts b/api/src/validators/garbage.validator.ts index e651d1968..ee95f5ff7 100644 --- a/api/src/validators/garbage.validator.ts +++ b/api/src/validators/garbage.validator.ts @@ -40,17 +40,21 @@ export class GarbageValidator extends Validator { } updateOneValidator(): express.RequestHandler { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - pickup_time: Joi.date().iso(), - action_id: Joi.number().positive(), - building_id: Joi.number().positive(), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + pickup_time: Joi.date().iso(), + action_id: Joi.number().positive(), + building_id: Joi.number().positive(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator(): express.RequestHandler { diff --git a/api/src/validators/mailtemplate.validator.ts b/api/src/validators/mailtemplate.validator.ts index 8f2b7e8dc..9154ec5d5 100644 --- a/api/src/validators/mailtemplate.validator.ts +++ b/api/src/validators/mailtemplate.validator.ts @@ -34,17 +34,21 @@ export class MailTemplateValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - name: Joi.string().trim().min(1), - mail_subject: Joi.string().trim().min(1), - content: Joi.string().trim().min(1), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + name: Joi.string().trim().min(1), + mail_subject: Joi.string().trim().min(1), + content: Joi.string().trim().min(1), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/progress.validator.ts b/api/src/validators/progress.validator.ts index 7ace0b2bf..62f3d546e 100644 --- a/api/src/validators/progress.validator.ts +++ b/api/src/validators/progress.validator.ts @@ -33,7 +33,7 @@ export class ProgressValidator extends Validator { createOneValidator() { return celebrate({ body: Joi.object({ - report: Joi.string().trim().min(1).required(), + report: Joi.string().trim().required(), arrival: Joi.date().iso(), departure: Joi.date().iso(), building_id: Joi.number().positive().required(), @@ -44,20 +44,24 @@ export class ProgressValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - report: Joi.string().trim(), - arrival: Joi.date().iso(), - departure: Joi.date().iso(), - building_id: Joi.number().positive(), - schedule_id: Joi.number().positive(), - deleted: Joi.bool(), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + report: Joi.string().trim(), + arrival: Joi.date().iso(), + departure: Joi.date().iso(), + building_id: Joi.number().positive(), + schedule_id: Joi.number().positive(), + deleted: Joi.bool(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { @@ -99,21 +103,25 @@ export class ProgressImageValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - image_id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.forbidden(), - type: Joi.string() - .trim() - .valid("ARRIVAL", "DEPARTURE", "GARBAGE"), - description: Joi.string().trim().min(1), - image_id: Joi.number().positive(), - progress_id: Joi.number().positive(), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + image_id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + type: Joi.string() + .trim() + .valid("ARRIVAL", "DEPARTURE", "GARBAGE"), + description: Joi.string().trim().min(1), + image_id: Joi.number().positive(), + progress_id: Joi.number().positive(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/region.validator.ts b/api/src/validators/region.validator.ts index 7388f6bda..236a9688b 100644 --- a/api/src/validators/region.validator.ts +++ b/api/src/validators/region.validator.ts @@ -1,5 +1,5 @@ import { Validator } from "./validator"; -import { celebrate } from "celebrate"; +import { celebrate, Segments } from "celebrate"; import Joi from "joi"; export class RegionValidator extends Validator { @@ -10,6 +10,7 @@ export class RegionValidator extends Validator { skip: Joi.number(), name: Joi.string().trim().min(1), user_id: Joi.number(), + deleted: Joi.bool(), }), }); } @@ -31,15 +32,19 @@ export class RegionValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - name: Joi.string().min(1).required(), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + name: Joi.string().min(1).required(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/round.validator.ts b/api/src/validators/round.validator.ts index d873b5913..ccce0923c 100644 --- a/api/src/validators/round.validator.ts +++ b/api/src/validators/round.validator.ts @@ -32,15 +32,19 @@ export class RoundValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - name: Joi.string().trim().min(1), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + name: Joi.string().trim().min(1), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/round_building.validator.ts b/api/src/validators/round_building.validator.ts index 8722f456b..7b702a9c1 100644 --- a/api/src/validators/round_building.validator.ts +++ b/api/src/validators/round_building.validator.ts @@ -37,16 +37,20 @@ export class RoundBuildingValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: Joi.object({ - id: Joi.ref("params.id"), - round_id: Joi.number().positive(), - building_id: Joi.number().positive(), - }), - }); + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: Joi.object({ + id: Joi.ref("$params.id"), + round_id: Joi.number().positive(), + building_id: Joi.number().positive(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/schedule.validator.ts b/api/src/validators/schedule.validator.ts index a0fd81a32..4a4aa705a 100644 --- a/api/src/validators/schedule.validator.ts +++ b/api/src/validators/schedule.validator.ts @@ -46,20 +46,24 @@ export class ScheduleValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), - body: Joi.object({ - id: Joi.ref("params.id"), - day: Joi.date().iso(), - user_id: Joi.number().positive(), - round_id: Joi.number().positive(), - start: Joi.string().isoDate(), - end: Joi.string().isoDate(), - }), - }); + body: Joi.object({ + id: Joi.ref("$params.id"), + day: Joi.date().iso(), + user_id: Joi.number().positive(), + round_id: Joi.number().positive(), + start: Joi.string().isoDate(), + end: Joi.string().isoDate(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/syndicus.validator.ts b/api/src/validators/syndicus.validator.ts index 4f3634ee3..4daba6090 100644 --- a/api/src/validators/syndicus.validator.ts +++ b/api/src/validators/syndicus.validator.ts @@ -38,16 +38,20 @@ export class SyndicusValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), - body: Joi.object({ - id: Joi.ref("params.id"), - user_id: Joi.number().positive(), - }), - }); + body: Joi.object({ + id: Joi.ref("$params.id"), + user_id: Joi.number().positive(), + }), + }, + undefined, + { reqContext: true }, + ); } deleteOneValidator() { diff --git a/api/src/validators/user.validator.ts b/api/src/validators/user.validator.ts index f422c3ea3..b4e582e49 100644 --- a/api/src/validators/user.validator.ts +++ b/api/src/validators/user.validator.ts @@ -72,28 +72,32 @@ export class UserValidator extends Validator { } updateOneValidator() { - return celebrate({ - params: Joi.object({ - id: Joi.number().positive().required(), - }), - body: { - id: Joi.ref("params.id"), - email: Joi.string().email(), - first_name: Joi.string().min(1), - last_name: Joi.string().min(1), - date_added: Joi.date(), - last_login: Joi.date().less(Joi.ref("date_added")), - phone: Joi.string() - .min(1) - // accept a potential + sign at the beginning of the number and at least 1 digit - .regex(/^\\+?d\\+$/), - address_id: Joi.number().positive(), - student: Joi.boolean(), - super_student: Joi.boolean(), - admin: Joi.boolean(), - password: Joi.string().min(1), + return celebrate( + { + params: Joi.object({ + id: Joi.number().positive().required(), + }), + body: { + id: Joi.ref("$params.id"), + email: Joi.string().email(), + first_name: Joi.string().min(1), + last_name: Joi.string().min(1), + date_added: Joi.date(), + last_login: Joi.date().less(Joi.ref("date_added")), + phone: Joi.string() + .min(1) + // accept a potential + sign at the beginning of the number and at least 1 digit + .regex(/^\\+?d\\+$/), + address_id: Joi.number().positive(), + student: Joi.boolean(), + super_student: Joi.boolean(), + admin: Joi.boolean(), + password: Joi.string().min(1), + }, }, - }); + undefined, + { reqContext: true }, + ); } deleteOneValidator() {