diff options
author | 2025-04-29 10:47:43 +0530 | |
---|---|---|
committer | 2025-04-29 10:47:43 +0530 | |
commit | a2e0a65b2599267efe94d665d6305f59b225bbd5 (patch) | |
tree | e2cef2031e3f7655e0c5f419020a3f1064c3b7b8 /backend/src | |
parent | 570bf0f3f065d583d6f94ecfc61aae93ba3e43de (diff) | |
download | restaurant-a2e0a65b2599267efe94d665d6305f59b225bbd5.tar.gz restaurant-a2e0a65b2599267efe94d665d6305f59b225bbd5.tar.bz2 restaurant-a2e0a65b2599267efe94d665d6305f59b225bbd5.zip |
Diffstat (limited to 'backend/src')
-rw-r--r-- | backend/src/config/database.js | 14 | ||||
-rw-r--r-- | backend/src/config/env.js | 11 | ||||
-rw-r--r-- | backend/src/config/logger.js | 7 | ||||
-rw-r--r-- | backend/src/controllers/auth.controller.js | 130 | ||||
-rw-r--r-- | backend/src/index.js | 48 | ||||
-rw-r--r-- | backend/src/middleware/auth.middleware.js | 63 | ||||
-rw-r--r-- | backend/src/middleware/error.middleware.js | 40 | ||||
-rw-r--r-- | backend/src/models/Category.js | 34 | ||||
-rw-r--r-- | backend/src/models/Feedback.js | 61 | ||||
-rw-r--r-- | backend/src/models/MenuItem.js | 73 | ||||
-rw-r--r-- | backend/src/models/Order.js | 60 | ||||
-rw-r--r-- | backend/src/models/OrderItem.js | 32 | ||||
-rw-r--r-- | backend/src/models/Reservation.js | 54 | ||||
-rw-r--r-- | backend/src/models/Table.js | 36 | ||||
-rw-r--r-- | backend/src/models/User.js | 70 | ||||
-rw-r--r-- | backend/src/routes/auth.routes.js | 14 | ||||
-rw-r--r-- | backend/src/routes/index.js | 20 | ||||
-rw-r--r-- | backend/src/socket/handlers.js | 51 | ||||
-rw-r--r-- | backend/src/socket/index.js | 42 | ||||
-rw-r--r-- | backend/src/utils/jwt.js | 37 |
20 files changed, 897 insertions, 0 deletions
diff --git a/backend/src/config/database.js b/backend/src/config/database.js new file mode 100644 index 0000000..8fd758e --- /dev/null +++ b/backend/src/config/database.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose'); + +const connectDB = async () => { + try { + const conn = await mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/restaurant'); + console.log(`MongoDB Connected: ${conn.connection.host}`); + return conn; + } catch (error) { + console.error(`Error: ${error.message}`); + process.exit(1); + } +}; + +module.exports = connectDB;
\ No newline at end of file diff --git a/backend/src/config/env.js b/backend/src/config/env.js new file mode 100644 index 0000000..9353571 --- /dev/null +++ b/backend/src/config/env.js @@ -0,0 +1,11 @@ +require('dotenv').config(); + +const env = { + PORT: process.env.PORT || 5000, + MONGODB_URI: process.env.MONGODB_URI || 'mongodb://localhost:27017/restaurant', + JWT_SECRET: process.env.JWT_SECRET || 'your_jwt_secret_here', + NODE_ENV: process.env.NODE_ENV || 'development', + JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '30d' +}; + +module.exports = env;
\ No newline at end of file diff --git a/backend/src/config/logger.js b/backend/src/config/logger.js new file mode 100644 index 0000000..c9897b0 --- /dev/null +++ b/backend/src/config/logger.js @@ -0,0 +1,7 @@ +const morgan = require('morgan'); +const env = require('./env'); + +// Configure morgan logger +const logger = morgan(env.NODE_ENV === 'development' ? 'dev' : 'combined'); + +module.exports = logger;
\ No newline at end of file diff --git a/backend/src/controllers/auth.controller.js b/backend/src/controllers/auth.controller.js new file mode 100644 index 0000000..b5142d2 --- /dev/null +++ b/backend/src/controllers/auth.controller.js @@ -0,0 +1,130 @@ +const User = require('../models/User'); +const { generateToken } = require('../utils/jwt'); + +/** + * Register a new user + * @param {Object} req - Express request object + * @param {Object} res - Express response object + */ +const register = async (req, res) => { + try { + const { name, email, password, phone, address } = req.body; + + // Check if user already exists + const existingUser = await User.findOne({ email }); + if (existingUser) { + return res.status(400).json({ message: 'User already exists with this email' }); + } + + // Create new user + const user = await User.create({ + name, + email, + password, + phone, + address, + role: 'customer' // Default role for registrations + }); + + // Generate token + const token = generateToken(user); + + // Send response + res.status(201).json({ + message: 'User registered successfully', + token, + user: { + id: user._id, + name: user.name, + email: user.email, + role: user.role + } + }); + } catch (error) { + res.status(500).json({ + message: 'Error registering user', + error: error.message + }); + } +}; + +/** + * Login a user + * @param {Object} req - Express request object + * @param {Object} res - Express response object + */ +const login = async (req, res) => { + try { + const { email, password } = req.body; + + // Find user by email + const user = await User.findOne({ email }).select('+password'); + + // Check if user exists and password is correct + if (!user || !(await user.comparePassword(password))) { + return res.status(401).json({ message: 'Invalid email or password' }); + } + + // Check if user is active + if (!user.active) { + return res.status(401).json({ message: 'Your account has been deactivated' }); + } + + // Generate token + const token = generateToken(user); + + // Send response + res.status(200).json({ + message: 'Logged in successfully', + token, + user: { + id: user._id, + name: user.name, + email: user.email, + role: user.role + } + }); + } catch (error) { + res.status(500).json({ + message: 'Error logging in', + error: error.message + }); + } +}; + +/** + * Get current user profile + * @param {Object} req - Express request object + * @param {Object} res - Express response object + */ +const getProfile = async (req, res) => { + try { + const user = await User.findById(req.user._id); + + if (!user) { + return res.status(404).json({ message: 'User not found' }); + } + + res.status(200).json({ + user: { + id: user._id, + name: user.name, + email: user.email, + role: user.role, + phone: user.phone, + address: user.address + } + }); + } catch (error) { + res.status(500).json({ + message: 'Error retrieving profile', + error: error.message + }); + } +}; + +module.exports = { + register, + login, + getProfile +};
\ No newline at end of file diff --git a/backend/src/index.js b/backend/src/index.js new file mode 100644 index 0000000..6ee6435 --- /dev/null +++ b/backend/src/index.js @@ -0,0 +1,48 @@ +const express = require('express'); +const cors = require('cors'); +const path = require('path'); +const http = require('http'); +const connectDB = require('./config/database'); +const env = require('./config/env'); +const logger = require('./config/logger'); +const { notFound, errorHandler } = require('./middleware/error.middleware'); +const apiRoutes = require('./routes'); +const initializeSocket = require('./socket'); + +// Initialize express app +const app = express(); +const PORT = env.PORT; + +// Create HTTP server +const server = http.createServer(app); + +// Initialize Socket.IO +const io = initializeSocket(server); + +// Make io accessible to routes +app.set('io', io); + +// Connect to MongoDB +connectDB(); + +// Middleware +app.use(cors()); +app.use(express.json()); +app.use(logger); + +// Routes +app.get('/', (req, res) => { + res.json({ message: 'Welcome to Restaurant Management System API' }); +}); + +// API Routes +app.use('/api', apiRoutes); + +// Error handling middleware +app.use(notFound); +app.use(errorHandler); + +// Start the server +server.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +});
\ No newline at end of file diff --git a/backend/src/middleware/auth.middleware.js b/backend/src/middleware/auth.middleware.js new file mode 100644 index 0000000..62c7aa9 --- /dev/null +++ b/backend/src/middleware/auth.middleware.js @@ -0,0 +1,63 @@ +const { verifyToken } = require('../utils/jwt'); +const User = require('../models/User'); + +/** + * Authentication middleware + * @param {Object} req - Express request object + * @param {Object} res - Express response object + * @param {Function} next - Express next function + */ +const authenticate = async (req, res, next) => { + try { + let token; + + // Get token from Authorization header + if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) { + token = req.headers.authorization.split(' ')[1]; + } + + if (!token) { + return res.status(401).json({ message: 'Authentication required. Please log in.' }); + } + + // Verify token + const decoded = verifyToken(token); + + // Find user by id + const user = await User.findById(decoded.id); + + if (!user || !user.active) { + return res.status(401).json({ message: 'The user no longer exists or is inactive.' }); + } + + // Attach user to request object + req.user = user; + next(); + } catch (error) { + res.status(401).json({ message: 'Authentication failed. Invalid token.' }); + } +}; + +/** + * Authorization middleware factory + * @param {String[]} roles - Array of allowed roles + * @returns {Function} Express middleware + */ +const authorize = (...roles) => { + return (req, res, next) => { + if (!req.user) { + return res.status(401).json({ message: 'Authentication required.' }); + } + + if (!roles.includes(req.user.role)) { + return res.status(403).json({ message: 'You do not have permission to perform this action.' }); + } + + next(); + }; +}; + +module.exports = { + authenticate, + authorize +};
\ No newline at end of file diff --git a/backend/src/middleware/error.middleware.js b/backend/src/middleware/error.middleware.js new file mode 100644 index 0000000..e037cff --- /dev/null +++ b/backend/src/middleware/error.middleware.js @@ -0,0 +1,40 @@ +const env = require('../config/env'); + +/** + * Not found error handler middleware + * @param {Object} req - Express request object + * @param {Object} res - Express response object + * @param {Function} next - Express next function + */ +const notFound = (req, res, next) => { + const error = new Error(`Not Found - ${req.originalUrl}`); + res.status(404); + next(error); +}; + +/** + * General error handler middleware + * @param {Error} err - Error object + * @param {Object} req - Express request object + * @param {Object} res - Express response object + * @param {Function} next - Express next function + */ +const errorHandler = (err, req, res, next) => { + // Log the error + console.error(err.stack); + + // Set status code + const statusCode = res.statusCode === 200 ? 500 : res.statusCode; + + // Send response + res.status(statusCode).json({ + message: err.message, + stack: env.NODE_ENV === 'production' ? '🥞' : err.stack, + error: env.NODE_ENV === 'development' ? err : {} + }); +}; + +module.exports = { + notFound, + errorHandler +};
\ No newline at end of file diff --git a/backend/src/models/Category.js b/backend/src/models/Category.js new file mode 100644 index 0000000..bb28ba3 --- /dev/null +++ b/backend/src/models/Category.js @@ -0,0 +1,34 @@ +const mongoose = require('mongoose'); + +const categorySchema = new mongoose.Schema( + { + name: { + type: String, + required: [true, 'Category name is required'], + trim: true, + unique: true + }, + description: { + type: String, + trim: true + }, + image: { + type: String + }, + active: { + type: Boolean, + default: true + }, + displayOrder: { + type: Number, + default: 0 + } + }, + { + timestamps: true + } +); + +const Category = mongoose.model('Category', categorySchema); + +module.exports = Category;
\ No newline at end of file diff --git a/backend/src/models/Feedback.js b/backend/src/models/Feedback.js new file mode 100644 index 0000000..b433fed --- /dev/null +++ b/backend/src/models/Feedback.js @@ -0,0 +1,61 @@ +const mongoose = require('mongoose'); + +const feedbackSchema = new mongoose.Schema( + { + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: [true, 'User is required'] + }, + order: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Order' + }, + rating: { + type: Number, + required: [true, 'Rating is required'], + min: 1, + max: 5 + }, + comment: { + type: String, + trim: true + }, + foodRating: { + type: Number, + min: 1, + max: 5 + }, + serviceRating: { + type: Number, + min: 1, + max: 5 + }, + ambience: { + type: Number, + min: 1, + max: 5 + }, + photos: [ + { + type: String + } + ], + status: { + type: String, + enum: ['pending', 'approved', 'rejected'], + default: 'pending' + }, + adminResponse: { + type: String, + trim: true + } + }, + { + timestamps: true + } +); + +const Feedback = mongoose.model('Feedback', feedbackSchema); + +module.exports = Feedback;
\ No newline at end of file diff --git a/backend/src/models/MenuItem.js b/backend/src/models/MenuItem.js new file mode 100644 index 0000000..47701c8 --- /dev/null +++ b/backend/src/models/MenuItem.js @@ -0,0 +1,73 @@ +const mongoose = require('mongoose'); + +const menuItemSchema = new mongoose.Schema( + { + name: { + type: String, + required: [true, 'Menu item name is required'], + trim: true + }, + description: { + type: String, + trim: true + }, + price: { + type: Number, + required: [true, 'Price is required'], + min: 0 + }, + category: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Category', + required: [true, 'Category is required'] + }, + image: { + type: String + }, + ingredients: { + type: [String], + default: [] + }, + available: { + type: Boolean, + default: true + }, + vegetarian: { + type: Boolean, + default: false + }, + vegan: { + type: Boolean, + default: false + }, + glutenFree: { + type: Boolean, + default: false + }, + spiceLevel: { + type: Number, + min: 0, + max: 5, + default: 0 + }, + preparationTime: { + type: Number, + min: 0, + default: 15 + }, + featuredItem: { + type: Boolean, + default: false + } + }, + { + timestamps: true + } +); + +// Create text index for search functionality +menuItemSchema.index({ name: 'text', description: 'text', ingredients: 'text' }); + +const MenuItem = mongoose.model('MenuItem', menuItemSchema); + +module.exports = MenuItem;
\ No newline at end of file diff --git a/backend/src/models/Order.js b/backend/src/models/Order.js new file mode 100644 index 0000000..c60f986 --- /dev/null +++ b/backend/src/models/Order.js @@ -0,0 +1,60 @@ +const mongoose = require('mongoose'); + +const orderSchema = new mongoose.Schema( + { + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: [true, 'User is required'] + }, + items: [ + { + type: mongoose.Schema.Types.ObjectId, + ref: 'OrderItem' + } + ], + table: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Table' + }, + status: { + type: String, + enum: ['pending', 'preparing', 'ready', 'served', 'completed', 'cancelled'], + default: 'pending' + }, + totalAmount: { + type: Number, + required: [true, 'Total amount is required'], + min: 0 + }, + paymentStatus: { + type: String, + enum: ['pending', 'completed', 'failed', 'refunded'], + default: 'pending' + }, + paymentMethod: { + type: String, + enum: ['cash', 'card', 'mobile'], + default: 'cash' + }, + specialInstructions: { + type: String, + trim: true + }, + isDelivery: { + type: Boolean, + default: false + }, + deliveryAddress: { + type: String, + trim: true + } + }, + { + timestamps: true + } +); + +const Order = mongoose.model('Order', orderSchema); + +module.exports = Order;
\ No newline at end of file diff --git a/backend/src/models/OrderItem.js b/backend/src/models/OrderItem.js new file mode 100644 index 0000000..0625c96 --- /dev/null +++ b/backend/src/models/OrderItem.js @@ -0,0 +1,32 @@ +const mongoose = require('mongoose'); + +const orderItemSchema = new mongoose.Schema( + { + menuItem: { + type: mongoose.Schema.Types.ObjectId, + ref: 'MenuItem', + required: [true, 'Menu item is required'] + }, + quantity: { + type: Number, + required: [true, 'Quantity is required'], + min: 1 + }, + price: { + type: Number, + required: [true, 'Price is required'], + min: 0 + }, + specialInstructions: { + type: String, + trim: true + } + }, + { + timestamps: true + } +); + +const OrderItem = mongoose.model('OrderItem', orderItemSchema); + +module.exports = OrderItem;
\ No newline at end of file diff --git a/backend/src/models/Reservation.js b/backend/src/models/Reservation.js new file mode 100644 index 0000000..8ddba54 --- /dev/null +++ b/backend/src/models/Reservation.js @@ -0,0 +1,54 @@ +const mongoose = require('mongoose'); + +const reservationSchema = new mongoose.Schema( + { + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: [true, 'User is required'] + }, + table: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Table', + required: [true, 'Table is required'] + }, + date: { + type: Date, + required: [true, 'Reservation date is required'] + }, + startTime: { + type: String, + required: [true, 'Start time is required'] + }, + endTime: { + type: String, + required: [true, 'End time is required'] + }, + numberOfGuests: { + type: Number, + required: [true, 'Number of guests is required'], + min: 1 + }, + status: { + type: String, + enum: ['pending', 'confirmed', 'cancelled', 'completed'], + default: 'pending' + }, + specialRequests: { + type: String, + trim: true + }, + occasion: { + type: String, + enum: ['regular', 'birthday', 'anniversary', 'business', 'other'], + default: 'regular' + } + }, + { + timestamps: true + } +); + +const Reservation = mongoose.model('Reservation', reservationSchema); + +module.exports = Reservation;
\ No newline at end of file diff --git a/backend/src/models/Table.js b/backend/src/models/Table.js new file mode 100644 index 0000000..7653b3e --- /dev/null +++ b/backend/src/models/Table.js @@ -0,0 +1,36 @@ +const mongoose = require('mongoose'); + +const tableSchema = new mongoose.Schema( + { + tableNumber: { + type: Number, + required: [true, 'Table number is required'], + unique: true + }, + capacity: { + type: Number, + required: [true, 'Capacity is required'], + min: 1 + }, + location: { + type: String, + enum: ['indoor', 'outdoor', 'balcony', 'private'], + default: 'indoor' + }, + available: { + type: Boolean, + default: true + }, + isReserved: { + type: Boolean, + default: false + } + }, + { + timestamps: true + } +); + +const Table = mongoose.model('Table', tableSchema); + +module.exports = Table;
\ No newline at end of file diff --git a/backend/src/models/User.js b/backend/src/models/User.js new file mode 100644 index 0000000..dda71d0 --- /dev/null +++ b/backend/src/models/User.js @@ -0,0 +1,70 @@ +const mongoose = require('mongoose'); +const bcrypt = require('bcryptjs'); + +const userSchema = new mongoose.Schema( + { + name: { + type: String, + required: [true, 'Name is required'], + trim: true + }, + email: { + type: String, + required: [true, 'Email is required'], + unique: true, + trim: true, + lowercase: true, + match: [/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/, 'Please enter a valid email'] + }, + password: { + type: String, + required: [true, 'Password is required'], + minlength: [6, 'Password must be at least 6 characters long'], + select: false + }, + role: { + type: String, + enum: ['customer', 'staff', 'admin'], + default: 'customer' + }, + phone: { + type: String, + trim: true + }, + address: { + type: String, + trim: true + }, + active: { + type: Boolean, + default: true + } + }, + { + timestamps: true + } +); + +// Password hashing middleware +userSchema.pre('save', async function (next) { + if (!this.isModified('password')) { + return next(); + } + + try { + const salt = await bcrypt.genSalt(10); + this.password = await bcrypt.hash(this.password, salt); + next(); + } catch (error) { + next(error); + } +}); + +// Compare password method +userSchema.methods.comparePassword = async function (candidatePassword) { + return await bcrypt.compare(candidatePassword, this.password); +}; + +const User = mongoose.model('User', userSchema); + +module.exports = User;
\ No newline at end of file diff --git a/backend/src/routes/auth.routes.js b/backend/src/routes/auth.routes.js new file mode 100644 index 0000000..d01423c --- /dev/null +++ b/backend/src/routes/auth.routes.js @@ -0,0 +1,14 @@ +const express = require('express'); +const { register, login, getProfile } = require('../controllers/auth.controller'); +const { authenticate } = require('../middleware/auth.middleware'); + +const router = express.Router(); + +// Public routes +router.post('/register', register); +router.post('/login', login); + +// Protected routes +router.get('/profile', authenticate, getProfile); + +module.exports = router;
\ No newline at end of file diff --git a/backend/src/routes/index.js b/backend/src/routes/index.js new file mode 100644 index 0000000..4ea5c46 --- /dev/null +++ b/backend/src/routes/index.js @@ -0,0 +1,20 @@ +const express = require('express'); +const authRoutes = require('./auth.routes'); +// Import other routes as they are created +// const menuRoutes = require('./menu.routes'); +// const reservationRoutes = require('./reservations.routes'); +// const orderRoutes = require('./orders.routes'); +// const feedbackRoutes = require('./feedback.routes'); + +const router = express.Router(); + +// Auth routes +router.use('/auth', authRoutes); + +// Other routes to be added +// router.use('/menu', menuRoutes); +// router.use('/reservations', reservationRoutes); +// router.use('/orders', orderRoutes); +// router.use('/feedback', feedbackRoutes); + +module.exports = router;
\ No newline at end of file diff --git a/backend/src/socket/handlers.js b/backend/src/socket/handlers.js new file mode 100644 index 0000000..7e110b5 --- /dev/null +++ b/backend/src/socket/handlers.js @@ -0,0 +1,51 @@ +/** + * Register all event handlers for a socket connection + * @param {object} io - Socket.IO server instance + * @param {object} socket - Socket connection instance + */ +const registerHandlers = (io, socket) => { + // Handle joining a room (e.g., for orders or staff notifications) + socket.on('join-room', (room) => { + socket.join(room); + console.log(`Client ${socket.id} joined room: ${room}`); + }); + + // Handle order updates + socket.on('order-update', (data) => { + // Broadcast order updates to all clients in the room + io.to('staff-notifications').emit('order-status-changed', data); + io.to(`user-${data.userId}`).emit('order-status-changed', data); + console.log(`Order update: ${JSON.stringify(data)}`); + }); + + // Handle table reservation updates + socket.on('reservation-update', (data) => { + // Broadcast reservation updates to staff + io.to('staff-notifications').emit('reservation-changed', data); + console.log(`Reservation update: ${JSON.stringify(data)}`); + }); + + // Handle staff notifications + socket.on('staff-notification', (data) => { + // Broadcast to specific staff members or all staff + io.to('staff-notifications').emit('new-notification', data); + console.log(`Staff notification: ${JSON.stringify(data)}`); + }); + + // Handle customer notifications + socket.on('customer-notification', (data) => { + // Send notification to specific customer + io.to(`user-${data.userId}`).emit('new-notification', data); + console.log(`Customer notification: ${JSON.stringify(data)}`); + }); + + // Leave room + socket.on('leave-room', (room) => { + socket.leave(room); + console.log(`Client ${socket.id} left room: ${room}`); + }); +}; + +module.exports = { + registerHandlers +};
\ No newline at end of file diff --git a/backend/src/socket/index.js b/backend/src/socket/index.js new file mode 100644 index 0000000..0c25ed4 --- /dev/null +++ b/backend/src/socket/index.js @@ -0,0 +1,42 @@ +const socketIO = require('socket.io'); +const handlers = require('./handlers'); + +/** + * Initialize Socket.IO + * @param {object} server - HTTP server instance + * @returns {object} Socket.IO instance + */ +const initializeSocket = (server) => { + const io = socketIO(server, { + cors: { + origin: '*', + methods: ['GET', 'POST'] + } + }); + + // Authentication middleware for socket connections + io.use((socket, next) => { + // Simple authentication can be added here if needed + // const token = socket.handshake.auth.token; + // if (token validation logic) next(); + // else next(new Error('Authentication error')); + next(); + }); + + // Handle connection + io.on('connection', (socket) => { + console.log(`New client connected: ${socket.id}`); + + // Register event handlers + handlers.registerHandlers(io, socket); + + // Handle disconnection + socket.on('disconnect', () => { + console.log(`Client disconnected: ${socket.id}`); + }); + }); + + return io; +}; + +module.exports = initializeSocket;
\ No newline at end of file diff --git a/backend/src/utils/jwt.js b/backend/src/utils/jwt.js new file mode 100644 index 0000000..283b986 --- /dev/null +++ b/backend/src/utils/jwt.js @@ -0,0 +1,37 @@ +const jwt = require('jsonwebtoken'); +const env = require('../config/env'); + +/** + * Generate JWT token for a user + * @param {Object} user - User object + * @returns {String} JWT token + */ +const generateToken = (user) => { + return jwt.sign( + { + id: user._id, + role: user.role, + email: user.email + }, + env.JWT_SECRET, + { expiresIn: env.JWT_EXPIRES_IN } + ); +}; + +/** + * Verify JWT token + * @param {String} token - JWT token + * @returns {Object} Decoded token + */ +const verifyToken = (token) => { + try { + return jwt.verify(token, env.JWT_SECRET); + } catch (error) { + throw new Error('Invalid token'); + } +}; + +module.exports = { + generateToken, + verifyToken +};
\ No newline at end of file |