/*********************************************************************************************************************************************************************** * File Name: profile.controller.js (admin) * Type of Program: Controller * Description: Self-service profile management for admin users. * All routes require: authenticate → requireAdmin() * * Endpoints: * GET /api/admin/profile → view own profile * PUT /api/admin/profile → update personal_info * POST /api/admin/profile/avatar → upload / replace avatar * DELETE /api/admin/profile/avatar → remove avatar * * Author: Kenneth Obsequio (@lash0000) * Date Created: Jun. 18, 2026 ***********************************************************************************************************************************************************************/ 'use strict'; const mdl_Users = require('../../models/users/users.mdl'); const R = require('../../utils/response.util'); const { replaceUserAvatar, removeUserAvatar } = require('../../services/avatar.service'); const { resolveUserAvatar } = require('../../utils/resolveAvatar.util'); // ─── GET own profile ─────────────────────────────────────────────────────────── exports.getProfile = async (req, res) => { try { const user = await mdl_Users.findByPk(req.user.user_id, { attributes: { exclude: ['password', 'otp_code', 'otp_expires_at'] }, }); return R.success(res, 'Profile retrieved.', await resolveUserAvatar(user)); } catch (err) { return R.error(res, 'Could not retrieve profile.', 500); } }; // ─── PUT update own profile ──────────────────────────────────────────────────── exports.updateProfile = async (req, res) => { try { const user = await mdl_Users.findByPk(req.user.user_id); const { personal_info } = req.body; const merged = { ...(user.personal_info || {}), ...(personal_info || {}), name: { ...((user.personal_info?.name) || {}), ...((personal_info?.name) || {}), }, }; await user.update({ personal_info: merged }); const updated = await mdl_Users.findByPk(req.user.user_id, { attributes: { exclude: ['password', 'otp_code', 'otp_expires_at'] }, }); return R.success(res, 'Profile updated.', await resolveUserAvatar(updated)); } catch (err) { console.error('[ADMIN] updateProfile error:', err); return R.error(res, 'Profile update failed.', 500); } }; // ─── POST upload own avatar ──────────────────────────────────────────────────── exports.uploadAvatar = async (req, res) => { try { if (!req.file) return R.error(res, 'No file provided.', 400); const user = await mdl_Users.findByPk(req.user.user_id); const avatarMeta = await replaceUserAvatar(user, req.file); const merged = { ...(user.personal_info || {}), avatar: avatarMeta }; await user.update({ personal_info: merged }); const updated = await mdl_Users.findByPk(req.user.user_id, { attributes: { exclude: ['password', 'otp_code', 'otp_expires_at'] }, }); return R.success(res, 'Avatar updated.', await resolveUserAvatar(updated)); } catch (err) { if (err.status === 400) return R.error(res, err.message, 400); console.error('[ADMIN] uploadAvatar error:', err); return R.error(res, 'Avatar upload failed.', 500); } }; // ─── DELETE remove own avatar ────────────────────────────────────────────────── exports.deleteAvatar = async (req, res) => { try { const user = await mdl_Users.findByPk(req.user.user_id); await removeUserAvatar(user); const merged = { ...(user.personal_info || {}), avatar: null }; await user.update({ personal_info: merged }); return R.success(res, 'Avatar removed.'); } catch (err) { if (err.status === 404) return R.error(res, err.message, 404); console.error('[ADMIN] deleteAvatar error:', err); return R.error(res, 'Could not remove avatar.', 500); } };