MD.Riad Rayhan
Node.js + Socket.IO backend (migrated from FastAPI)
839aef2 verified
Raw History Blame Contribute Delete
1.68 kB
import { decodeToken } from '../utils/security.js';
import { User } from '../models/index.js';
/** Express error helper that mirrors FastAPI's {detail} 4xx body. */
export function httpError(status, detail) {
const err = new Error(detail);
err.status = status;
err.detail = detail;
return err;
}
function extractToken(req) {
const header = req.headers.authorization || '';
if (!header.startsWith('Bearer ')) return null;
return header.slice(7).trim();
}
/** Resolve the current user from a Bearer access token, or throw 401. */
export async function resolveUser(req) {
const token = extractToken(req);
if (!token) throw httpError(401, 'Not authenticated');
const payload = decodeToken(token);
if (payload.type !== 'access') throw httpError(401, 'Invalid token type');
const userId = payload.sub;
if (!userId) throw httpError(401, 'Could not validate credentials');
const user = await User.findByPk(userId);
if (!user) throw httpError(401, 'User not found');
return user;
}
/** Middleware: require a valid logged-in user (any role). */
export function requireUser(req, res, next) {
resolveUser(req)
.then((user) => {
req.user = user;
next();
})
.catch(next);
}
/** Middleware: require an admin or superadmin. */
export function requireAdmin(req, res, next) {
resolveUser(req)
.then((user) => {
if (!['admin', 'superadmin'].includes(user.role)) {
throw httpError(403, 'Not enough permissions');
}
req.user = user;
next();
})
.catch(next);
}
export default { requireUser, requireAdmin, resolveUser, httpError };