diff --git a/controllers/auth.ts b/controllers/auth.ts index 07d1476..666b2e7 100644 --- a/controllers/auth.ts +++ b/controllers/auth.ts @@ -4,6 +4,7 @@ import { NextFunction, Request, Response } from 'express'; import logger from '../utils/logger'; import * as authService from '../services/authService'; import { apiResponse } from '../@types/apiReponse'; +import { MicrosoftOAuthJson } from '../@types/providers'; /** * Makes authentication call to google statergy @@ -87,27 +88,33 @@ const microsoftAuthCallback = ( const rCalUiUrl = new URL(config.get('services.rCalUi.baseUrl')); try { - return passport.authenticate('microsoft', {}, async (err, _, user) => { - if (err) { - logger.error(err); - return res.boom(Boom.unauthorized('User cannot be authenticated')); + return passport.authenticate( + 'microsoft', + {}, + async (err: any, _: any, user: { _json: MicrosoftOAuthJson }) => { + if (err) { + logger.error(err); + return res.boom(Boom.unauthorized('User cannot be authenticated')); + } + const userData = await authService.loginOrSignupWithMicrosoft( + user._json + ); + const token = authService.generateAuthToken({ userId: userData?.id }); + + // respond with a cookie + res.cookie(config.get('userAccessToken.cookieName'), token, { + domain: rCalUiUrl.hostname, + expires: new Date( + Date.now() + config.get('userAccessToken.ttl') * 1000 + ), + httpOnly: true, + secure: true, + sameSite: 'lax', + }); + + return res.redirect(rCalUiUrl.href); } - const userData = await authService.loginOrSignupWithMicrosoft(user._json); - const token = authService.generateAuthToken({ userId: userData?.id }); - - // respond with a cookie - res.cookie(config.get('userAccessToken.cookieName'), token, { - domain: rCalUiUrl.hostname, - expires: new Date( - Date.now() + config.get('userAccessToken.ttl') * 1000 - ), - httpOnly: true, - secure: true, - sameSite: 'lax', - }); - - return res.redirect(rCalUiUrl.href); - })(req, res, next); + )(req, res, next); } catch (err: any) { logger.error(err); diff --git a/controllers/events.ts b/controllers/events.ts index 71da9f1..3636ff0 100644 --- a/controllers/events.ts +++ b/controllers/events.ts @@ -1,8 +1,10 @@ +import { z } from 'zod'; import { Event, EventType } from '@prisma/client'; import { Request, Response } from 'express'; import Boom from '@hapi/boom'; import prisma from '../prisma/prisma'; import { findEvent, findEventFromCalendar } from '../services/eventsService'; +import { getAcknowledgementSchema } from '../middlewares/validators/zod-schemas/events'; /** * Route used to post event @@ -99,7 +101,10 @@ const getEvents = async (req: Request, res: Response): Promise => { * @param req {Object} - Express request object * @param res {Object} - Express response object */ -const getCalendarEvents = async (req: Request, res: Response): Promise => { +const getCalendarEvents = async ( + req: Request, + res: Response +): Promise => { try { const { calendarId } = req.params; const { startTime, endTime } = req.query; @@ -120,4 +125,40 @@ const getCalendarEvents = async (req: Request, res: Response): Promise => { } }; -export { postEvent, getEvents, getCalendarEvents }; +type TAcknowledgementStatusReq = z.infer; + +const getAcknowledgementStatus = async ( + req: Request, + res: Response +): Promise => { + const { eventId, attendeeId } = req.params; + const { status } = req.body as TAcknowledgementStatusReq['body']; + + const attendeeData = await prisma.attendees.findFirst({ + where: { + eventId: Number(eventId), + attendeeId: Number(attendeeId), + }, + }); + + if (attendeeData === null) { + return res.boom(Boom.badRequest('Attendee not found')); + } + + const updatedData = await prisma.attendees.update({ + where: { + id: attendeeData.id, + }, + data: { + acknowledgement: status, + }, + }); + + if (updatedData.acknowledgement === status) { + return res.json({ message: 'Acknowledgement status updated' }); + } else { + return res.boom(Boom.internal('Something went wrong')); + } +}; + +export { postEvent, getEvents, getCalendarEvents, getAcknowledgementStatus }; diff --git a/middlewares/validators/zod-schemas/events.ts b/middlewares/validators/zod-schemas/events.ts index 8460cac..795f101 100644 --- a/middlewares/validators/zod-schemas/events.ts +++ b/middlewares/validators/zod-schemas/events.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import { EventAcknowledgements } from '@prisma/client'; const EVENT_TYPE = ['event'] as const; @@ -24,6 +25,22 @@ const getEventSchema = z.object({ }), }); +const UPDATED_ACKNOWLEDGEMENT_TYPES = [ + EventAcknowledgements.ACCEPTED, + EventAcknowledgements.DECLINED, + EventAcknowledgements.TENTATIVE, +] as const; + +const getAcknowledgementSchema = z.object({ + params: z.object({ + eventId: z.preprocess((a) => Number(a), z.number().positive()), + attendeeId: z.preprocess((a) => Number(a), z.number().positive()), + }), + body: z.object({ + status: z.enum(UPDATED_ACKNOWLEDGEMENT_TYPES), + }), +}); + const getCalenderEventSchema = z.object({ params: z.object({ calendarId: z.preprocess((a) => Number(a), z.number().positive()), @@ -34,4 +51,9 @@ const getCalenderEventSchema = z.object({ }), }); -export { postEventSchema, getEventSchema, getCalenderEventSchema }; +export { + postEventSchema, + getEventSchema, + getCalenderEventSchema, + getAcknowledgementSchema, +}; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 40b48e0..46fbf7d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -95,12 +95,20 @@ enum RecurringFrequency { HOURLY } +enum EventAcknowledgements { + AWAITING + ACCEPTED + DECLINED + TENTATIVE +} + model Attendees { - id Int @id @default(autoincrement()) - eventId Int - event Event @relation(fields: [eventId], references: [id]) - attendeeId Int - attendee Users @relation(fields: [attendeeId], references: [id]) + id Int @id @default(autoincrement()) + eventId Int + event Event @relation(fields: [eventId], references: [id]) + attendeeId Int + attendee Users @relation(fields: [attendeeId], references: [id]) + acknowledgement EventAcknowledgements @default(AWAITING) } enum CalendarType { diff --git a/routes/events.ts b/routes/events.ts index 779bac8..efc59f9 100644 --- a/routes/events.ts +++ b/routes/events.ts @@ -1,8 +1,14 @@ import { Router } from 'express'; -import { getCalendarEvents, getEvents, postEvent } from '../controllers/events'; +import { + getAcknowledgementStatus, + getCalendarEvents, + getEvents, + postEvent, +} from '../controllers/events'; import authenticate from '../middlewares/authenticate'; import { validate } from '../middlewares/validators/validator'; import { + getAcknowledgementSchema, getCalenderEventSchema, getEventSchema, postEventSchema, @@ -13,6 +19,14 @@ const router = Router(); /* eslint-disable @typescript-eslint/no-misused-promises */ router.post('/', authenticate, validate(postEventSchema), postEvent); router.get('/:eventId', authenticate, validate(getEventSchema), getEvents); + +router.patch( + '/:eventId/attendee/:attendeeId', + // authenticate, + validate(getAcknowledgementSchema), + getAcknowledgementStatus +); + router.get( '/calendar/:calendarId', authenticate,