feat: add updateUserStatus method to AdminUserController and corresponding service logic
This commit is contained in:
parent
c74a363fd9
commit
4fc78f3f8b
@ -220,6 +220,29 @@ class AdminUserController {
|
|||||||
res.status(500).json({ success: false, message: error.message });
|
res.status(500).json({ success: false, message: error.message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async updateUserStatus(req, res) {
|
||||||
|
if (!req.user || (req.user.role !== 'admin' && req.user.role !== 'super_admin')) {
|
||||||
|
return res.status(403).json({ success: false, message: 'Forbidden: Admins only.' });
|
||||||
|
}
|
||||||
|
const userId = req.params.id;
|
||||||
|
const { status } = req.body;
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
return res.status(400).json({ success: false, message: 'Missing status.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const unitOfWork = new UnitOfWork();
|
||||||
|
await unitOfWork.start();
|
||||||
|
try {
|
||||||
|
const result = await AdminService.updateUserStatus(unitOfWork, userId, status);
|
||||||
|
await unitOfWork.commit();
|
||||||
|
res.json({ success: true, message: result.message || 'User status updated successfully.' });
|
||||||
|
} catch (error) {
|
||||||
|
await unitOfWork.rollback(error);
|
||||||
|
res.status(500).json({ success: false, message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AdminUserController;
|
module.exports = AdminUserController;
|
||||||
@ -188,8 +188,8 @@ async function createDatabase() {
|
|||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS user_status (
|
CREATE TABLE IF NOT EXISTS user_status (
|
||||||
user_id INT PRIMARY KEY,
|
user_id INT PRIMARY KEY,
|
||||||
status ENUM('inactive', 'pending', 'active', 'suspended') DEFAULT 'pending',
|
status ENUM('inactive', 'pending', 'active', 'suspended', 'archived') DEFAULT 'pending',
|
||||||
previous_status ENUM('inactive', 'pending', 'active', 'suspended') NULL,
|
previous_status ENUM('inactive', 'pending', 'active', 'suspended', 'archived') NULL,
|
||||||
email_verified BOOLEAN DEFAULT FALSE,
|
email_verified BOOLEAN DEFAULT FALSE,
|
||||||
email_verified_at TIMESTAMP NULL,
|
email_verified_at TIMESTAMP NULL,
|
||||||
profile_completed BOOLEAN DEFAULT FALSE,
|
profile_completed BOOLEAN DEFAULT FALSE,
|
||||||
@ -207,20 +207,25 @@ async function createDatabase() {
|
|||||||
`);
|
`);
|
||||||
console.log('✅ User status table created/verified');
|
console.log('✅ User status table created/verified');
|
||||||
|
|
||||||
// Add previous_status column if it doesn't exist (for existing databases)
|
// Modify existing ENUM columns to add 'archived' status (for existing databases)
|
||||||
try {
|
try {
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
ALTER TABLE user_status
|
ALTER TABLE user_status
|
||||||
ADD COLUMN previous_status ENUM('inactive', 'pending', 'active', 'suspended') NULL
|
MODIFY COLUMN status ENUM('inactive', 'pending', 'active', 'suspended', 'archived') DEFAULT 'pending'
|
||||||
AFTER status
|
|
||||||
`);
|
`);
|
||||||
console.log('✅ Added previous_status column to user_status table');
|
console.log('✅ Updated status column to include archived');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === 'ER_DUP_FIELDNAME') {
|
console.warn('⚠️ Could not modify status column:', err.message);
|
||||||
console.log('ℹ️ previous_status column already exists in user_status table');
|
|
||||||
} else {
|
|
||||||
console.warn('⚠️ Could not add previous_status column:', err.message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await connection.query(`
|
||||||
|
ALTER TABLE user_status
|
||||||
|
MODIFY COLUMN previous_status ENUM('inactive', 'pending', 'active', 'suspended', 'archived') NULL
|
||||||
|
`);
|
||||||
|
console.log('✅ Updated previous_status column to include archived');
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('⚠️ Could not modify previous_status column:', err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Authentication & Verification Tables ---
|
// --- Authentication & Verification Tables ---
|
||||||
|
|||||||
@ -31,6 +31,7 @@ router.patch('/admin/archive-user/:id', authMiddleware, adminOnly, AdminUserCont
|
|||||||
router.patch('/admin/unarchive-user/:id', authMiddleware, adminOnly, AdminUserController.unarchiveUser);
|
router.patch('/admin/unarchive-user/:id', authMiddleware, adminOnly, AdminUserController.unarchiveUser);
|
||||||
router.patch('/admin/update-verification/:id', authMiddleware, adminOnly, AdminUserController.updateUserVerification);
|
router.patch('/admin/update-verification/:id', authMiddleware, adminOnly, AdminUserController.updateUserVerification);
|
||||||
router.patch('/admin/update-user-profile/:id', authMiddleware, adminOnly, AdminUserController.updateUserProfile);
|
router.patch('/admin/update-user-profile/:id', authMiddleware, adminOnly, AdminUserController.updateUserProfile);
|
||||||
|
router.patch('/admin/update-user-status/:id', authMiddleware, adminOnly, AdminUserController.updateUserStatus);
|
||||||
|
|
||||||
// Add other PATCH routes here as needed
|
// Add other PATCH routes here as needed
|
||||||
|
|
||||||
|
|||||||
@ -314,16 +314,16 @@ class AdminService {
|
|||||||
|
|
||||||
const currentStatus = statusRows[0].status;
|
const currentStatus = statusRows[0].status;
|
||||||
|
|
||||||
// Don't archive if already inactive
|
// Don't archive if already archived
|
||||||
if (currentStatus === 'inactive') {
|
if (currentStatus === 'archived') {
|
||||||
logger.warn('AdminService.archiveUser:already_inactive', { userId });
|
logger.warn('AdminService.archiveUser:already_archived', { userId });
|
||||||
return { message: 'User is already archived' };
|
return { message: 'User is already archived' };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the previous status and update to inactive
|
// Store the previous status and update to archived
|
||||||
await unitOfWork.connection.query(
|
await unitOfWork.connection.query(
|
||||||
`UPDATE user_status
|
`UPDATE user_status
|
||||||
SET status = 'inactive',
|
SET status = 'archived',
|
||||||
previous_status = ?
|
previous_status = ?
|
||||||
WHERE user_id = ?`,
|
WHERE user_id = ?`,
|
||||||
[currentStatus, userId]
|
[currentStatus, userId]
|
||||||
@ -352,9 +352,9 @@ class AdminService {
|
|||||||
const currentStatus = statusRows[0].status;
|
const currentStatus = statusRows[0].status;
|
||||||
const previousStatus = statusRows[0].previous_status;
|
const previousStatus = statusRows[0].previous_status;
|
||||||
|
|
||||||
// Only unarchive if currently inactive
|
// Only unarchive if currently archived
|
||||||
if (currentStatus !== 'inactive') {
|
if (currentStatus !== 'archived') {
|
||||||
logger.warn('AdminService.unarchiveUser:not_inactive', { userId, currentStatus });
|
logger.warn('AdminService.unarchiveUser:not_archived', { userId, currentStatus });
|
||||||
return { message: 'User is not archived' };
|
return { message: 'User is not archived' };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +376,49 @@ class AdminService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async updateUserStatus(unitOfWork, userId, newStatus) {
|
||||||
|
logger.info('AdminService.updateUserStatus:start', { userId, newStatus });
|
||||||
|
try {
|
||||||
|
// Validate status
|
||||||
|
const validStatuses = ['inactive', 'pending', 'active', 'suspended', 'archived'];
|
||||||
|
if (!validStatuses.includes(newStatus)) {
|
||||||
|
throw new Error(`Invalid status: ${newStatus}. Must be one of: ${validStatuses.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current status
|
||||||
|
const [statusRows] = await unitOfWork.connection.query(
|
||||||
|
`SELECT status FROM user_status WHERE user_id = ? LIMIT 1`,
|
||||||
|
[userId]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (statusRows.length === 0) {
|
||||||
|
throw new Error('User status not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentStatus = statusRows[0].status;
|
||||||
|
|
||||||
|
// Don't update if already at target status
|
||||||
|
if (currentStatus === newStatus) {
|
||||||
|
logger.warn('AdminService.updateUserStatus:already_at_status', { userId, status: newStatus });
|
||||||
|
return { message: `User is already ${newStatus}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update status
|
||||||
|
await unitOfWork.connection.query(
|
||||||
|
`UPDATE user_status
|
||||||
|
SET status = ?
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[newStatus, userId]
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info('AdminService.updateUserStatus:success', { userId, oldStatus: currentStatus, newStatus });
|
||||||
|
return { message: `User status updated from ${currentStatus} to ${newStatus}` };
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('AdminService.updateUserStatus:error', { userId, error: error.message });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static async updateUserVerification(unitOfWork, userId, isAdminVerified) {
|
static async updateUserVerification(unitOfWork, userId, isAdminVerified) {
|
||||||
logger.info('AdminService.updateUserVerification:start', { userId, isAdminVerified });
|
logger.info('AdminService.updateUserVerification:start', { userId, isAdminVerified });
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user