Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/authorization #98

Merged
merged 4 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions middlewares/authorize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Boom from '@hapi/boom';
import { NextFunction, Request, Response } from 'express';
import { findCalendarWithId, findEventWithId } from '../services/eventsService';

/**
* Middleware to authorize if the calendar belongs to the user
*
* @param req {Object} - Express request object
* @param res {Object} - Express response object
* @param next {Function} - Express middleware function
* @return {Object} - Returns unauthenticated object if token is invalid
*/
const calendarBelongsToUser = async (
req: Request,
res: Response,
next: NextFunction
): Promise<any | Response> => {
try {
const userId = req.userData.id;
const calendarId = +(req.params.calendarId || req.body.calendarId);

const calendarData = await findCalendarWithId(calendarId);

if (calendarData === null) {
logger.error('Calendar not found.');
return res.boom(Boom.notFound('Calendar not found'));
}

if (calendarData.ownerId !== userId) {
logger.info('Calendar does not belong to user');
return res.boom(Boom.forbidden('Calendar does not belong to user'));
}

return next();
} catch (err: any) {
logger.error('An internal server error occurred', { err: err.stack });
return res.boom(
Boom.badImplementation('An internal server error occurred')
);
}
};

const eventBelongsToUser = async (
req: Request,
res: Response,
next: NextFunction
): Promise<any | Response> => {
try {
const { eventId } = req.params;
const userId = req.userData.id;

const eventData = await findEventWithId(+eventId);

if (eventData === null) {
logger.info('Event not found');
return res.boom(Boom.notFound());
}

if (eventData.ownerId !== userId) {
logger.info('Event does not belong to user');
return res.boom(Boom.forbidden('Event does not belong to user'));
}

return next();
} catch (err: any) {
logger.error('An internal server error occurred', { err: err.stack });
return res.boom(
Boom.badImplementation('An internal server error occurred')
);
}
};

export { calendarBelongsToUser, eventBelongsToUser };
29 changes: 26 additions & 3 deletions routes/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,40 @@ import {
postEventSchema,
patchEventSchema,
} from '../middlewares/validators/zod-schemas/events';
import {
calendarBelongsToUser,
eventBelongsToUser,
} from '../middlewares/authorize';

const router = Router();

/* eslint-disable @typescript-eslint/no-misused-promises */
router.post('/', authenticate, validate(postEventSchema), postEvent);
router.patch('/:eventId', authenticate, validate(patchEventSchema), patchEvent);
router.get('/:eventId', authenticate, validate(getEventSchema), getEvents);
router.post(
'/',
authenticate,
validate(postEventSchema),
calendarBelongsToUser,
postEvent
);
router.patch(
'/:eventId',
authenticate,
validate(patchEventSchema),
eventBelongsToUser,
patchEvent
);
router.get(
'/:eventId',
authenticate,
validate(getEventSchema),
eventBelongsToUser,
getEvents
);
router.get(
'/calendar/:calendarId',
authenticate,
validate(getCalenderEventSchema),
calendarBelongsToUser,
getCalendarEvents
);
/* eslint-disable @typescript-eslint/no-misused-promises */
Expand Down
12 changes: 7 additions & 5 deletions server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import app from './app';
import { version } from './package.json';
import ErrnoException = NodeJS.ErrnoException;
import checkDatabaseConnection from './utils/prisma';
import { env } from 'process';

// Initialise globals
global.config = config;
Expand All @@ -27,11 +28,12 @@ server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
* Checks if DB is connected
*/
void checkDatabaseConnection();

if (String(env.NODE_ENV) !== 'test') {
/**
* Checks if DB is connected
*/
void checkDatabaseConnection();
}
/**
* Event listener for HTTP server "error" event.
*/
Expand Down
24 changes: 23 additions & 1 deletion services/eventsService.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Calendar, Event } from '@prisma/client';
import { eventWithAttendees } from '../@types/apiReponse';
import prisma from '../prisma/prisma';

Expand Down Expand Up @@ -69,4 +70,25 @@ const findEventFromCalendar = async (
}
};

export { findEvent, findEventFromCalendar };
const findCalendarWithId = async (
calendarId: number
): Promise<Calendar | null> => {
const calendarData = await prisma.calendar.findUnique({
where: { id: calendarId },
});
return calendarData;
};

const findEventWithId = async (eventId: number): Promise<Event | null> => {
const eventResponse = await prisma.event.findUnique({
where: { id: +eventId },
});
return eventResponse;
};

export {
findEvent,
findEventFromCalendar,
findCalendarWithId,
findEventWithId,
};
2 changes: 1 addition & 1 deletion utils/prisma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import prisma from '../prisma/prisma';
async function checkDatabaseConnection(): Promise<void> {
try {
await prisma.$connect();
logger.error('Database connected.');
logger.info('Database connected.');
} catch (error) {
logger.error('Database connection failed:', error);
process.exit(1);
Expand Down
Loading