11const jwt = require ( 'jsonwebtoken' ) ;
2- const { User } = require ( '../models' ) ;
32
43/**
5- * Ensures the request has a valid, unexpired token and attaches the decoded
6- * user data (including userId, role, and guestId) to req.user.
4+ * Middleware to authenticate JWT token
75 */
8- const authenticateToken = async ( req , res , next ) => {
6+ const authenticateToken = ( req , res , next ) => {
97 try {
8+ // Get token from header
109 const authHeader = req . headers [ 'authorization' ] ;
11- const token = authHeader && authHeader . split ( ' ' ) [ 1 ] ;
10+ const token = authHeader && authHeader . split ( ' ' ) [ 1 ] ; // Bearer TOKEN
1211
1312 if ( ! token ) {
14- return res . status ( 401 ) . json ( {
13+ return res . status ( 401 ) . json ( {
1514 success : false ,
16- error : 'Access token required'
15+ error : 'Access token is required'
1716 } ) ;
1817 }
1918
20- // 1. Verify and Decode the token
21- const decoded = jwt . verify ( token , process . env . JWT_SECRET ) ;
22-
23- // 2. Attach the DECODED JWT payload to req.user
24- // This payload already contains userId, role, and guestId (if present in the token).
25- // This allows controllers to access req.user.guestId, req.user.userId, etc., without
26- // needing another complex database query here.
27- req . user = decoded ;
28-
29- // Optional Security Check: Verify user still exists in the database
30- // We only select essential, existing columns (user_id, username)
31- const user = await User . findByPk ( decoded . userId , {
32- attributes : [ 'user_id' , 'username' ]
33- } ) ;
34-
35- if ( ! user ) {
36- return res . status ( 401 ) . json ( {
37- success : false ,
38- error : 'Invalid token or user not found in database'
39- } ) ;
40- }
19+ // Verify token
20+ jwt . verify ( token , process . env . JWT_SECRET , ( err , user ) => {
21+ if ( err ) {
22+ return res . status ( 403 ) . json ( {
23+ success : false ,
24+ error : 'Invalid or expired token'
25+ } ) ;
26+ }
4127
42- // Since the database does not have an 'is_active' column, we remove that faulty check entirely.
43-
44- next ( ) ;
28+ // Attach user info to request
29+ req . user = user ;
30+ next ( ) ;
31+ } ) ;
4532 } catch ( error ) {
46- // This catches JWT errors (expired, tampered, invalid signature)
47- // The previous error of 'user inactive' is now resolved.
48- return res . status ( 403 ) . json ( {
33+ return res . status ( 500 ) . json ( {
4934 success : false ,
50- error : 'Invalid or expired token'
35+ error : 'Token authentication failed'
5136 } ) ;
5237 }
5338} ;
5439
5540/**
56- * Authorizes the user based on their role included in the JWT payload.
41+ * Middleware to authorize based on user roles
42+ * Usage: authorizeRoles('Admin', 'Manager')
5743 */
58- // In middleware/auth.js
59-
60- // const authorizeRoles = (...roles) => {
61- // return (req, res, next) => {
62-
63- // // 1. Check 1: Ensure the user object is attached and has a role property.
64- // // We must return a clear error if the role is truly missing from the token.
65- // if (!req.user || req.user.role === undefined || req.user.role === null) {
66- // return res.status(403).json({
67- // success: false,
68- // error: 'Access denied. User role not defined in token.' // More specific message
69- // });
70- // }
71-
72- // // 2. Perform Case-Insensitive Comparison
73- // // Ensure the role is treated as a string before calling toLowerCase().
74- // const userRole = String(req.user.role).toLowerCase();
75- // const allowedRoles = roles.map(role => String(role).toLowerCase()); // Also convert allowed roles to strings
76-
77- // if (!allowedRoles.includes(userRole)) {
78- // return res.status(403).json({
79- // success: false,
80- // error: 'Access denied. Insufficient permissions.'
81- // });
82- // }
83-
84- // next();
85- // };
86- // };
87-
88- const authorizeRoles = ( ...roles ) => {
44+ const authorizeRoles = ( ...allowedRoles ) => {
8945 return ( req , res , next ) => {
90- // 1. Ensure req.user and req.user.role exist
91- if ( ! req . user || ! req . user . role ) {
92- return res . status ( 403 ) . json ( {
46+ if ( ! req . user ) {
47+ return res . status ( 401 ) . json ( {
9348 success : false ,
94- error : 'Access denied. User role not defined in token. '
49+ error : 'Authentication required '
9550 } ) ;
9651 }
9752
98- // 2. Normalize user role: trim spaces and lowercase
99- const userRole = String ( req . user . role ) . trim ( ) . toLowerCase ( ) ;
100-
101- // 3. Normalize allowed roles
102- const allowedRoles = roles . map ( role => String ( role ) . trim ( ) . toLowerCase ( ) ) ;
53+ const userRole = req . user . role ;
10354
104- // 4. Debug: log roles (remove or comment out in production)
105- console . log ( `DEBUG: userRole="${ userRole } ", allowedRoles=[${ allowedRoles . join ( ', ' ) } ]` ) ;
106-
107- // 5. Check if the user's role exists in allowedRoles
55+ // Check if user's role is in the allowed roles
10856 if ( ! allowedRoles . includes ( userRole ) ) {
10957 return res . status ( 403 ) . json ( {
11058 success : false ,
111- error : `Access denied. User role " ${ req . user . role } " insufficient. `
59+ error : `Access denied. Required roles: ${ allowedRoles . join ( ', ' ) } `
11260 } ) ;
11361 }
11462
11563 next ( ) ;
11664 } ;
11765} ;
11866
119- module . exports = { authorizeRoles } ;
120-
121-
122-
123-
12467/**
125- * Optionally authenticates a token if one is present, but allows the request to continue if not.
68+ * Optional authentication - doesn't fail if no token
69+ * Useful for endpoints that work for both authenticated and public users
12670 */
127- const optionalAuth = async ( req , res , next ) => {
71+ const optionalAuth = ( req , res , next ) => {
12872 try {
12973 const authHeader = req . headers [ 'authorization' ] ;
13074 const token = authHeader && authHeader . split ( ' ' ) [ 1 ] ;
13175
132- if ( token ) {
133- const decoded = jwt . verify ( token , process . env . JWT_SECRET ) ;
134-
135- // Optionally verify user existence again, but primarily attach the payload data
136- const user = await User . findByPk ( decoded . userId , {
137- attributes : [ 'user_id' , 'username' ]
138- } ) ;
76+ if ( ! token ) {
77+ // No token provided, continue without user
78+ req . user = null ;
79+ return next ( ) ;
80+ }
13981
140- if ( user ) {
141- req . user = decoded ;
82+ // Verify token if provided
83+ jwt . verify ( token , process . env . JWT_SECRET , ( err , user ) => {
84+ if ( err ) {
85+ // Invalid token, continue without user
86+ req . user = null ;
87+ } else {
88+ // Valid token, attach user
89+ req . user = user ;
14290 }
143- }
144- next ( ) ;
91+ next ( ) ;
92+ } ) ;
14593 } catch ( error ) {
146- // Do not throw an error if token is invalid/expired; just proceed without req.user
94+ // Error in processing, continue without user
95+ req . user = null ;
14796 next ( ) ;
14897 }
14998} ;
15099
151- module . exports = {
152- authenticateToken,
153- authorizeRoles,
154- optionalAuth
155- } ;
100+ module . exports = {
101+ authenticateToken,
102+ authorizeRoles,
103+ optionalAuth
104+ } ;
0 commit comments