Spaces:
Running
Running
| const User = require('../models/userModel'); | |
| const Provider = require('../models/providerModel'); | |
| const Newsletter = require('../models/newsletterModel'); | |
| const bcrypt = require('bcryptjs'); | |
| // Get all users (with filtering by role) | |
| exports.getAllUsers = async (req, res) => { | |
| try { | |
| const { role, isActive } = req.query; | |
| let users; | |
| if (role === 'subscriber') { | |
| // Find all active newsletter emails | |
| const subscribers = await Newsletter.find({ isActive: true }).select( | |
| 'email', | |
| ); | |
| const emails = subscribers.map((s) => s.email); | |
| // Find users whose email is in the subscribers list (for in-app notifications) | |
| users = await User.find({ email: { $in: emails } }).select('-password'); | |
| // For the results count, we show the total number of newsletter subscribers | |
| return res.status(200).json({ | |
| status: 'success', | |
| results: subscribers.length, | |
| data: { | |
| users, | |
| totalSubscribers: subscribers.length, | |
| }, | |
| }); | |
| } else { | |
| const filter = {}; | |
| if (role) filter.role = role; | |
| if (isActive !== undefined) filter.isActive = isActive === 'true'; | |
| users = await User.find(filter).select('-password'); | |
| } | |
| res.status(200).json({ | |
| status: 'success', | |
| results: users.length, | |
| data: { | |
| users, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to fetch users', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Get single user by ID | |
| exports.getUser = async (req, res) => { | |
| try { | |
| const user = await User.findById(req.params.id).select('-password'); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to fetch user', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Create user with specific role (admin only) | |
| exports.createUser = async (req, res) => { | |
| try { | |
| const { name, email, phone, password, role, permissions, providerData } = | |
| req.body; | |
| // Validate required fields | |
| if (!name || !email || !phone || !password) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Please provide name, email, phone, and password', | |
| }); | |
| } | |
| // Check if email already exists | |
| const existingUser = await User.findOne({ email }); | |
| if (existingUser) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Email already registered', | |
| }); | |
| } | |
| // Check if phone already exists | |
| const existingPhone = await User.findOne({ phone }); | |
| if (existingPhone) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Phone number already registered', | |
| }); | |
| } | |
| // Create user data object | |
| const userData = { | |
| name, | |
| email, | |
| phone, | |
| password, | |
| role: role || 'customer', | |
| }; | |
| // Add permissions if role is employee | |
| if (role === 'employee' && permissions) { | |
| userData.permissions = permissions; | |
| } | |
| // Create the user first | |
| const newUser = await User.create(userData); | |
| // If role is vendor, create or link provider | |
| if (role === 'vendor' && providerData) { | |
| const provider = await Provider.create({ | |
| ...providerData, | |
| user: newUser._id, | |
| }); | |
| newUser.provider = provider._id; | |
| await newUser.save(); | |
| } | |
| // Remove password from response | |
| newUser.password = undefined; | |
| res.status(201).json({ | |
| status: 'success', | |
| data: { | |
| user: newUser, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to create user', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Update user details (for employees) | |
| exports.updateUser = async (req, res) => { | |
| try { | |
| const { name, email, phone, password, permissions, isActive } = req.body; | |
| const user = await User.findById(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| // Update basic fields if provided | |
| if (name) user.name = name; | |
| if (email) { | |
| // Check if email is already taken by another user | |
| const existingUser = await User.findOne({ | |
| email, | |
| _id: { $ne: req.params.id }, | |
| }); | |
| if (existingUser) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Email already in use', | |
| }); | |
| } | |
| user.email = email; | |
| } | |
| if (phone) { | |
| // Check if phone is already taken by another user | |
| const existingPhone = await User.findOne({ | |
| phone, | |
| _id: { $ne: req.params.id }, | |
| }); | |
| if (existingPhone) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Phone number already in use', | |
| }); | |
| } | |
| user.phone = phone; | |
| } | |
| // Update password if provided | |
| if (password) { | |
| user.password = password; // Will be hashed by pre-save middleware | |
| } | |
| // Update permissions if user is employee | |
| if (user.role === 'employee' && permissions !== undefined) { | |
| user.permissions = permissions; | |
| } | |
| // Update isActive status | |
| if (isActive !== undefined) { | |
| user.isActive = isActive; | |
| } | |
| await user.save(); | |
| // Remove password from response | |
| user.password = undefined; | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to update user', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Update user role | |
| exports.updateUserRole = async (req, res) => { | |
| try { | |
| const { role } = req.body; | |
| if (!role || !['customer', 'admin', 'employee', 'vendor'].includes(role)) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Please provide a valid role', | |
| }); | |
| } | |
| const user = await User.findById(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| user.role = role; | |
| // Clear permissions if changing from employee to another role | |
| if (role !== 'employee') { | |
| user.permissions = []; | |
| } | |
| await user.save(); | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to update user role', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Update employee permissions | |
| exports.updateEmployeePermissions = async (req, res) => { | |
| try { | |
| const { permissions } = req.body; | |
| if (!Array.isArray(permissions)) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Permissions must be an array', | |
| }); | |
| } | |
| const user = await User.findById(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| if (user.role !== 'employee') { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Permissions can only be set for employees', | |
| }); | |
| } | |
| user.permissions = permissions; | |
| await user.save(); | |
| // Emit socket event to notify the employee of permission changes | |
| try { | |
| const io = require('../utils/socket').getIO(); | |
| io.to(user._id.toString()).emit('permissionsUpdated', { | |
| permissions: user.permissions, | |
| message: 'تم تحديث صلاحياتك من قبل المسؤول', | |
| }); | |
| } catch (socketError) { | |
| console.error('Failed to emit permission update:', socketError); | |
| // Don't fail the request if socket emission fails | |
| } | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to update permissions', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Update vendor information | |
| exports.updateVendorInfo = async (req, res) => { | |
| try { | |
| const { vendorInfo } = req.body; | |
| if (!vendorInfo) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Please provide vendor information', | |
| }); | |
| } | |
| const user = await User.findById(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| if (user.role !== 'vendor') { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: 'Vendor info can only be set for vendors', | |
| }); | |
| } | |
| user.vendorInfo = { ...user.vendorInfo, ...vendorInfo }; | |
| await user.save(); | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to update vendor info', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Deactivate user account | |
| exports.deactivateUser = async (req, res) => { | |
| try { | |
| const user = await User.findById(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| user.isActive = false; | |
| await user.save(); | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'User account deactivated successfully', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to deactivate user', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Activate user account | |
| exports.activateUser = async (req, res) => { | |
| try { | |
| const user = await User.findById(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| user.isActive = true; | |
| await user.save(); | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'User account activated successfully', | |
| data: { | |
| user, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to activate user', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // Delete user (permanent) | |
| exports.deleteUser = async (req, res) => { | |
| try { | |
| const user = await User.findByIdAndDelete(req.params.id); | |
| if (!user) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'User not found', | |
| }); | |
| } | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'User deleted successfully', | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to delete user', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |