import jwt from 'jsonwebtoken'; import httpStatus from 'http-status'; import ApiError from '../../utils/helper/ApiError'; import config from '../../../config/config'; import { ROLE } from '@/common/utils/constants/common.constant'; import { prisma } from '../../database/prisma.client'; interface DecodedToken { id?: number; sub?: string | number; role?: string; iat: number; exp: number; } export async function verifyAnyToken( token: string ): Promise<{ id: number; roleXid: number; role?: string }> { if (!token) { throw new ApiError(httpStatus.UNAUTHORIZED, 'Please authenticate'); } try { const decoded = jwt.verify(token, config.jwt.secret) as unknown as DecodedToken; const userId = decoded.id ?? (decoded.sub ? Number(decoded.sub) : null); if (!userId) { throw new ApiError(httpStatus.UNAUTHORIZED, 'Invalid token payload'); } const user = await prisma.user.findUnique({ where: { id: userId }, include: { role: true }, }); const latestToken = await prisma.token.findFirst({ where: { userXid: userId }, orderBy: { id: 'desc' }, }); if (latestToken?.isBlackListed === true) { throw new ApiError(401, 'This session is expired. Please login.'); } if (!user) { throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found'); } if (user.isActive === false) { throw new ApiError( httpStatus.FORBIDDEN, 'Your account is deactivated by admin.' ); } if (user.roleXid !== ROLE.USER && user.roleXid !== ROLE.HOST) { throw new ApiError(httpStatus.FORBIDDEN, 'Access denied.'); } return { id: user.id, roleXid: user.roleXid || 0, role: user.role?.roleName }; } catch (error) { if (error instanceof jwt.TokenExpiredError) { throw new ApiError( httpStatus.UNAUTHORIZED, 'Your session has expired. Please log in again.' ); } if (error instanceof ApiError) { throw error; } throw new ApiError( httpStatus.FORBIDDEN, 'Invalid or expired authentication token.' ); } }