49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import passport from 'passport';
|
|
import httpStatus from 'http-status';
|
|
import ApiError from '../utils/ApiError';
|
|
import { roleRights } from '../config/roles';
|
|
import { NextFunction, Request, Response } from 'express';
|
|
import { User } from '@prisma/client';
|
|
|
|
const verifyCallback =
|
|
(
|
|
req: any,
|
|
resolve: (value?: unknown) => void,
|
|
reject: (reason?: unknown) => void,
|
|
requiredRights: string[]
|
|
) =>
|
|
async (err: unknown, user: User | false, info: unknown) => {
|
|
if (err || info || !user) {
|
|
return reject(new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate'));
|
|
}
|
|
req.user = user;
|
|
|
|
if (requiredRights.length) {
|
|
const userRights = roleRights.get(user.role) ?? [];
|
|
const hasRequiredRights = requiredRights.every((requiredRight) =>
|
|
userRights.includes(requiredRight)
|
|
);
|
|
if (!hasRequiredRights && req.params.userId !== user.id) {
|
|
return reject(new ApiError(httpStatus.FORBIDDEN, 'Forbidden'));
|
|
}
|
|
}
|
|
|
|
resolve();
|
|
};
|
|
|
|
const auth =
|
|
(...requiredRights: string[]) =>
|
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
return new Promise((resolve, reject) => {
|
|
passport.authenticate(
|
|
'jwt',
|
|
{ session: false },
|
|
verifyCallback(req, resolve, reject, requiredRights)
|
|
)(req, res, next);
|
|
})
|
|
.then(() => next())
|
|
.catch((err) => next(err));
|
|
};
|
|
|
|
export default auth;
|