samoulla-backend / controllers /userManagementController.js
Samoulla Sync Bot
Auto-deploy Samoulla Backend: b68e45770de26ed39feb4b1c0925e5345eb3a61d
634b9bb
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,
});
}
};