ability to ban and unban users
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
const express = require('express');
|
||||
const { User, UserAddress } = require('../models'); // Import from models/index.js to get models with associations
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const { authenticateToken, optionalAuth, requireAdmin } = require('../middleware/auth');
|
||||
const logger = require('../utils/logger');
|
||||
const userService = require('../services/UserService');
|
||||
const { validateS3Keys } = require('../utils/s3KeyValidator');
|
||||
@@ -210,10 +210,20 @@ router.put('/availability', authenticateToken, async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/:id', async (req, res, next) => {
|
||||
router.get('/:id', optionalAuth, async (req, res, next) => {
|
||||
try {
|
||||
const isAdmin = req.user?.role === 'admin';
|
||||
|
||||
// Base attributes to exclude
|
||||
const excludedAttributes = ['password', 'email', 'phone', 'address', 'verificationToken', 'passwordResetToken'];
|
||||
|
||||
// If not admin, also exclude ban-related fields
|
||||
if (!isAdmin) {
|
||||
excludedAttributes.push('isBanned', 'bannedAt', 'bannedBy', 'banReason');
|
||||
}
|
||||
|
||||
const user = await User.findByPk(req.params.id, {
|
||||
attributes: { exclude: ['password', 'email', 'phone', 'address'] }
|
||||
attributes: { exclude: excludedAttributes }
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
@@ -222,7 +232,8 @@ router.get('/:id', async (req, res, next) => {
|
||||
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.info("Public user profile fetched", {
|
||||
requestedUserId: req.params.id
|
||||
requestedUserId: req.params.id,
|
||||
viewerIsAdmin: isAdmin
|
||||
});
|
||||
|
||||
res.json(user);
|
||||
@@ -263,4 +274,137 @@ router.put('/profile', authenticateToken, async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Admin: Ban a user
|
||||
router.post('/admin/:id/ban', authenticateToken, requireAdmin, async (req, res, next) => {
|
||||
try {
|
||||
const { reason } = req.body;
|
||||
const targetUserId = req.params.id;
|
||||
|
||||
// Validate reason is provided
|
||||
if (!reason || !reason.trim()) {
|
||||
return res.status(400).json({ error: "Ban reason is required" });
|
||||
}
|
||||
|
||||
// Prevent banning yourself
|
||||
if (targetUserId === req.user.id) {
|
||||
return res.status(400).json({ error: "You cannot ban yourself" });
|
||||
}
|
||||
|
||||
const targetUser = await User.findByPk(targetUserId);
|
||||
|
||||
if (!targetUser) {
|
||||
return res.status(404).json({ error: "User not found" });
|
||||
}
|
||||
|
||||
// Prevent banning other admins
|
||||
if (targetUser.role === 'admin') {
|
||||
return res.status(403).json({ error: "Cannot ban admin users" });
|
||||
}
|
||||
|
||||
// Check if already banned
|
||||
if (targetUser.isBanned) {
|
||||
return res.status(400).json({ error: "User is already banned" });
|
||||
}
|
||||
|
||||
// Ban the user (this also invalidates sessions via jwtVersion increment)
|
||||
await targetUser.banUser(req.user.id, reason.trim());
|
||||
|
||||
// Send ban notification email
|
||||
try {
|
||||
const emailServices = require("../services/email");
|
||||
await emailServices.userEngagement.sendUserBannedNotification(
|
||||
targetUser,
|
||||
req.user,
|
||||
reason.trim()
|
||||
);
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.info("User ban notification email sent", {
|
||||
bannedUserId: targetUserId,
|
||||
adminId: req.user.id
|
||||
});
|
||||
} catch (emailError) {
|
||||
// Log but don't fail the ban operation
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.error('Failed to send user ban notification email', {
|
||||
error: emailError.message,
|
||||
stack: emailError.stack,
|
||||
bannedUserId: targetUserId,
|
||||
adminId: req.user.id
|
||||
});
|
||||
}
|
||||
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.info("User banned by admin", {
|
||||
targetUserId,
|
||||
adminId: req.user.id,
|
||||
reason: reason.trim()
|
||||
});
|
||||
|
||||
// Return updated user data (excluding sensitive fields)
|
||||
const updatedUser = await User.findByPk(targetUserId, {
|
||||
attributes: { exclude: ['password', 'verificationToken', 'passwordResetToken'] }
|
||||
});
|
||||
|
||||
res.json({
|
||||
message: "User has been banned successfully",
|
||||
user: updatedUser
|
||||
});
|
||||
} catch (error) {
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.error("Admin ban user failed", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
targetUserId: req.params.id,
|
||||
adminId: req.user.id
|
||||
});
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Admin: Unban a user
|
||||
router.post('/admin/:id/unban', authenticateToken, requireAdmin, async (req, res, next) => {
|
||||
try {
|
||||
const targetUserId = req.params.id;
|
||||
|
||||
const targetUser = await User.findByPk(targetUserId);
|
||||
|
||||
if (!targetUser) {
|
||||
return res.status(404).json({ error: "User not found" });
|
||||
}
|
||||
|
||||
// Check if user is actually banned
|
||||
if (!targetUser.isBanned) {
|
||||
return res.status(400).json({ error: "User is not banned" });
|
||||
}
|
||||
|
||||
// Unban the user
|
||||
await targetUser.unbanUser();
|
||||
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.info("User unbanned by admin", {
|
||||
targetUserId,
|
||||
adminId: req.user.id
|
||||
});
|
||||
|
||||
// Return updated user data (excluding sensitive fields)
|
||||
const updatedUser = await User.findByPk(targetUserId, {
|
||||
attributes: { exclude: ['password', 'verificationToken', 'passwordResetToken'] }
|
||||
});
|
||||
|
||||
res.json({
|
||||
message: "User has been unbanned successfully",
|
||||
user: updatedUser
|
||||
});
|
||||
} catch (error) {
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.error("Admin unban user failed", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
targetUserId: req.params.id,
|
||||
adminId: req.user.id
|
||||
});
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user