CentralBackend/services/AdminService.js
2025-09-07 12:44:01 +02:00

224 lines
9.2 KiB
JavaScript

const AdminRepository = require('../repositories/AdminRepository');
const UserDocumentRepository = require('../repositories/UserDocumentRepository');
const UserRepository = require('../repositories/UserRepository');
const { s3 } = require('../utils/exoscaleUploader');
const { GetObjectCommand } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
const { DeleteObjectCommand } = require('@aws-sdk/client-s3');
const pidusage = require('pidusage');
const os = require('os');
const { logger } = require('../middleware/logger');
class AdminService {
static async getUserStats(unitOfWork) {
logger.info('AdminService.getUserStats:start');
try {
const stats = await AdminRepository.getUserStats(unitOfWork.connection);
logger.info('AdminService.getUserStats:success', stats);
return stats;
} catch (error) {
logger.error('AdminService.getUserStats:error', { error: error.message });
throw error;
}
}
static async getUserList(unitOfWork) {
logger.info('AdminService.getUserList:start');
try {
const list = await AdminRepository.getUserList(unitOfWork.connection);
logger.info('AdminService.getUserList:success', { count: list.length });
return list;
} catch (error) {
logger.error('AdminService.getUserList:error', { error: error.message });
throw error;
}
}
static async getVerificationPendingUsers(unitOfWork) {
logger.info('AdminService.getVerificationPendingUsers:start');
try {
const users = await AdminRepository.getVerificationPendingUsers(unitOfWork.connection);
logger.info('AdminService.getVerificationPendingUsers:success', { count: users.length });
return users;
} catch (error) {
logger.error('AdminService.getVerificationPendingUsers:error', { error: error.message });
throw error;
}
}
static async verifyUser(unitOfWork, userId, permissions) {
logger.info('AdminService.verifyUser:start', { userId, permissions });
try {
// 1. Fetch user
const userRepo = new UserRepository(unitOfWork);
const user = await userRepo.findUserByEmailOrId(Number(userId));
if (!user) throw new Error('User not found');
logger.info('AdminService.verifyUser:user_fetched', { userId });
// 2. Fetch documents and contracts
const documents = await AdminRepository.getUserDocuments(unitOfWork.connection, userId);
const contracts = await AdminRepository.getUserContracts(unitOfWork.connection, userId);
logger.info('AdminService.verifyUser:documents_fetched', { userId, documentsCount: documents.length, contractsCount: contracts.length });
// 3. Fetch ID document metadata
const idDocs = await AdminRepository.getUserIdDocuments(unitOfWork.connection, userId);
logger.info('AdminService.verifyUser:id_docs_fetched', { userId, idDocsCount: idDocs.length });
// 4. Generate signed URLs for front/back of ID documents
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.verifyUser:id_docs_urls_generated', { userId, idDocsCount: idDocumentsWithUrls.length });
// 5. Update user_status
await AdminRepository.verifyUser(unitOfWork.connection, userId);
logger.info('AdminService.verifyUser:user_status_updated', { userId });
// 6. Assign permissions
if (permissions.length > 0) {
await AdminRepository.assignPermissions(unitOfWork.connection, userId, permissions);
logger.info('AdminService.verifyUser:permissions_assigned', { userId, permissions });
}
// 7. Return updated user data
logger.info('AdminService.verifyUser:success', { userId });
return {
message: 'User verified and permissions updated',
user: user.getPublicData(),
documents,
contracts,
idDocuments: idDocumentsWithUrls
};
} catch (error) {
logger.error('AdminService.verifyUser:error', { userId, error: error.message });
throw error;
}
}
static async getFullUserAccountDetails(unitOfWork, userId) {
logger.info('AdminService.getFullUserAccountDetails:start', { userId });
try {
const user = await AdminRepository.getUserById(unitOfWork.connection, userId);
if (!user) throw new Error('User not found');
const personalProfile = await AdminRepository.getPersonalProfile(unitOfWork.connection, userId);
const companyProfile = await AdminRepository.getCompanyProfile(unitOfWork.connection, userId);
const permissions = await AdminRepository.getUserPermissions(unitOfWork.connection, userId);
logger.info('AdminService.getFullUserAccountDetails:success', { userId });
return { user, personalProfile, companyProfile, permissions };
} catch (error) {
logger.error('AdminService.getFullUserAccountDetails:error', { userId, error: error.message });
throw error;
}
}
static async updateUserPermissions(unitOfWork, userId, permissions) {
logger.info('AdminService.updateUserPermissions:start', { userId, permissions });
try {
await AdminRepository.updateUserPermissions(unitOfWork.connection, userId, permissions);
logger.info('AdminService.updateUserPermissions:success', { userId, permissions });
} catch (error) {
logger.error('AdminService.updateUserPermissions:error', { userId, error: error.message });
throw error;
}
}
static async getServerStatus() {
logger.info('AdminService.getServerStatus:start');
try {
const stats = await pidusage(process.pid);
const uptimeSeconds = process.uptime();
const uptimeDays = Math.floor(uptimeSeconds / (60 * 60 * 24));
const uptimeHours = Math.floor((uptimeSeconds % (60 * 60 * 24)) / 3600);
const totalMem = os.totalmem();
logger.info('AdminService.getServerStatus:success', { status: 'Online', uptime: { days: uptimeDays, hours: uptimeHours } });
return {
status: 'Online',
uptime: { days: uptimeDays, hours: uptimeHours },
cpuUsagePercent: Math.round(stats.cpu),
memory: {
used: (stats.memory / (1024 ** 3)).toFixed(1),
total: (totalMem / (1024 ** 3)).toFixed(1)
},
logs: []
};
} catch (error) {
logger.error('AdminService.getServerStatus:error', { error: error.message });
throw error;
}
}
static async deleteUser(unitOfWork, userId) {
logger.info('AdminService.deleteUser:start', { userId });
try {
// 1. Fetch all object storage IDs for user documents
const docRepo = new UserDocumentRepository(unitOfWork);
const objectIds = await docRepo.getAllObjectStorageIdsForUser(userId);
// 2. Delete each document from S3
for (const obj of objectIds) {
try {
if (obj.object_storage_id) {
await s3.send(new DeleteObjectCommand({
Bucket: process.env.EXOSCALE_BUCKET,
Key: obj.object_storage_id
}));
logger.info('AdminService.deleteUser:s3_deleted', { userId, objectKey: obj.object_storage_id });
}
// For user_id_documents: front/back
if (obj.front_object_storage_id) {
await s3.send(new DeleteObjectCommand({
Bucket: process.env.EXOSCALE_BUCKET,
Key: obj.front_object_storage_id
}));
logger.info('AdminService.deleteUser:s3_deleted', { userId, objectKey: obj.front_object_storage_id });
}
if (obj.back_object_storage_id) {
await s3.send(new DeleteObjectCommand({
Bucket: process.env.EXOSCALE_BUCKET,
Key: obj.back_object_storage_id
}));
logger.info('AdminService.deleteUser:s3_deleted', { userId, objectKey: obj.back_object_storage_id });
}
} catch (err) {
logger.warn('AdminService.deleteUser:s3_delete_failed', { userId, error: err.message, objectKey: obj.object_storage_id || obj.front_object_storage_id || obj.back_object_storage_id });
}
}
// 3. Delete user from DB (cascades)
const userRepo = new UserRepository(unitOfWork);
await userRepo.deleteUserById(userId);
logger.info('AdminService.deleteUser:success', { userId });
} catch (error) {
logger.error('AdminService.deleteUser:error', { userId, error: error.message });
throw error;
}
}
}
module.exports = AdminService;