From dac3f219216ae0bf7784973b868ce247a86cdeab Mon Sep 17 00:00:00 2001 From: seaznCode Date: Wed, 22 Oct 2025 18:29:58 +0200 Subject: [PATCH] feat: add getDetailedUserInfo method to AdminUserController and AdminService, and update routes --- controller/admin/AdminUserController.js | 17 +++++++ routes/getRoutes.js | 1 + services/admin/AdminService.js | 68 +++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/controller/admin/AdminUserController.js b/controller/admin/AdminUserController.js index e19d88f..bdb8667 100644 --- a/controller/admin/AdminUserController.js +++ b/controller/admin/AdminUserController.js @@ -86,6 +86,23 @@ class AdminUserController { } } + static async getDetailedUserInfo(req, res) { + if (!req.user || (req.user.role !== 'admin' && req.user.role !== 'super_admin')) { + return res.status(403).json({ success: false, message: 'Forbidden' }); + } + const userId = req.params.id; + const unitOfWork = new UnitOfWork(); + await unitOfWork.start(); + try { + const details = await AdminService.getDetailedUserInfo(unitOfWork, userId); + await unitOfWork.commit(); + res.json({ success: true, ...details }); + } catch (error) { + await unitOfWork.rollback(error); + res.status(500).json({ success: false, message: error.message }); + } + } + static async updateUserPermissions(req, res) { const userId = Number(req.params.id); const permissions = req.body.permissions; diff --git a/routes/getRoutes.js b/routes/getRoutes.js index be5613e..f22e430 100644 --- a/routes/getRoutes.js +++ b/routes/getRoutes.js @@ -48,6 +48,7 @@ router.get('/users/:id/full', authMiddleware, UserController.getFullUserData); router.get('/user/settings', authMiddleware, UserSettingsController.getSettings); router.get('/users/:id/permissions', authMiddleware, PermissionController.getUserPermissions); router.get('/admin/users/:id/full', authMiddleware, AdminUserController.getFullUserAccountDetails); +router.get('/admin/users/:id/detailed', authMiddleware, requireAdmin, AdminUserController.getDetailedUserInfo); router.get('/users/:id/documents', authMiddleware, UserController.getUserDocumentsAndContracts); router.get('/verify-password-reset', (req, res) => { /* Note: was moved from PasswordResetController.verifyPasswordResetToken */ res.status(204).end(); }); // keep placeholder if controller already registered via other verb diff --git a/services/admin/AdminService.js b/services/admin/AdminService.js index 311d01b..fcf329e 100644 --- a/services/admin/AdminService.js +++ b/services/admin/AdminService.js @@ -146,6 +146,74 @@ class AdminService { } } + static async getDetailedUserInfo(unitOfWork, userId) { + logger.info('AdminService.getDetailedUserInfo:start', { userId }); + try { + // Get basic user info + const user = await AdminRepository.getUserById(unitOfWork.connection, userId); + if (!user) throw new Error('User not found'); + + // Get profiles + const personalProfile = await AdminRepository.getPersonalProfile(unitOfWork.connection, userId); + const companyProfile = await AdminRepository.getCompanyProfile(unitOfWork.connection, userId); + + // Get permissions + const permissions = await AdminRepository.getUserPermissions(unitOfWork.connection, userId); + + // Get user status + const [statusRows] = await unitOfWork.connection.query( + `SELECT * FROM user_status WHERE user_id = ? LIMIT 1`, [userId] + ); + const userStatus = statusRows.length ? statusRows[0] : null; + + // Get documents + const documents = await AdminRepository.getUserDocuments(unitOfWork.connection, userId); + const contracts = await AdminRepository.getUserContracts(unitOfWork.connection, userId); + + // Get ID documents with signed URLs + const idDocs = await AdminRepository.getUserIdDocuments(unitOfWork.connection, userId); + const idDocumentsWithUrls = await Promise.all( + idDocs.map(async doc => { + let frontUrl = null, backUrl = null; + if (doc.front_object_storage_id) { + try { + const command = new GetObjectCommand({ + Bucket: process.env.EXOSCALE_BUCKET, + Key: doc.front_object_storage_id + }); + frontUrl = await getSignedUrl(s3, command, { expiresIn: 900 }); + } catch (err) { frontUrl = null; } + } + if (doc.back_object_storage_id) { + try { + const command = new GetObjectCommand({ + Bucket: process.env.EXOSCALE_BUCKET, + Key: doc.back_object_storage_id + }); + backUrl = await getSignedUrl(s3, command, { expiresIn: 900 }); + } catch (err) { backUrl = null; } + } + return { ...doc, frontUrl, backUrl }; + }) + ); + + logger.info('AdminService.getDetailedUserInfo:success', { userId }); + return { + user, + personalProfile, + companyProfile, + permissions, + userStatus, + documents, + contracts, + idDocuments: idDocumentsWithUrls + }; + } catch (error) { + logger.error('AdminService.getDetailedUserInfo:error', { userId, error: error.message }); + throw error; + } + } + static async updateUserPermissions(unitOfWork, userId, permissions) { logger.info('AdminService.updateUserPermissions:start', { userId, permissions }); try {