Merge branch 'main' of https://git.profit-planet.partners/DK404/CentralBackend
This commit is contained in:
commit
c74a363fd9
@ -140,6 +140,86 @@ class AdminUserController {
|
|||||||
res.status(500).json({ success: false, message: error.message });
|
res.status(500).json({ success: false, message: error.message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async archiveUser(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 unitOfWork = new UnitOfWork();
|
||||||
|
await unitOfWork.start();
|
||||||
|
try {
|
||||||
|
await AdminService.archiveUser(unitOfWork, userId);
|
||||||
|
await unitOfWork.commit();
|
||||||
|
res.json({ success: true, message: 'User archived successfully.' });
|
||||||
|
} catch (error) {
|
||||||
|
await unitOfWork.rollback(error);
|
||||||
|
res.status(500).json({ success: false, message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async unarchiveUser(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 unitOfWork = new UnitOfWork();
|
||||||
|
await unitOfWork.start();
|
||||||
|
try {
|
||||||
|
await AdminService.unarchiveUser(unitOfWork, userId);
|
||||||
|
await unitOfWork.commit();
|
||||||
|
res.json({ success: true, message: 'User unarchived successfully.' });
|
||||||
|
} catch (error) {
|
||||||
|
await unitOfWork.rollback(error);
|
||||||
|
res.status(500).json({ success: false, message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateUserVerification(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 { is_admin_verified } = req.body;
|
||||||
|
|
||||||
|
if (typeof is_admin_verified !== 'number' || (is_admin_verified !== 0 && is_admin_verified !== 1)) {
|
||||||
|
return res.status(400).json({ success: false, message: 'Invalid is_admin_verified value. Must be 0 or 1.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const unitOfWork = new UnitOfWork();
|
||||||
|
await unitOfWork.start();
|
||||||
|
try {
|
||||||
|
await AdminService.updateUserVerification(unitOfWork, userId, is_admin_verified);
|
||||||
|
await unitOfWork.commit();
|
||||||
|
res.json({ success: true, message: 'User verification status updated successfully.' });
|
||||||
|
} catch (error) {
|
||||||
|
await unitOfWork.rollback(error);
|
||||||
|
res.status(500).json({ success: false, message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateUserProfile(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 { profileData, userType } = req.body;
|
||||||
|
|
||||||
|
if (!profileData || !userType) {
|
||||||
|
return res.status(400).json({ success: false, message: 'Missing profileData or userType.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const unitOfWork = new UnitOfWork();
|
||||||
|
await unitOfWork.start();
|
||||||
|
try {
|
||||||
|
await AdminService.updateUserProfile(unitOfWork, userId, profileData, userType);
|
||||||
|
await unitOfWork.commit();
|
||||||
|
res.json({ success: true, message: 'User profile updated successfully.' });
|
||||||
|
} catch (error) {
|
||||||
|
await unitOfWork.rollback(error);
|
||||||
|
res.status(500).json({ success: false, message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AdminUserController;
|
module.exports = AdminUserController;
|
||||||
@ -189,6 +189,7 @@ async function createDatabase() {
|
|||||||
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') DEFAULT 'pending',
|
||||||
|
previous_status ENUM('inactive', 'pending', 'active', 'suspended') 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,
|
||||||
@ -206,6 +207,22 @@ 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)
|
||||||
|
try {
|
||||||
|
await connection.query(`
|
||||||
|
ALTER TABLE user_status
|
||||||
|
ADD COLUMN previous_status ENUM('inactive', 'pending', 'active', 'suspended') NULL
|
||||||
|
AFTER status
|
||||||
|
`);
|
||||||
|
console.log('✅ Added previous_status column to user_status table');
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code === 'ER_DUP_FIELDNAME') {
|
||||||
|
console.log('ℹ️ previous_status column already exists in user_status table');
|
||||||
|
} else {
|
||||||
|
console.warn('⚠️ Could not add previous_status column:', err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Authentication & Verification Tables ---
|
// --- Authentication & Verification Tables ---
|
||||||
|
|
||||||
// 5. refresh_tokens table: For refresh token authentication
|
// 5. refresh_tokens table: For refresh token authentication
|
||||||
|
|||||||
@ -4,6 +4,7 @@ const router = express.Router();
|
|||||||
const authMiddleware = require('../middleware/authMiddleware');
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
||||||
const CompanyStampController = require('../controller/companyStamp/CompanyStampController'); // <-- added
|
const CompanyStampController = require('../controller/companyStamp/CompanyStampController'); // <-- added
|
||||||
|
const AdminUserController = require('../controller/admin/AdminUserController');
|
||||||
|
|
||||||
// Helper middlewares for company-stamp
|
// Helper middlewares for company-stamp
|
||||||
function adminOnly(req, res, next) {
|
function adminOnly(req, res, next) {
|
||||||
@ -25,6 +26,12 @@ router.patch('/document-templates/:id/state', authMiddleware, DocumentTemplateCo
|
|||||||
// Company-stamp PATCH (activate)
|
// Company-stamp PATCH (activate)
|
||||||
router.patch('/company-stamps/:id/activate', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.activate);
|
router.patch('/company-stamps/:id/activate', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.activate);
|
||||||
|
|
||||||
|
// Admin user management PATCH routes
|
||||||
|
router.patch('/admin/archive-user/:id', authMiddleware, adminOnly, AdminUserController.archiveUser);
|
||||||
|
router.patch('/admin/unarchive-user/:id', authMiddleware, adminOnly, AdminUserController.unarchiveUser);
|
||||||
|
router.patch('/admin/update-verification/:id', authMiddleware, adminOnly, AdminUserController.updateUserVerification);
|
||||||
|
router.patch('/admin/update-user-profile/:id', authMiddleware, adminOnly, AdminUserController.updateUserProfile);
|
||||||
|
|
||||||
// Add other PATCH routes here as needed
|
// Add other PATCH routes here as needed
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@ -298,6 +298,134 @@ class AdminService {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async archiveUser(unitOfWork, userId) {
|
||||||
|
logger.info('AdminService.archiveUser:start', { userId });
|
||||||
|
try {
|
||||||
|
// First, get the current status to store it
|
||||||
|
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 archive if already inactive
|
||||||
|
if (currentStatus === 'inactive') {
|
||||||
|
logger.warn('AdminService.archiveUser:already_inactive', { userId });
|
||||||
|
return { message: 'User is already archived' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the previous status and update to inactive
|
||||||
|
await unitOfWork.connection.query(
|
||||||
|
`UPDATE user_status
|
||||||
|
SET status = 'inactive',
|
||||||
|
previous_status = ?
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[currentStatus, userId]
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info('AdminService.archiveUser:success', { userId, previousStatus: currentStatus });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('AdminService.archiveUser:error', { userId, error: error.message });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async unarchiveUser(unitOfWork, userId) {
|
||||||
|
logger.info('AdminService.unarchiveUser:start', { userId });
|
||||||
|
try {
|
||||||
|
// Get the current status and previous status
|
||||||
|
const [statusRows] = await unitOfWork.connection.query(
|
||||||
|
`SELECT status, previous_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;
|
||||||
|
const previousStatus = statusRows[0].previous_status;
|
||||||
|
|
||||||
|
// Only unarchive if currently inactive
|
||||||
|
if (currentStatus !== 'inactive') {
|
||||||
|
logger.warn('AdminService.unarchiveUser:not_inactive', { userId, currentStatus });
|
||||||
|
return { message: 'User is not archived' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore to previous status or default to 'pending' if no previous status exists
|
||||||
|
const restoreStatus = previousStatus || 'pending';
|
||||||
|
|
||||||
|
await unitOfWork.connection.query(
|
||||||
|
`UPDATE user_status
|
||||||
|
SET status = ?,
|
||||||
|
previous_status = NULL
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[restoreStatus, userId]
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info('AdminService.unarchiveUser:success', { userId, restoredStatus: restoreStatus });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('AdminService.unarchiveUser:error', { userId, error: error.message });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateUserVerification(unitOfWork, userId, isAdminVerified) {
|
||||||
|
logger.info('AdminService.updateUserVerification:start', { userId, isAdminVerified });
|
||||||
|
try {
|
||||||
|
// Update the is_admin_verified field in user_status
|
||||||
|
const timestamp = isAdminVerified === 1 ? new Date() : null;
|
||||||
|
|
||||||
|
await unitOfWork.connection.query(
|
||||||
|
`UPDATE user_status
|
||||||
|
SET is_admin_verified = ?,
|
||||||
|
admin_verified_at = ?
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[isAdminVerified, timestamp, userId]
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info('AdminService.updateUserVerification:success', { userId, isAdminVerified });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('AdminService.updateUserVerification:error', { userId, error: error.message });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateUserProfile(unitOfWork, userId, profileData, userType) {
|
||||||
|
logger.info('AdminService.updateUserProfile:start', { userId, userType });
|
||||||
|
try {
|
||||||
|
if (userType === 'personal') {
|
||||||
|
const { first_name, last_name, phone, date_of_birth, address, city, zip_code, country } = profileData;
|
||||||
|
await unitOfWork.connection.query(
|
||||||
|
`UPDATE personal_profiles
|
||||||
|
SET first_name = ?, last_name = ?, phone = ?, date_of_birth = ?,
|
||||||
|
address = ?, city = ?, zip_code = ?, country = ?
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[first_name, last_name, phone, date_of_birth, address, city, zip_code, country, userId]
|
||||||
|
);
|
||||||
|
} else if (userType === 'company') {
|
||||||
|
const { company_name, registration_number, tax_id, phone, address, city, zip_code, country } = profileData;
|
||||||
|
await unitOfWork.connection.query(
|
||||||
|
`UPDATE company_profiles
|
||||||
|
SET company_name = ?, registration_number = ?, tax_id = ?, phone = ?,
|
||||||
|
address = ?, city = ?, zip_code = ?, country = ?
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[company_name, registration_number, tax_id, phone, address, city, zip_code, country, userId]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info('AdminService.updateUserProfile:success', { userId, userType });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('AdminService.updateUserProfile:error', { userId, error: error.message });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AdminService;
|
module.exports = AdminService;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user