From eef616c415f4120cca663a2bcff9d96982e87e31 Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Sat, 22 Jun 2024 12:26:06 -0400 Subject: [PATCH 1/7] Added behaviour endpoints --- .../validators/behaviourValidators.ts | 20 +++ backend/typescript/models/behaviour.model.ts | 2 +- backend/typescript/rest/behaviourRoutes.ts | 95 ++++++++++++++ backend/typescript/server.ts | 4 +- .../implementations/behaviourService.ts | 117 ++++++++++++++++++ .../services/interfaces/behaviourService.ts | 57 +++++++++ 6 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 backend/typescript/middlewares/validators/behaviourValidators.ts create mode 100644 backend/typescript/rest/behaviourRoutes.ts create mode 100644 backend/typescript/services/implementations/behaviourService.ts create mode 100644 backend/typescript/services/interfaces/behaviourService.ts diff --git a/backend/typescript/middlewares/validators/behaviourValidators.ts b/backend/typescript/middlewares/validators/behaviourValidators.ts new file mode 100644 index 0000000..912e0d5 --- /dev/null +++ b/backend/typescript/middlewares/validators/behaviourValidators.ts @@ -0,0 +1,20 @@ +import { Request, Response, NextFunction } from "express"; +import { + getApiValidationError, + validateArray, + validatePrimitive, +} from "./util"; + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable-next-line import/prefer-default-export */ +export const behaviourRequestDtoValidators = async ( + req: Request, + res: Response, + next: NextFunction, +) => { + const { body } = req; + if (!validatePrimitive(body.behaviourName, "string")) { + return res.status(400).send(getApiValidationError("behaviourName", "string")); + } + return next(); +}; diff --git a/backend/typescript/models/behaviour.model.ts b/backend/typescript/models/behaviour.model.ts index ef94be7..9ffaf6d 100644 --- a/backend/typescript/models/behaviour.model.ts +++ b/backend/typescript/models/behaviour.model.ts @@ -1,6 +1,6 @@ import { Column, Model, Table } from "sequelize-typescript"; -@Table({ tableName: "behaviours" }) +@Table({ timestamps: false, tableName: "behaviours" }) export default class Behaviour extends Model { @Column behaviour_name!: string; diff --git a/backend/typescript/rest/behaviourRoutes.ts b/backend/typescript/rest/behaviourRoutes.ts new file mode 100644 index 0000000..a51cbad --- /dev/null +++ b/backend/typescript/rest/behaviourRoutes.ts @@ -0,0 +1,95 @@ +import { Router } from "express"; +import { isAuthorizedByRole } from "../middlewares/auth"; +import { behaviourRequestDtoValidators } from "../middlewares/validators/behaviourValidators"; +import BehaviourService from "../services/implementations/behaviourService"; +import { + BehaviourResponseDTO, + IBehaviourService, +} from "../services/interfaces/behaviourService"; +import { getErrorMessage } from "../utilities/errorUtils"; +import { sendResponseByMimeType } from "../utilities/responseUtil"; + +const behaviourRouter: Router = Router(); + +const behaviourService: IBehaviourService = new BehaviourService(); + +/* Create Behaviour */ +behaviourRouter.post( + "/", + behaviourRequestDtoValidators, + async (req, res) => { + try { + const { body } = req; + const newBehaviour = await behaviourService.createBehaviour({ + behaviourName: body.behaviourName, + }); + res.status(201).json(newBehaviour); + } catch (e: unknown) { + res.status(500).send(getErrorMessage(e)); + } + }, +); + +/* Get all Behaviours */ +behaviourRouter.get("/", async (req, res) => { + const contentType = req.headers["content-type"]; + try { + const behaviours = await behaviourService.getBehaviours(); + await sendResponseByMimeType( + res, + 200, + contentType, + behaviours, + ); + } catch (e: unknown) { + await sendResponseByMimeType(res, 500, contentType, [ + { + error: getErrorMessage(e), + }, + ]); + } +}); + +/* Get Behaviour by id */ +behaviourRouter.get("/:id", async (req, res) => { + const { id } = req.params; + + try { + const behaviour = await behaviourService.getBehaviour(id); + res.status(200).json(behaviour); + } catch (e: unknown) { + res.status(500).send(getErrorMessage(e)); + } +}); + +/* Update Behaviour by id */ +behaviourRouter.put( + "/:id", + behaviourRequestDtoValidators, + async (req, res) => { + const { id } = req.params; + try { + const { body } = req; + const behaviour = await behaviourService.updateBehaviour(id, { + behaviourName: body.behaviourName, + }); + res.status(200).json(behaviour); + } catch (e: unknown) { + res.status(500).send(getErrorMessage(e)); + } + }, +); + +/* Delete Behaviour by id */ +behaviourRouter.delete("/:id", async (req, res) => { + const { id } = req.params; + + try { + const deletedId = await behaviourService.deleteBehaviour(id); + res.status(200).json({ id: deletedId }); + } catch (e: unknown) { + res.status(500).send(getErrorMessage(e)); + } +}); + +export default behaviourRouter; diff --git a/backend/typescript/server.ts b/backend/typescript/server.ts index b824007..4938045 100644 --- a/backend/typescript/server.ts +++ b/backend/typescript/server.ts @@ -7,9 +7,10 @@ import YAML from "yamljs"; import { sequelize } from "./models"; import authRouter from "./rest/authRoutes"; +import behaviourRouter from "./rest/behaviourRoutes"; import entityRouter from "./rest/entityRoutes"; import simpleEntityRouter from "./rest/simpleEntityRoutes"; -import userRouter from "./rest/userRoutes"; +import userRouter from "./rest/userRoutes"; const CORS_ALLOW_LIST = [ "http://localhost:3000", @@ -32,6 +33,7 @@ app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use("/auth", authRouter); +app.use("/behaviours", behaviourRouter); app.use("/entities", entityRouter); app.use("/simple-entities", simpleEntityRouter); app.use("/users", userRouter); diff --git a/backend/typescript/services/implementations/behaviourService.ts b/backend/typescript/services/implementations/behaviourService.ts new file mode 100644 index 0000000..41010f0 --- /dev/null +++ b/backend/typescript/services/implementations/behaviourService.ts @@ -0,0 +1,117 @@ +import PgBehaviour from "../../models/behaviour.model"; +import { + IBehaviourService, + BehaviourRequestDTO, + BehaviourResponseDTO, +} from "../interfaces/behaviourService"; +import { getErrorMessage } from "../../utilities/errorUtils"; +import logger from "../../utilities/logger"; + +const Logger = logger(__filename); + +class BehaviourService implements IBehaviourService { + /* eslint-disable class-methods-use-this */ + async getBehaviour(id: string): Promise { + let behaviour: PgBehaviour | null; + try { + behaviour = await PgBehaviour.findByPk(id, { raw: true }); + if (!behaviour) { + throw new Error(`Behaviour id ${id} not found`); + } + } catch (error: unknown) { + Logger.error(`Failed to get behaviour. Reason = ${getErrorMessage(error)}`); + throw error; + } + + return { + id: String(behaviour.id), + behaviourName: behaviour.behaviour_name, + }; + } + + async getBehaviours(): Promise { + try { + const behaviours: Array = await PgBehaviour.findAll({ + raw: true, + }); + return behaviours.map((behaviour) => ({ + id: String(behaviour.id), + behaviourName: behaviour.behaviour_name, + })); + } catch (error: unknown) { + Logger.error( + `Failed to get behaviours. Reason = ${getErrorMessage(error)}`, + ); + throw error; + } + } + + async createBehaviour( + behaviour: BehaviourRequestDTO, + ): Promise { + let newBehaviour: PgBehaviour | null; + try { + newBehaviour = await PgBehaviour.create({ + behaviour_name: behaviour.behaviourName, + }); + } catch (error: unknown) { + Logger.error( + `Failed to create behaviour. Reason = ${getErrorMessage(error)}`, + ); + throw error; + } + return { + id: String(newBehaviour.id), + behaviourName: newBehaviour?.behaviour_name, + }; + } + + async updateBehaviour( + id: string, + behaviour: BehaviourRequestDTO, + ): Promise { + let resultingBehaviour: PgBehaviour | null; + let updateResult: [number, PgBehaviour[]] | null; + try { + updateResult = await PgBehaviour.update( + { + behaviour_name: behaviour.behaviourName, + }, + { where: { id }, returning: true }, + ); + + if (!updateResult[0]) { + throw new Error(`Behaviour id ${id} not found`); + } + [, [resultingBehaviour]] = updateResult; + } catch (error: unknown) { + Logger.error( + `Failed to update behaviour. Reason = ${getErrorMessage(error)}`, + ); + throw error; + } + return { + id: String(resultingBehaviour.id), + behaviourName: resultingBehaviour?.behaviour_name, + }; + } + + async deleteBehaviour(id: string): Promise { + try { + const deleteResult: number | null = await PgBehaviour.destroy({ + where: { id }, + }); + if (!deleteResult) { + throw new Error(`Behaviour id ${id} not found`); + } + return id; + } catch (error: unknown) { + Logger.error( + `Failed to delete behaviour. Reason = ${getErrorMessage(error)}`, + ); + throw error; + } + } +} + +export default BehaviourService; diff --git a/backend/typescript/services/interfaces/behaviourService.ts b/backend/typescript/services/interfaces/behaviourService.ts new file mode 100644 index 0000000..f93bdf5 --- /dev/null +++ b/backend/typescript/services/interfaces/behaviourService.ts @@ -0,0 +1,57 @@ +export interface BehaviourRequestDTO { + behaviourName: string; + } + + export interface BehaviourResponseDTO { + id: string; + behaviourName: string; + } + + export interface IBehaviourService { + /** + * retrieve the Behaviour with the given id + * @param id Behaviour id + * @returns requested Behaviour + * @throws Error if retrieval fails + */ + getBehaviour(id: string): Promise; + + /** + * retrieve all Behaviours + * @param + * @returns returns array of Behaviours + * @throws Error if retrieval fails + */ + getBehaviours(): Promise; + + /** + * create a Behaviour with the fields given in the DTO, return created Behaviour + * @param behaviour new Behaviour + * @returns the created Behaviour + * @throws Error if creation fails + */ + createBehaviour( + behaviour: BehaviourRequestDTO, + ): Promise; + + /** + * update the Behaviour with the given id with fields in the DTO, return updated Behaviour + * @param id Behaviour id + * @param behaviour Updated Behaviour + * @returns the updated Behaviour + * @throws Error if update fails + */ + updateBehaviour( + id: string, + behaviour: BehaviourRequestDTO, + ): Promise; + + /** + * delete the Behaviour with the given id + * @param id Behaviour id + * @returns id of the Behaviour deleted + * @throws Error if deletion fails + */ + deleteBehaviour(id: string): Promise; + } + \ No newline at end of file From ea28d6a744338ab15858e2f2153c4d8f9b762bad Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Sat, 22 Jun 2024 12:47:13 -0400 Subject: [PATCH 2/7] Fixed formatting errors --- .../validators/behaviourValidators.ts | 4 +- backend/typescript/rest/behaviourRoutes.ts | 58 ++++----- backend/typescript/server.ts | 2 +- .../implementations/behaviourService.ts | 14 ++- .../services/interfaces/behaviourService.ts | 111 +++++++++--------- 5 files changed, 91 insertions(+), 98 deletions(-) diff --git a/backend/typescript/middlewares/validators/behaviourValidators.ts b/backend/typescript/middlewares/validators/behaviourValidators.ts index 912e0d5..f9f101b 100644 --- a/backend/typescript/middlewares/validators/behaviourValidators.ts +++ b/backend/typescript/middlewares/validators/behaviourValidators.ts @@ -14,7 +14,9 @@ export const behaviourRequestDtoValidators = async ( ) => { const { body } = req; if (!validatePrimitive(body.behaviourName, "string")) { - return res.status(400).send(getApiValidationError("behaviourName", "string")); + return res + .status(400) + .send(getApiValidationError("behaviourName", "string")); } return next(); }; diff --git a/backend/typescript/rest/behaviourRoutes.ts b/backend/typescript/rest/behaviourRoutes.ts index a51cbad..198e747 100644 --- a/backend/typescript/rest/behaviourRoutes.ts +++ b/backend/typescript/rest/behaviourRoutes.ts @@ -1,5 +1,4 @@ import { Router } from "express"; -import { isAuthorizedByRole } from "../middlewares/auth"; import { behaviourRequestDtoValidators } from "../middlewares/validators/behaviourValidators"; import BehaviourService from "../services/implementations/behaviourService"; import { @@ -9,26 +8,21 @@ import { import { getErrorMessage } from "../utilities/errorUtils"; import { sendResponseByMimeType } from "../utilities/responseUtil"; -const behaviourRouter: Router = Router(); - +const behaviourRouter: Router = Router(); const behaviourService: IBehaviourService = new BehaviourService(); /* Create Behaviour */ -behaviourRouter.post( - "/", - behaviourRequestDtoValidators, - async (req, res) => { - try { - const { body } = req; - const newBehaviour = await behaviourService.createBehaviour({ - behaviourName: body.behaviourName, - }); - res.status(201).json(newBehaviour); - } catch (e: unknown) { - res.status(500).send(getErrorMessage(e)); - } - }, -); +behaviourRouter.post("/", behaviourRequestDtoValidators, async (req, res) => { + try { + const { body } = req; + const newBehaviour = await behaviourService.createBehaviour({ + behaviourName: body.behaviourName, + }); + res.status(201).json(newBehaviour); + } catch (e: unknown) { + res.status(500).send(getErrorMessage(e)); + } +}); /* Get all Behaviours */ behaviourRouter.get("/", async (req, res) => { @@ -63,22 +57,18 @@ behaviourRouter.get("/:id", async (req, res) => { }); /* Update Behaviour by id */ -behaviourRouter.put( - "/:id", - behaviourRequestDtoValidators, - async (req, res) => { - const { id } = req.params; - try { - const { body } = req; - const behaviour = await behaviourService.updateBehaviour(id, { - behaviourName: body.behaviourName, - }); - res.status(200).json(behaviour); - } catch (e: unknown) { - res.status(500).send(getErrorMessage(e)); - } - }, -); +behaviourRouter.put("/:id", behaviourRequestDtoValidators, async (req, res) => { + const { id } = req.params; + try { + const { body } = req; + const behaviour = await behaviourService.updateBehaviour(id, { + behaviourName: body.behaviourName, + }); + res.status(200).json(behaviour); + } catch (e: unknown) { + res.status(500).send(getErrorMessage(e)); + } +}); /* Delete Behaviour by id */ behaviourRouter.delete("/:id", async (req, res) => { diff --git a/backend/typescript/server.ts b/backend/typescript/server.ts index 4938045..338bfd3 100644 --- a/backend/typescript/server.ts +++ b/backend/typescript/server.ts @@ -10,7 +10,7 @@ import authRouter from "./rest/authRoutes"; import behaviourRouter from "./rest/behaviourRoutes"; import entityRouter from "./rest/entityRoutes"; import simpleEntityRouter from "./rest/simpleEntityRoutes"; -import userRouter from "./rest/userRoutes"; +import userRouter from "./rest/userRoutes"; const CORS_ALLOW_LIST = [ "http://localhost:3000", diff --git a/backend/typescript/services/implementations/behaviourService.ts b/backend/typescript/services/implementations/behaviourService.ts index 41010f0..cda7b77 100644 --- a/backend/typescript/services/implementations/behaviourService.ts +++ b/backend/typescript/services/implementations/behaviourService.ts @@ -19,13 +19,15 @@ class BehaviourService implements IBehaviourService { throw new Error(`Behaviour id ${id} not found`); } } catch (error: unknown) { - Logger.error(`Failed to get behaviour. Reason = ${getErrorMessage(error)}`); + Logger.error( + `Failed to get behaviour. Reason = ${getErrorMessage(error)}`, + ); throw error; } return { id: String(behaviour.id), - behaviourName: behaviour.behaviour_name, + behaviourName: behaviour.behaviour_name, }; } @@ -36,7 +38,7 @@ class BehaviourService implements IBehaviourService { }); return behaviours.map((behaviour) => ({ id: String(behaviour.id), - behaviourName: behaviour.behaviour_name, + behaviourName: behaviour.behaviour_name, })); } catch (error: unknown) { Logger.error( @@ -52,7 +54,7 @@ class BehaviourService implements IBehaviourService { let newBehaviour: PgBehaviour | null; try { newBehaviour = await PgBehaviour.create({ - behaviour_name: behaviour.behaviourName, + behaviour_name: behaviour.behaviourName, }); } catch (error: unknown) { Logger.error( @@ -62,7 +64,7 @@ class BehaviourService implements IBehaviourService { } return { id: String(newBehaviour.id), - behaviourName: newBehaviour?.behaviour_name, + behaviourName: newBehaviour?.behaviour_name, }; } @@ -92,7 +94,7 @@ class BehaviourService implements IBehaviourService { } return { id: String(resultingBehaviour.id), - behaviourName: resultingBehaviour?.behaviour_name, + behaviourName: resultingBehaviour?.behaviour_name, }; } diff --git a/backend/typescript/services/interfaces/behaviourService.ts b/backend/typescript/services/interfaces/behaviourService.ts index f93bdf5..647aa54 100644 --- a/backend/typescript/services/interfaces/behaviourService.ts +++ b/backend/typescript/services/interfaces/behaviourService.ts @@ -1,57 +1,56 @@ export interface BehaviourRequestDTO { - behaviourName: string; - } - - export interface BehaviourResponseDTO { - id: string; - behaviourName: string; - } - - export interface IBehaviourService { - /** - * retrieve the Behaviour with the given id - * @param id Behaviour id - * @returns requested Behaviour - * @throws Error if retrieval fails - */ - getBehaviour(id: string): Promise; - - /** - * retrieve all Behaviours - * @param - * @returns returns array of Behaviours - * @throws Error if retrieval fails - */ - getBehaviours(): Promise; - - /** - * create a Behaviour with the fields given in the DTO, return created Behaviour - * @param behaviour new Behaviour - * @returns the created Behaviour - * @throws Error if creation fails - */ - createBehaviour( - behaviour: BehaviourRequestDTO, - ): Promise; - - /** - * update the Behaviour with the given id with fields in the DTO, return updated Behaviour - * @param id Behaviour id - * @param behaviour Updated Behaviour - * @returns the updated Behaviour - * @throws Error if update fails - */ - updateBehaviour( - id: string, - behaviour: BehaviourRequestDTO, - ): Promise; - - /** - * delete the Behaviour with the given id - * @param id Behaviour id - * @returns id of the Behaviour deleted - * @throws Error if deletion fails - */ - deleteBehaviour(id: string): Promise; - } - \ No newline at end of file + behaviourName: string; +} + +export interface BehaviourResponseDTO { + id: string; + behaviourName: string; +} + +export interface IBehaviourService { + /** + * retrieve the Behaviour with the given id + * @param id Behaviour id + * @returns requested Behaviour + * @throws Error if retrieval fails + */ + getBehaviour(id: string): Promise; + + /** + * retrieve all Behaviours + * @param + * @returns returns array of Behaviours + * @throws Error if retrieval fails + */ + getBehaviours(): Promise; + + /** + * create a Behaviour with the fields given in the DTO, return created Behaviour + * @param behaviour new Behaviour + * @returns the created Behaviour + * @throws Error if creation fails + */ + createBehaviour( + behaviour: BehaviourRequestDTO, + ): Promise; + + /** + * update the Behaviour with the given id with fields in the DTO, return updated Behaviour + * @param id Behaviour id + * @param behaviour Updated Behaviour + * @returns the updated Behaviour + * @throws Error if update fails + */ + updateBehaviour( + id: string, + behaviour: BehaviourRequestDTO, + ): Promise; + + /** + * delete the Behaviour with the given id + * @param id Behaviour id + * @returns id of the Behaviour deleted + * @throws Error if deletion fails + */ + deleteBehaviour(id: string): Promise; +} From f468dbd8a937ee2f478ffb236e0759cd42d78f41 Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Sat, 22 Jun 2024 12:54:21 -0400 Subject: [PATCH 3/7] Removed unused import --- backend/typescript/middlewares/validators/behaviourValidators.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/typescript/middlewares/validators/behaviourValidators.ts b/backend/typescript/middlewares/validators/behaviourValidators.ts index f9f101b..6264e4a 100644 --- a/backend/typescript/middlewares/validators/behaviourValidators.ts +++ b/backend/typescript/middlewares/validators/behaviourValidators.ts @@ -1,7 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { getApiValidationError, - validateArray, validatePrimitive, } from "./util"; From 2f492f0296d5b13c64f647b5e605eb6cfd542cc5 Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Sat, 22 Jun 2024 12:59:46 -0400 Subject: [PATCH 4/7] Fixed linting errors --- .../typescript/middlewares/validators/behaviourValidators.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/typescript/middlewares/validators/behaviourValidators.ts b/backend/typescript/middlewares/validators/behaviourValidators.ts index 6264e4a..10ac9ee 100644 --- a/backend/typescript/middlewares/validators/behaviourValidators.ts +++ b/backend/typescript/middlewares/validators/behaviourValidators.ts @@ -1,8 +1,5 @@ import { Request, Response, NextFunction } from "express"; -import { - getApiValidationError, - validatePrimitive, -} from "./util"; +import { getApiValidationError, validatePrimitive } from "./util"; /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable-next-line import/prefer-default-export */ From 45896edd118a08e92d42852c207c26093810b1fb Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Mon, 24 Jun 2024 18:20:44 -0400 Subject: [PATCH 5/7] Changed BehaviourResponseDTO id to be a number --- .../services/implementations/behaviourService.ts | 8 ++++---- .../typescript/services/interfaces/behaviourService.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/typescript/services/implementations/behaviourService.ts b/backend/typescript/services/implementations/behaviourService.ts index cda7b77..d89a83a 100644 --- a/backend/typescript/services/implementations/behaviourService.ts +++ b/backend/typescript/services/implementations/behaviourService.ts @@ -26,7 +26,7 @@ class BehaviourService implements IBehaviourService { } return { - id: String(behaviour.id), + id: behaviour.id, behaviourName: behaviour.behaviour_name, }; } @@ -37,7 +37,7 @@ class BehaviourService implements IBehaviourService { raw: true, }); return behaviours.map((behaviour) => ({ - id: String(behaviour.id), + id: behaviour.id, behaviourName: behaviour.behaviour_name, })); } catch (error: unknown) { @@ -63,7 +63,7 @@ class BehaviourService implements IBehaviourService { throw error; } return { - id: String(newBehaviour.id), + id: newBehaviour?.id, behaviourName: newBehaviour?.behaviour_name, }; } @@ -93,7 +93,7 @@ class BehaviourService implements IBehaviourService { throw error; } return { - id: String(resultingBehaviour.id), + id: resultingBehaviour?.id, behaviourName: resultingBehaviour?.behaviour_name, }; } diff --git a/backend/typescript/services/interfaces/behaviourService.ts b/backend/typescript/services/interfaces/behaviourService.ts index 647aa54..af34ecb 100644 --- a/backend/typescript/services/interfaces/behaviourService.ts +++ b/backend/typescript/services/interfaces/behaviourService.ts @@ -3,7 +3,7 @@ export interface BehaviourRequestDTO { } export interface BehaviourResponseDTO { - id: string; + id: number; behaviourName: string; } From 0227c794fd094409e9241e39e41dd9b352a16316 Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Tue, 25 Jun 2024 20:53:00 -0400 Subject: [PATCH 6/7] Added custom error handling --- backend/typescript/rest/behaviourRoutes.ts | 20 +++++++++++++++---- .../implementations/behaviourService.ts | 8 ++++---- backend/typescript/utilities/errorUtils.ts | 8 ++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/backend/typescript/rest/behaviourRoutes.ts b/backend/typescript/rest/behaviourRoutes.ts index 198e747..291f307 100644 --- a/backend/typescript/rest/behaviourRoutes.ts +++ b/backend/typescript/rest/behaviourRoutes.ts @@ -5,7 +5,7 @@ import { BehaviourResponseDTO, IBehaviourService, } from "../services/interfaces/behaviourService"; -import { getErrorMessage } from "../utilities/errorUtils"; +import { getErrorMessage, NotFoundError } from "../utilities/errorUtils"; import { sendResponseByMimeType } from "../utilities/responseUtil"; const behaviourRouter: Router = Router(); @@ -52,7 +52,11 @@ behaviourRouter.get("/:id", async (req, res) => { const behaviour = await behaviourService.getBehaviour(id); res.status(200).json(behaviour); } catch (e: unknown) { - res.status(500).send(getErrorMessage(e)); + if (e instanceof NotFoundError) { + res.status(404).send(getErrorMessage(e)); + } else { + res.status(500).send(getErrorMessage(e)); + } } }); @@ -66,7 +70,11 @@ behaviourRouter.put("/:id", behaviourRequestDtoValidators, async (req, res) => { }); res.status(200).json(behaviour); } catch (e: unknown) { - res.status(500).send(getErrorMessage(e)); + if (e instanceof NotFoundError) { + res.status(404).send(getErrorMessage(e)); + } else { + res.status(500).send(getErrorMessage(e)); + } } }); @@ -78,7 +86,11 @@ behaviourRouter.delete("/:id", async (req, res) => { const deletedId = await behaviourService.deleteBehaviour(id); res.status(200).json({ id: deletedId }); } catch (e: unknown) { - res.status(500).send(getErrorMessage(e)); + if (e instanceof NotFoundError) { + res.status(404).send(getErrorMessage(e)); + } else { + res.status(500).send(getErrorMessage(e)); + } } }); diff --git a/backend/typescript/services/implementations/behaviourService.ts b/backend/typescript/services/implementations/behaviourService.ts index d89a83a..793761b 100644 --- a/backend/typescript/services/implementations/behaviourService.ts +++ b/backend/typescript/services/implementations/behaviourService.ts @@ -4,7 +4,7 @@ import { BehaviourRequestDTO, BehaviourResponseDTO, } from "../interfaces/behaviourService"; -import { getErrorMessage } from "../../utilities/errorUtils"; +import { getErrorMessage, NotFoundError } from "../../utilities/errorUtils"; import logger from "../../utilities/logger"; const Logger = logger(__filename); @@ -16,7 +16,7 @@ class BehaviourService implements IBehaviourService { try { behaviour = await PgBehaviour.findByPk(id, { raw: true }); if (!behaviour) { - throw new Error(`Behaviour id ${id} not found`); + throw new NotFoundError(`Behaviour id ${id} not found`); } } catch (error: unknown) { Logger.error( @@ -83,7 +83,7 @@ class BehaviourService implements IBehaviourService { ); if (!updateResult[0]) { - throw new Error(`Behaviour id ${id} not found`); + throw new NotFoundError(`Behaviour id ${id} not found`); } [, [resultingBehaviour]] = updateResult; } catch (error: unknown) { @@ -104,7 +104,7 @@ class BehaviourService implements IBehaviourService { where: { id }, }); if (!deleteResult) { - throw new Error(`Behaviour id ${id} not found`); + throw new NotFoundError(`Behaviour id ${id} not found`); } return id; } catch (error: unknown) { diff --git a/backend/typescript/utilities/errorUtils.ts b/backend/typescript/utilities/errorUtils.ts index a5e59f0..e66455a 100644 --- a/backend/typescript/utilities/errorUtils.ts +++ b/backend/typescript/utilities/errorUtils.ts @@ -2,3 +2,11 @@ export const getErrorMessage = (error: unknown): string => { return error instanceof Error ? error.message : "Unknown error occurred."; }; + +// Thrown when resource is not found +export class NotFoundError extends Error { + constructor(message: string) { + super(message); + this.name = "NotFoundError"; + } +} From fae5ed4fbd88227632ce80dec004cefcb99aa1a0 Mon Sep 17 00:00:00 2001 From: Daniel Zhang Date: Tue, 25 Jun 2024 21:56:57 -0400 Subject: [PATCH 7/7] Hid internal server error messages --- backend/typescript/rest/behaviourRoutes.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/typescript/rest/behaviourRoutes.ts b/backend/typescript/rest/behaviourRoutes.ts index 291f307..44049ea 100644 --- a/backend/typescript/rest/behaviourRoutes.ts +++ b/backend/typescript/rest/behaviourRoutes.ts @@ -20,7 +20,7 @@ behaviourRouter.post("/", behaviourRequestDtoValidators, async (req, res) => { }); res.status(201).json(newBehaviour); } catch (e: unknown) { - res.status(500).send(getErrorMessage(e)); + res.status(500).send("Internal server error occured."); } }); @@ -38,7 +38,7 @@ behaviourRouter.get("/", async (req, res) => { } catch (e: unknown) { await sendResponseByMimeType(res, 500, contentType, [ { - error: getErrorMessage(e), + error: "Internal server error occured.", }, ]); } @@ -55,7 +55,7 @@ behaviourRouter.get("/:id", async (req, res) => { if (e instanceof NotFoundError) { res.status(404).send(getErrorMessage(e)); } else { - res.status(500).send(getErrorMessage(e)); + res.status(500).send("Internal server error occured."); } } }); @@ -73,7 +73,7 @@ behaviourRouter.put("/:id", behaviourRequestDtoValidators, async (req, res) => { if (e instanceof NotFoundError) { res.status(404).send(getErrorMessage(e)); } else { - res.status(500).send(getErrorMessage(e)); + res.status(500).send("Internal server error occured."); } } }); @@ -89,7 +89,7 @@ behaviourRouter.delete("/:id", async (req, res) => { if (e instanceof NotFoundError) { res.status(404).send(getErrorMessage(e)); } else { - res.status(500).send(getErrorMessage(e)); + res.status(500).send("Internal server error occured."); } } });