mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
92 lines
4.0 KiB
JavaScript
92 lines
4.0 KiB
JavaScript
/***********************************************************************************************************************************************************************
|
|
* File Name: profile.controller.js (client)
|
|
* Type of Program: Controller
|
|
* Description: Self-service profile management for CLIENT users.
|
|
* All routes require: authenticate → requireClient()
|
|
*
|
|
* Endpoints:
|
|
* GET /api/client/profile → view own profile
|
|
* PUT /api/client/profile → update personal_info
|
|
* GET /api/client/sessions → view own active sessions
|
|
* DELETE /api/client/sessions/:id → revoke a specific session
|
|
*
|
|
* Author: rgrgogu
|
|
* Date Created: Oct. 6, 2025
|
|
***********************************************************************************************************************************************************************/
|
|
const mdl_Users = require('../../models/users/users.mdl');
|
|
const mdl_UserSessions = require('../../models/users/user_sessions.mdl');
|
|
const R = require('../../utils/response.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.', 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;
|
|
|
|
// Deep-merge personal_info so partial updates don't wipe existing data
|
|
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.', updated);
|
|
} catch (err) {
|
|
console.error('[CLIENT] updateProfile error:', err);
|
|
return R.error(res, 'Profile update failed.', 500);
|
|
}
|
|
};
|
|
|
|
// ─── GET own sessions ──────────────────────────────────────────────────────────
|
|
exports.getSessions = async (req, res) => {
|
|
try {
|
|
const sessions = await mdl_UserSessions.findAll({
|
|
where: { user_id: req.user.user_id, is_active: true },
|
|
order: [['createdAt', 'DESC']],
|
|
attributes: { exclude: ['refresh_token_hash'] },
|
|
});
|
|
return R.success(res, 'Sessions retrieved.', sessions);
|
|
} catch (err) {
|
|
return R.error(res, 'Could not retrieve sessions.', 500);
|
|
}
|
|
};
|
|
|
|
// ─── DELETE revoke a session ───────────────────────────────────────────────────
|
|
exports.revokeSession = async (req, res) => {
|
|
try {
|
|
const session = await mdl_UserSessions.findOne({
|
|
where: { session_id: req.params.id, user_id: req.user.user_id },
|
|
});
|
|
if (!session) return R.error(res, 'Session not found.', 404);
|
|
|
|
await session.update({
|
|
is_active: false,
|
|
logout_info: { date: new Date().toISOString(), ip_address: req.ip },
|
|
});
|
|
|
|
return R.success(res, 'Session revoked.');
|
|
} catch (err) {
|
|
return R.error(res, 'Could not revoke session.', 500);
|
|
}
|
|
}; |