This commit is contained in:
shafi54 2026-03-22 16:38:37 +05:30
parent a0a05615b1
commit b49015b446
4 changed files with 53 additions and 24 deletions

View file

@ -16,7 +16,7 @@ import signedUrlCache from '@/src/lib/signed-url-cache';
import { seed } from '@/src/db/seed';
import '@/src/jobs/jobs-index';
import { startAutomatedJobs } from '@/src/lib/automatedJobs';
import { verifyToken } from '@/src/lib/jwt-utils';
import { verifyToken, UserJWTPayload, StaffJWTPayload } from '@/src/lib/jwt-utils';
seed()
initFunc()
@ -77,30 +77,35 @@ app.use('/api/trpc', createExpressMiddleware({
if (authHeader?.startsWith('Bearer ')) {
const token = authHeader.substring(7);
try {
const decoded = (await verifyToken(token)) as any;
const decoded = await verifyToken(token);
// Check if this is a staff token (has staffId)
if (decoded.staffId) {
if ('staffId' in decoded) {
const staffPayload = decoded as StaffJWTPayload;
// This is a staff token, verify staff exists
const staff = await db.query.staffUsers.findFirst({
where: eq(staffUsers.id, decoded.staffId),
where: eq(staffUsers.id, staffPayload.staffId),
});
if (staff) {
user=staffUser
staffUser = {
id: staff.id,
name: staff.name,
};
}
} else {
const userPayload = decoded as UserJWTPayload;
// This is a regular user token
user = decoded;
user = {
userId: userPayload.userId,
name: userPayload.name,
email: userPayload.email,
mobile: userPayload.mobile,
};
// Check if user is suspended
const details = await db.query.userDetails.findFirst({
where: eq(userDetails.userId, user.userId),
where: eq(userDetails.userId, userPayload.userId),
});
if (details?.isSuspended) {

View file

@ -1,6 +1,20 @@
import { SignJWT, jwtVerify, errors } from 'jose';
import { SignJWT, jwtVerify, errors, JWTPayload } from 'jose';
import { jwtSecret } from './env-exporter';
// JWT Payload Types
export interface UserJWTPayload extends JWTPayload {
userId: number;
name?: string;
email?: string;
mobile?: string;
roles?: string[];
}
export interface StaffJWTPayload extends JWTPayload {
staffId: number;
name: string;
}
// Convert string secret to Uint8Array
const getSecret = () => {
if (!jwtSecret) {
@ -14,7 +28,7 @@ const getSecret = () => {
* Compatible with tokens signed by jsonwebtoken library
*/
export const signToken = async (
payload: Record<string, any>,
payload: Record<string, unknown>,
expiresIn: string = '7d'
): Promise<string> => {
const secret = getSecret();
@ -30,7 +44,7 @@ export const signToken = async (
* Verify a JWT token
* Compatible with tokens signed by jsonwebtoken library
*/
export const verifyToken = async (token: string): Promise<Record<string, any>> => {
export const verifyToken = async (token: string): Promise<JWTPayload> => {
try {
const secret = getSecret();
const { payload } = await jwtVerify(token, secret);
@ -49,8 +63,10 @@ export const verifyToken = async (token: string): Promise<Record<string, any>> =
/**
* Check if an error is a JWT-related error
*/
export const isJWTError = (error: any): boolean => {
export const isJWTError = (error: unknown): boolean => {
return error instanceof errors.JOSEError ||
error?.message?.includes('token') ||
error?.message?.includes('JWT');
(error instanceof Error && (
error.message.includes('token') ||
error.message.includes('JWT')
));
};

View file

@ -3,7 +3,7 @@ import { db } from '@/src/db/db_index'
import { staffUsers, userDetails } from '@/src/db/schema'
import { eq } from 'drizzle-orm';
import { ApiError } from '@/src/lib/api-error'
import { verifyToken } from '@/src/lib/jwt-utils'
import { verifyToken, UserJWTPayload, StaffJWTPayload } from '@/src/lib/jwt-utils'
interface AuthenticatedRequest extends Request {
user?: {
@ -29,13 +29,14 @@ export const authenticateUser = async (req: AuthenticatedRequest, res: Response,
const token = authHeader.substring(7);
console.log(req.headers)
const decoded = (await verifyToken(token)) as any;
const decoded = await verifyToken(token);
// Check if this is a staff token (has staffId)
if (decoded.staffId) {
if ('staffId' in decoded) {
const staffPayload = decoded as StaffJWTPayload;
// This is a staff token, verify staff exists
const staff = await db.query.staffUsers.findFirst({
where: eq(staffUsers.id, decoded.staffId),
where: eq(staffUsers.id, staffPayload.staffId),
});
if (!staff) {
@ -47,12 +48,18 @@ export const authenticateUser = async (req: AuthenticatedRequest, res: Response,
name: staff.name,
};
} else {
const userPayload = decoded as UserJWTPayload;
// This is a regular user token
req.user = decoded;
req.user = {
userId: userPayload.userId,
name: userPayload.name,
email: userPayload.email,
mobile: userPayload.mobile,
};
// Check if user is suspended
const details = await db.query.userDetails.findFirst({
where: eq(userDetails.userId, decoded.userId),
where: eq(userDetails.userId, userPayload.userId),
});
if (details?.isSuspended) {

View file

@ -3,7 +3,7 @@ import { db } from '@/src/db/db_index'
import { staffUsers } from '@/src/db/schema'
import { eq } from 'drizzle-orm';
import { ApiError } from '@/src/lib/api-error'
import { verifyToken } from '@/src/lib/jwt-utils'
import { verifyToken, StaffJWTPayload } from '@/src/lib/jwt-utils'
// Extend Request interface to include staffUser
declare global {
@ -20,9 +20,10 @@ declare global {
/**
* Verify JWT token and extract payload
*/
const verifyStaffToken = async (token: string) => {
const verifyStaffToken = async (token: string): Promise<StaffJWTPayload> => {
try {
return await verifyToken(token);
const payload = await verifyToken(token);
return payload as StaffJWTPayload;
} catch (error) {
throw new ApiError('Access denied. Invalid auth credentials', 401);
}
@ -47,7 +48,7 @@ export const authenticateStaff = async (req: Request, res: Response, next: NextF
}
// Verify token and extract payload
const decoded = (await verifyStaffToken(token)) as any;
const decoded = await verifyStaffToken(token);
// Verify staffId exists in token
if (!decoded.staffId) {