From d0da75fdde3222ff0e89ec3f5d8135eb55ece2fd Mon Sep 17 00:00:00 2001 From: Kriogenia <47500377+kriogenia@users.noreply.github.com> Date: Sat, 29 Jan 2022 19:06:50 +0100 Subject: [PATCH] Unbond endpoint --- __tests__/routes/auth/Refresh.ts | 2 +- __tests__/routes/auth/SignIn.ts | 2 +- __tests__/routes/user/bonds/RemoveBond.ts | 48 +++++++++++++++++++++++ __tests__/services/UserService.ts | 6 +-- src/models/User.ts | 6 +-- src/routes/auth/SignIn.ts | 6 ++- src/routes/user/bond/BondsList.ts | 2 +- src/routes/user/bond/RemoveBond.ts | 38 ++++++++++++++++++ src/routes/user/bond/index.ts | 4 ++ 9 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 __tests__/routes/user/bonds/RemoveBond.ts create mode 100644 src/routes/user/bond/RemoveBond.ts diff --git a/__tests__/routes/auth/Refresh.ts b/__tests__/routes/auth/Refresh.ts index 2799e28..4d3b071 100644 --- a/__tests__/routes/auth/Refresh.ts +++ b/__tests__/routes/auth/Refresh.ts @@ -29,7 +29,7 @@ describe("Calling GET " + endpoint, () => { const response = await getRequest(endpoint + "refreshToken", "authToken") .send() .expect(StatusCodes.UNAUTHORIZED); - expect(response.body.message).toBe(ERR_MSG.session_invalid); + expect(response.body.message).toBe(ERR_MSG.token_invalid); }); }); \ No newline at end of file diff --git a/__tests__/routes/auth/SignIn.ts b/__tests__/routes/auth/SignIn.ts index 417419c..6ee0af0 100644 --- a/__tests__/routes/auth/SignIn.ts +++ b/__tests__/routes/auth/SignIn.ts @@ -55,7 +55,7 @@ describe("Calling GET " + endpoint, () => { await request(app) .get(`${endpoint}`) .send() - .expect(StatusCodes.NOT_FOUND); + .expect(StatusCodes.BAD_REQUEST); }); }); \ No newline at end of file diff --git a/__tests__/routes/user/bonds/RemoveBond.ts b/__tests__/routes/user/bonds/RemoveBond.ts new file mode 100644 index 0000000..342d675 --- /dev/null +++ b/__tests__/routes/user/bonds/RemoveBond.ts @@ -0,0 +1,48 @@ +import { Role, UserModel } from "@/models/User"; +import * as db from "@test-util/MongoMemory"; +import { openSession, deleteRequest } from "@test-util/SessionSetUp"; +import { StatusCodes } from "http-status-codes"; +import { SessionDto, UserDto } from "@/models/dto"; + +beforeAll(db.connect); +afterEach(db.clear); +afterAll(db.close); + +const endpoint = "/user/bonds/"; + +describe("Calling DELETE " + endpoint, () => { + + let session: SessionDto; + let user: UserDto; + + beforeEach((done) => { + openSession((response) => { + session = response.session; + user = response.user; + if (session && user) { + done(); + } + }); + }); + + it("should remove the bond if it's correct", async () => { + const keeper = await UserModel.findById(user._id); + keeper.role = Role.Keeper; + await keeper.save(); + const patient = await UserModel.create({ + googleId: "patient", + role: Role.Patient + }); + await patient.bondWith(keeper); + + await deleteRequest(endpoint + patient._id, session.auth) + .send() + .expect(StatusCodes.NO_CONTENT); + + const storedPatient = await UserModel.findById(patient._id); + expect(storedPatient.bonds.length).toBe(0); + const storedKeeper = await UserModel.findById(user._id); + expect(storedKeeper.cared).toBeUndefined(); + }); + +}); \ No newline at end of file diff --git a/__tests__/services/UserService.ts b/__tests__/services/UserService.ts index d9d20c8..e67c9b7 100644 --- a/__tests__/services/UserService.ts +++ b/__tests__/services/UserService.ts @@ -106,14 +106,14 @@ describe("The unbond function", () => { expect(storedPatient.bonds[0]).not.toEqual(keeper._id); const storedKeeper = await UserModel.findById(keeper._id); - expect(storedKeeper.cared).toBeNull(); + expect(storedKeeper.cared).toBeUndefined(); }); it("should remove the bond when a Keeper removes a Patient", async () => { await UserService.unbond(keeper._id, patient._id); const storedKeeper = await UserModel.findById(keeper._id); - expect(storedKeeper.cared).toBeNull(); + expect(storedKeeper.cared).toBeUndefined(); const storedPatient = await UserModel.findById(patient._id); expect(storedPatient.bonds.length).toBe(1); expect(storedPatient.bonds[0]).not.toEqual(keeper._id); @@ -139,7 +139,7 @@ describe("The unbond function", () => { expect(storedPatient.bonds.length).toBe(1); expect(storedPatient.bonds[0]).not.toEqual(keeper._id); const storedKeeper = await UserModel.findById(keeper._id); - expect(storedKeeper.cared).toBeNull(); + expect(storedKeeper.cared).toBeUndefined(); }); }); diff --git a/src/models/User.ts b/src/models/User.ts index 1a57410..3824ae8 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -97,7 +97,7 @@ export class UserSchema { if (this.bonds.length >= parseInt(process.env.MAX_BONDS)) { throw badRequestError(ERR_MSG.maximum_bonds_reached); } - if (keeper.cared !== undefined) { + if (keeper.cared !== undefined && keeper.cared !== null) { throw badRequestError(ERR_MSG.keeper_already_bonded); } this.bonds.push(keeper); @@ -117,9 +117,9 @@ export class UserSchema { } if (this.role === Role.Patient) { this.bonds.remove(bond); - bond.cared = null; + bond.cared = undefined; } else { - this.cared = null; + this.cared = undefined; bond.bonds.remove(this); } await Promise.all([this.save(), bond.save()]); diff --git a/src/routes/auth/SignIn.ts b/src/routes/auth/SignIn.ts index 1920d50..f469965 100644 --- a/src/routes/auth/SignIn.ts +++ b/src/routes/auth/SignIn.ts @@ -32,9 +32,11 @@ export const signIn = async ( // Verify the Google token return GoogleAuth.verify(req.params.token) .then(UserService.getByGoogleId) // And get the user to return - .then((user) => res.status(StatusCodes.OK).json({ + .then((user) => { + return res.status(StatusCodes.OK).json({ session: TokenService.sessionPackage(user.id), user: user.dto() - }).send()) + }).send(); + }) .catch(next); } \ No newline at end of file diff --git a/src/routes/user/bond/BondsList.ts b/src/routes/user/bond/BondsList.ts index 375ad5f..71c4a4a 100644 --- a/src/routes/user/bond/BondsList.ts +++ b/src/routes/user/bond/BondsList.ts @@ -23,7 +23,7 @@ export const list = async ( ? UserService.getBonds(id) : UserService.getBondsOfCared(id); return list.then((users) => { - const bonds = users.filter(u => u._id != id).map(u => u.public); + const bonds = users.filter(u => u._id != id).map(u => u.dto()); return res.status(StatusCodes.OK).send({bonds: bonds}); }).catch(next); } \ No newline at end of file diff --git a/src/routes/user/bond/RemoveBond.ts b/src/routes/user/bond/RemoveBond.ts new file mode 100644 index 0000000..c3a52e5 --- /dev/null +++ b/src/routes/user/bond/RemoveBond.ts @@ -0,0 +1,38 @@ +import { NextFunction, Request, Response } from "express"; +import { StatusCodes } from "http-status-codes"; +import * as UserService from "@/services/UserService"; +import { UserDto } from "@/models/dto"; +import { IdParam } from "@/shared/values"; +import * as NotificationService from "@/services/NotificationService"; +import { Action } from "@/models/Notification"; +import { Role } from "@/models/User"; +import { GLOBAL } from "@/sockets/global"; +import { io } from "@server"; + +/** + * Removes the bond of the user with the specified user + * @param req request with the bond id + * @param res carried response + * @param next invokation of the next middleware to use in case of error + * @returns the response with the success or error confirmation message + */ +export const removeBond = async ( + req: Request, + res: Response, + next: NextFunction): Promise> => +{ + let patientId: string; + return UserService.getRole(req.sessionId) + .then((role) => { + patientId = role === Role.Patient ? req.sessionId : req.params.id; + return UserService.unbond(req.sessionId, req.params.id); + }) + .then(() => { + res.status(StatusCodes.NO_CONTENT).send(); + return NotificationService.create(Action.BOND_DELETED, patientId); + }) + .then((notification) => { + io.to(`${GLOBAL}:${patientId}`).emit(notification.event, notification.dto()) + }) + .catch(next); +} \ No newline at end of file diff --git a/src/routes/user/bond/index.ts b/src/routes/user/bond/index.ts index 4a1fb65..44dd2f9 100644 --- a/src/routes/user/bond/index.ts +++ b/src/routes/user/bond/index.ts @@ -2,12 +2,16 @@ import { Router } from "express"; import { list } from "./BondsList"; import { establish } from "./EstablishBond"; import { generate } from "./GenerateBond"; +import { removeBond } from "./RemoveBond"; const bondRouter = Router(); /* GET /user/bonds */ bondRouter.get("", list); +/* DELETE /user/bonds/:id */ +bondRouter.delete("/:id", removeBond); + /* POST /user/bonds/establish */ bondRouter.post("/establish", establish);