From 0512b2ad197e740da631b6bcc0ee89bde580309b Mon Sep 17 00:00:00 2001 From: jeffplays2005 Date: Sat, 2 Nov 2024 13:58:07 +1300 Subject: [PATCH] Scope get event id endpoint to admins only * Updated endpoint * Updated interfaces * Updated tests * Generate swagger --- server/src/middleware/__generated__/routes.ts | 81 ++++++++-------- .../src/middleware/__generated__/swagger.json | 92 ++++++++++--------- .../middleware/tests/AdminController.test.ts | 25 +++++ .../middleware/tests/EventController.test.ts | 17 ---- .../controllers/AdminController.ts | 26 +++++- .../controllers/EventController.ts | 28 +----- .../response-models/AdminResponse.ts | 6 +- .../response-models/EventResponse.ts | 4 - 8 files changed, 147 insertions(+), 132 deletions(-) diff --git a/server/src/middleware/__generated__/routes.ts b/server/src/middleware/__generated__/routes.ts index 51ec4df8f..05153a926 100644 --- a/server/src/middleware/__generated__/routes.ts +++ b/server/src/middleware/__generated__/routes.ts @@ -213,16 +213,6 @@ const models: TsoaRoute.Models = { "additionalProperties": false, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa - "GetEventResponse": { - "dataType": "refObject", - "properties": { - "error": {"dataType":"string"}, - "message": {"dataType":"string"}, - "data": {"ref":"Event"}, - }, - "additionalProperties": false, - }, - // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "AllUserBookingSlotsResponse": { "dataType": "refObject", "properties": { @@ -558,6 +548,16 @@ const models: TsoaRoute.Models = { "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"title":{"dataType":"string"},"description":{"dataType":"string"},"image_url":{"dataType":"string"},"location":{"dataType":"string"},"google_forms_link":{"dataType":"string"},"sign_up_start_date":{"ref":"FirebaseFirestore.Timestamp"},"sign_up_end_date":{"ref":"FirebaseFirestore.Timestamp"},"physical_start_date":{"ref":"FirebaseFirestore.Timestamp"},"physical_end_date":{"ref":"FirebaseFirestore.Timestamp"},"max_occupancy":{"dataType":"double"}},"validators":{}}, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "GetEventResponse": { + "dataType": "refObject", + "properties": { + "error": {"dataType":"string"}, + "message": {"dataType":"string"}, + "data": {"ref":"Event"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa }; const templateService = new ExpressTemplateService(models, {"noImplicitAdditionalProperties":"throw-on-extras","bodyCoercion":true}); @@ -906,36 +906,6 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa - app.get('/events/:id', - ...(fetchMiddlewares(EventController)), - ...(fetchMiddlewares(EventController.prototype.getEventById)), - - function EventController_getEventById(request: ExRequest, response: ExResponse, next: any) { - const args: Record = { - id: {"in":"path","name":"id","required":true,"dataType":"string"}, - }; - - // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa - - let validatedArgs: any[] = []; - try { - validatedArgs = templateService.getValidatedArgs({ args, request, response }); - - const controller = new EventController(); - - templateService.apiHandler({ - methodName: 'getEventById', - controller, - response, - next, - validatedArgs, - successStatus: 200, - }); - } catch (err) { - return next(err); - } - }); - // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.get('/bookings', authenticateMiddleware([{"jwt":["member"]}]), ...(fetchMiddlewares(BookingController)), @@ -1496,6 +1466,37 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.get('/admin/:id', + authenticateMiddleware([{"jwt":["admin"]}]), + ...(fetchMiddlewares(AdminController)), + ...(fetchMiddlewares(AdminController.prototype.getEventById)), + + function AdminController_getEventById(request: ExRequest, response: ExResponse, next: any) { + const args: Record = { + id: {"in":"path","name":"id","required":true,"dataType":"string"}, + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args, request, response }); + + const controller = new AdminController(); + + templateService.apiHandler({ + methodName: 'getEventById', + controller, + response, + next, + validatedArgs, + successStatus: 200, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa diff --git a/server/src/middleware/__generated__/swagger.json b/server/src/middleware/__generated__/swagger.json index 7476eda3e..2fb8ea5b5 100644 --- a/server/src/middleware/__generated__/swagger.json +++ b/server/src/middleware/__generated__/swagger.json @@ -489,21 +489,6 @@ "type": "object", "additionalProperties": false }, - "GetEventResponse": { - "properties": { - "error": { - "type": "string" - }, - "message": { - "type": "string" - }, - "data": { - "$ref": "#/components/schemas/Event" - } - }, - "type": "object", - "additionalProperties": false - }, "AllUserBookingSlotsResponse": { "properties": { "error": { @@ -1421,6 +1406,21 @@ }, "type": "object", "description": "Make all properties in T optional" + }, + "GetEventResponse": { + "properties": { + "error": { + "type": "string" + }, + "message": { + "type": "string" + }, + "data": { + "$ref": "#/components/schemas/Event" + } + }, + "type": "object", + "additionalProperties": false } }, "securitySchemes": { @@ -1848,34 +1848,6 @@ ] } }, - "/events/{id}": { - "get": { - "operationId": "GetEventById", - "responses": { - "200": { - "description": "Successfully fetched the event", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetEventResponse" - } - } - } - } - }, - "security": [], - "parameters": [ - { - "in": "path", - "name": "id", - "required": true, - "schema": { - "type": "string" - } - } - ] - } - }, "/bookings": { "get": { "operationId": "GetAllBookings", @@ -2496,6 +2468,40 @@ } } } + }, + "/admin/{id}": { + "get": { + "operationId": "GetEventById", + "responses": { + "200": { + "description": "Successfully fetched the event", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetEventResponse" + } + } + } + } + }, + "security": [ + { + "jwt": [ + "admin" + ] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ] + } } }, "servers": [ diff --git a/server/src/middleware/tests/AdminController.test.ts b/server/src/middleware/tests/AdminController.test.ts index d481d6afa..2fbd274f8 100644 --- a/server/src/middleware/tests/AdminController.test.ts +++ b/server/src/middleware/tests/AdminController.test.ts @@ -850,4 +850,29 @@ describe("AdminController endpoint tests", () => { ).toEqual(newDate) }) }) + describe("GET /events/:id", () => { + const event1: Event = { + title: "UASC New event", + physical_start_date: dateToFirestoreTimeStamp(new Date()), + location: "UASC", + sign_up_start_date: dateToFirestoreTimeStamp(new Date()), + sign_up_end_date: dateToFirestoreTimeStamp(new Date()) + } + const eventService = new EventService() + + it("should return the event details for a valid event ID", async () => { + const { id: id1 } = await eventService.createEvent(event1) + const res = await request.get(`/events/${id1}`).send() + expect(res.status).toEqual(200) + expect(res.body.data).toBeDefined() + expect(res.body.data.title).toEqual("UASC New event") + expect(res.body.data.location).toEqual("UASC") + }) + + it("should return 404 if the event does not exist", async () => { + const res = await request.get("/events/random-event").send() + expect(res.status).toEqual(404) + expect(res.body.error).toEqual("Event not found.") + }) + }) }) diff --git a/server/src/middleware/tests/EventController.test.ts b/server/src/middleware/tests/EventController.test.ts index 8510a2c52..9f8d64cbb 100644 --- a/server/src/middleware/tests/EventController.test.ts +++ b/server/src/middleware/tests/EventController.test.ts @@ -93,21 +93,4 @@ describe("EventController endpoint tests", () => { ) }) }) - - describe("GET /events/:id", () => { - it("should return the event details for a valid event ID", async () => { - const { id: id1 } = await eventService.createEvent(event1) - const res = await request.get(`/events/${id1}`).send() - expect(res.status).toEqual(200) - expect(res.body.data).toBeDefined() - expect(res.body.data.title).toEqual("UASC New event") - expect(res.body.data.location).toEqual("UASC") - }) - - it("should return 404 if the event does not exist", async () => { - const res = await request.get("/events/random-event").send() - expect(res.status).toEqual(404) - expect(res.body.error).toEqual("Event not found.") - }) - }) }) diff --git a/server/src/service-layer/controllers/AdminController.ts b/server/src/service-layer/controllers/AdminController.ts index bcd4055d7..941d308e8 100644 --- a/server/src/service-layer/controllers/AdminController.ts +++ b/server/src/service-layer/controllers/AdminController.ts @@ -58,7 +58,10 @@ import BookingUtils, { CHECK_OUT_TIME } from "business-layer/utils/BookingUtils" import BookingHistoryService from "data-layer/services/BookingHistoryService" -import { FetchLatestBookingHistoryEventResponse } from "service-layer/response-models/AdminResponse" +import { + FetchLatestBookingHistoryEventResponse, + GetEventResponse +} from "service-layer/response-models/AdminResponse" import { CreateEventBody } from "service-layer/request-models/EventRequests" import EventService from "data-layer/services/EventService" @@ -788,4 +791,25 @@ export class AdminController extends Controller { } this.setStatus(200) } + + @Get("{id}") + @SuccessResponse("200", "Successfully fetched the event") + public async getEventById(@Path() id: string): Promise { + try { + const eventService = new EventService() + const event = await eventService.getEventById(id) + + if (!event) { + this.setStatus(404) + return { error: "Event not found." } + } + + return { data: event } + } catch (e) { + this.setStatus(500) + return { + error: "Something went wrong when fetching the event, please try again" + } + } + } } diff --git a/server/src/service-layer/controllers/EventController.ts b/server/src/service-layer/controllers/EventController.ts index 696174770..e868333ed 100644 --- a/server/src/service-layer/controllers/EventController.ts +++ b/server/src/service-layer/controllers/EventController.ts @@ -1,9 +1,6 @@ import EventService from "data-layer/services/EventService" -import { - GetAllEventsResponse, - GetEventResponse -} from "service-layer/response-models/EventResponse" -import { Controller, Get, Path, Query, Route, SuccessResponse } from "tsoa" +import { GetAllEventsResponse } from "service-layer/response-models/EventResponse" +import { Controller, Get, Query, Route, SuccessResponse } from "tsoa" import { ONE_MINUTE_IN_MS } from "../../business-layer/utils/EventConstants" import { Timestamp } from "firebase-admin/firestore" @@ -48,25 +45,4 @@ export class EventController extends Controller { } } } - - @Get("{id}") - @SuccessResponse("200", "Successfully fetched the event") - public async getEventById(@Path() id: string): Promise { - try { - const eventService = new EventService() - const event = await eventService.getEventById(id) - - if (!event) { - this.setStatus(404) - return { error: "Event not found." } - } - - return { data: event } - } catch (e) { - this.setStatus(500) - return { - error: "Something went wrong when fetching the event, please try again" - } - } - } } diff --git a/server/src/service-layer/response-models/AdminResponse.ts b/server/src/service-layer/response-models/AdminResponse.ts index dd30e2341..f4e9eda6f 100644 --- a/server/src/service-layer/response-models/AdminResponse.ts +++ b/server/src/service-layer/response-models/AdminResponse.ts @@ -1,4 +1,4 @@ -import { BookingHistoryEvent } from "data-layer/models/firebase" +import { BookingHistoryEvent, Event } from "data-layer/models/firebase" import { CommonResponse, CursorPaginatedResponse } from "./CommonResponse" export interface FetchLatestBookingHistoryEventResponse @@ -6,3 +6,7 @@ export interface FetchLatestBookingHistoryEventResponse CommonResponse { historyEvents?: BookingHistoryEvent[] } + +export interface GetEventResponse extends CommonResponse { + data?: Event +} diff --git a/server/src/service-layer/response-models/EventResponse.ts b/server/src/service-layer/response-models/EventResponse.ts index a608e3955..ca7a6df19 100644 --- a/server/src/service-layer/response-models/EventResponse.ts +++ b/server/src/service-layer/response-models/EventResponse.ts @@ -7,7 +7,3 @@ export interface GetAllEventsResponse CursorPaginatedResponse { data?: DocumentDataWithUid[] } - -export interface GetEventResponse extends CommonResponse { - data?: Event -}