diff --git a/api-examples/deleteEvent.rest b/api-examples/deleteEvent.rest new file mode 100644 index 0000000..2763467 --- /dev/null +++ b/api-examples/deleteEvent.rest @@ -0,0 +1,3 @@ +DELETE http://localhost:3000/events/683f38cbecb0f8e7404c76a2 +Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2ODNkODY0YzQ5YmI1MDYxNTM3YjA1NTMiLCJuYW1lX2ZpcnN0IjoiQm9iIiwibmFtZV9sYXN0IjoiQnVpbGRlciIsImVtYWlsIjoiYm9iQGJ1aWxkZXIuY29tIiwidXNlcm5hbWUiOiJib2IiLCJzYXZlZF9ldmVudHMiOltdLCJyb2xlIjoidXNlciJ9.8f-bElJ6461QVgMFeA0rE72ionI5iuB7JOLrsa159fQ diff --git a/api-examples/login.rest b/api-examples/login.rest index e79fc7b..37005eb 100644 --- a/api-examples/login.rest +++ b/api-examples/login.rest @@ -2,7 +2,7 @@ POST http://localhost:3000/auth/login Content-Type: application/json { - "email": "admin@example.com", - "password": "supersecretadminpassword", - "username": "admin" + "email": "bob@builder.com", + "password": "builder", + "username": "bob" } diff --git a/api-examples/updateEvent.rest b/api-examples/updateEvent.rest new file mode 100644 index 0000000..a90fa02 --- /dev/null +++ b/api-examples/updateEvent.rest @@ -0,0 +1,14 @@ +PUT http://localhost:3000/events/683f38cbecb0f8e7404c76a1 +Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2ODNkODY0YzQ5YmI1MDYxNTM3YjA1NTMiLCJuYW1lX2ZpcnN0IjoiQm9iIiwibmFtZV9sYXN0IjoiQnVpbGRlciIsImVtYWlsIjoiYm9iQGJ1aWxkZXIuY29tIiwidXNlcm5hbWUiOiJib2IiLCJzYXZlZF9ldmVudHMiOltdLCJyb2xlIjoidXNlciJ9.8f-bElJ6461QVgMFeA0rE72ionI5iuB7JOLrsa159fQ + +{ + "mode": "other", + "name": "Something", + "description": "For something", + "location": "Earth", + "date": "Tomorrow", + "price": 42, + "distance": 0, + "url": "http://localhost:3000" +} \ No newline at end of file diff --git a/src/controllers/event.controller.ts b/src/controllers/event.controller.ts index a452c34..faebce5 100644 --- a/src/controllers/event.controller.ts +++ b/src/controllers/event.controller.ts @@ -1,8 +1,7 @@ -// deno-lint-ignore-file require-await import { Context, ObjectId, RouterContext, Status } from '../../deps.ts'; import { eventService } from '../services/event.service.ts'; import { generateEvents } from '../services/openai.service.ts'; -import { eventFilterSchema } from 'models/event.model.ts'; +import { eventFilterSchema, FullEvent } from 'models/event.model.ts'; export const getAllEvents = async (ctx: Context) => { const params = ctx.request.url.searchParams; @@ -55,6 +54,69 @@ export const getEventById = async (ctx: RouterContext<'/:id'>) => { ctx.response.body = event; }; +export const updateEventById = async (ctx: RouterContext<'/:id'>) => { + const user = ctx.state.user; + + if (!user) { + ctx.response.status = Status.Unauthorized; + ctx.response.body = { message: 'User not authenticated' }; + return; + } + + const id: string = ctx.params.id; + const event: FullEvent = await ctx.request.body.json(); + + if (!ObjectId.isValid(id)) { + ctx.response.status = Status.BadRequest; + ctx.response.body = `Invalid event id "${id}"`; + return; + } + + if (!eventService.isEvent(event)) { + ctx.response.status = Status.BadRequest; + ctx.response.body = `Failed to validate event body`; + return; + } + + const result = await eventService.updateEventById(id, event); + + if (!result.acknowledged) { + ctx.response.status = Status.NotFound; + ctx.response.body = `Failed to update event by id "${id}"`; + return; + } + + ctx.response.body = { message: `Updated event id "${id}"` }; +}; + +export const deleteEventById = async (ctx: RouterContext<'/:id'>) => { + const user = ctx.state.user; + + if (!user) { + ctx.response.status = Status.Unauthorized; + ctx.response.body = { message: 'User not authenticated' }; + return; + } + + const id: string = ctx.params.id; + + if (!ObjectId.isValid(id)) { + ctx.response.status = Status.BadRequest; + ctx.response.body = `Invalid event id "${id}"`; + return; + } + + const result = await eventService.deleteEventById(id); + + if (result.deletedCount == 0) { + ctx.response.status = Status.NotFound; + ctx.response.body = `Could not find event id "${id}"`; + return; + } + + ctx.response.body = { message: `Successfully deleted event id "${id}"` }; +}; + export const saveNewEvent = async (ctx: Context) => { // Things to note. Will this need admin authorisation? Possible need to implement token auth on this route or admin auth middleware? const event = await ctx.request.body.json(); @@ -97,13 +159,3 @@ export const saveEventsCronHandler = async (ctx: Context) => { console.log('There were no events to save'); } }; - -export const updateEvent = async (ctx: Context) => { - // TODO: Update event in DB - ctx.response.body = { message: `Update event of params.id` }; -}; - -export const deleteEvent = async (ctx: Context) => { - // TODO: Delete event from DB - ctx.response.body = { message: `Delete event params.id` }; -}; diff --git a/src/routes/event.routes.ts b/src/routes/event.routes.ts index eddfb69..b78f17b 100644 --- a/src/routes/event.routes.ts +++ b/src/routes/event.routes.ts @@ -1,10 +1,14 @@ import { Router } from '../../deps.ts'; import { + deleteEventById, getAllEvents, getEventById, saveEventsCronHandler, saveNewEvent, + updateEventById, } from '../controllers/event.controller.ts'; +import ProtectRoute from '../middleware/protectRoute.ts'; +import protectAdmin from '../middleware/requireAdmin.ts'; const router = new Router(); @@ -13,11 +17,11 @@ const router = new Router(); // -> to controllers router.get('/', getAllEvents); router.get('/:id', getEventById); +router.put('/:id', ProtectRoute, protectAdmin, updateEventById); +router.delete('/:id', ProtectRoute, protectAdmin, deleteEventById); router.post('/save-event', saveNewEvent); router.post('/cron/save-events', saveEventsCronHandler); // router.post("/") -// router.put("/:id", updateEvent) -// router.delete("/:id", deleteEvent) // router.post("/generate", generateEvents) (using the openAi service) diff --git a/src/services/event.service.ts b/src/services/event.service.ts index 67bfa7c..db9d2ff 100644 --- a/src/services/event.service.ts +++ b/src/services/event.service.ts @@ -32,6 +32,14 @@ const getEventById = async (id: string): Promise => { return await events.findOne({ _id: new ObjectId(id) }); }; +const updateEventById = async (id: string, event: FullEvent) => { + return await events.updateOne({ _id: new ObjectId(id) }, { $set: event }); +}; + +const deleteEventById = async (id: string) => { + return await events.deleteOne({ _id: new ObjectId(id) }); +}; + const databaseIncludes = async (event: FullEvent): Promise => { const existingEvent = await events.findOne({ eventKey: event.eventKey }); return existingEvent !== null; @@ -93,6 +101,8 @@ const saveEvents = async (input: Event | CompleteEventType) => { export const eventService = { getAllEvents, getEventById, + updateEventById, + deleteEventById, saveEvents, isEvent, };