mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Adjusted
This commit is contained in:
@@ -11,18 +11,18 @@ const { Op, Sequelize } = require('sequelize');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const mdl_Users = require('../../models/users/users.mdl');
|
||||
const mdl_Users = require('../../models/users/users.mdl');
|
||||
const mdl_UserSessions = require('../../models/users/user_sessions.mdl');
|
||||
const { mdl_UserGroups, mdl_UserGroupMembers } = require('../../models/users/user_groups.mdl');
|
||||
|
||||
const sendEmail = require('../../services/email.service');
|
||||
const R = require('../../utils/response.util');
|
||||
const { paginate } = require('../../utils/paginate.util');
|
||||
const R = require('../../utils/response.util');
|
||||
const { paginate } = require('../../utils/paginate.util');
|
||||
const { enrichPersonalInfo } = require('../../utils/personalInfo.util');
|
||||
|
||||
const { excludeAttributes: usersExclude, jsonbSchemas: usersSchemas } = require('../../models/users/users.attributes');
|
||||
|
||||
const EXCLUDED = ['password', 'otp_code', 'otp_expires_at', 'must_change_password', 'password_expires_at'];
|
||||
const EXCLUDED = ['password', 'otp_code', 'otp_expires_at', 'must_change_password', 'password_expires_at'];
|
||||
const auditByFields = ['createdBy', 'updatedBy', 'deletedBy'];
|
||||
|
||||
// ─── GET ALL ──────────────────────────────────────────────────────────────────
|
||||
@@ -31,9 +31,10 @@ exports.getUsers = async (req, res) => {
|
||||
try {
|
||||
const result = await paginate(mdl_Users, req, {
|
||||
excludeAttributes: usersExclude,
|
||||
jsonbSchemas: usersSchemas,
|
||||
jsonbColumn: 'personal_info',
|
||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||
jsonbSchemas: usersSchemas,
|
||||
jsonbColumn: 'personal_info',
|
||||
context: "list",
|
||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||
});
|
||||
|
||||
return R.success(res, 'Users retrieved.', result);
|
||||
@@ -54,7 +55,7 @@ exports.getUser = async (req, res) => {
|
||||
attributes: { exclude: EXCLUDED },
|
||||
include: [{
|
||||
model: mdl_UserGroups,
|
||||
as: 'groups',
|
||||
as: 'groups',
|
||||
through: { attributes: [] },
|
||||
}],
|
||||
});
|
||||
@@ -82,23 +83,23 @@ exports.addStaffUser = async (req, res) => {
|
||||
const existing = await mdl_Users.findOne({ where: { email } });
|
||||
if (existing) return R.error(res, 'Email is already in use.', 409);
|
||||
|
||||
const plainPassword = crypto.randomBytes(8).toString('base64url').slice(0, 12);
|
||||
const hashed = await bcrypt.hash(plainPassword, 12);
|
||||
const plainPassword = crypto.randomBytes(8).toString('base64url').slice(0, 12);
|
||||
const hashed = await bcrypt.hash(plainPassword, 12);
|
||||
const passwordExpiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
||||
const enriched = enrichPersonalInfo(personal_info);
|
||||
const fullName = enriched?.name?.full_name ?? email;
|
||||
const enriched = enrichPersonalInfo(personal_info);
|
||||
const fullName = enriched?.name?.full_name ?? email;
|
||||
|
||||
const user = await mdl_Users.create({
|
||||
email,
|
||||
password: hashed,
|
||||
password_expires_at: passwordExpiresAt,
|
||||
password: hashed,
|
||||
password_expires_at: passwordExpiresAt,
|
||||
must_change_password: true,
|
||||
acc_type: 'staff',
|
||||
reg_type: 'system',
|
||||
is_active: true,
|
||||
is_verified: true,
|
||||
createdBy: req.user.user_id,
|
||||
personal_info: enriched,
|
||||
acc_type: 'staff',
|
||||
reg_type: 'system',
|
||||
is_active: true,
|
||||
is_verified: true,
|
||||
createdBy: req.user.user_id,
|
||||
personal_info: enriched,
|
||||
});
|
||||
|
||||
await sendEmail({
|
||||
@@ -108,8 +109,8 @@ exports.addStaffUser = async (req, res) => {
|
||||
});
|
||||
|
||||
return R.success(res, 'Staff user created successfully.', {
|
||||
user_id: user.user_id,
|
||||
email: user.email,
|
||||
user_id: user.user_id,
|
||||
email: user.email,
|
||||
acc_type: user.acc_type,
|
||||
}, 201);
|
||||
} catch (err) {
|
||||
@@ -205,7 +206,7 @@ exports.bulkDeactivateUsers = async (req, res) => {
|
||||
|
||||
return R.success(res, `${activeIds.length} user(s) deactivated successfully.`, {
|
||||
deactivated_ids: activeIds,
|
||||
skipped_ids: ids.filter((id) => !activeIds.includes(id)),
|
||||
skipped_ids: ids.filter((id) => !activeIds.includes(id)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][BULK DEACTIVATE USERS]', err);
|
||||
@@ -220,7 +221,7 @@ exports.restoreUser = async (req, res) => {
|
||||
const user = await mdl_Users.findOne({
|
||||
where: { user_id: req.params.id }, paranoid: false,
|
||||
});
|
||||
if (!user) return R.error(res, 'User not found.', 404);
|
||||
if (!user) return R.error(res, 'User not found.', 404);
|
||||
if (!user.deletedAt) return R.error(res, 'User is not deactivated.', 400);
|
||||
|
||||
await user.restore();
|
||||
@@ -258,7 +259,7 @@ exports.bulkRestoreUsers = async (req, res) => {
|
||||
|
||||
return R.success(res, `${deletedIds.length} user(s) restored successfully.`, {
|
||||
restored_ids: deletedIds,
|
||||
skipped_ids: ids.filter((id) => !deletedIds.includes(id)),
|
||||
skipped_ids: ids.filter((id) => !deletedIds.includes(id)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][BULK RESTORE USERS]', err);
|
||||
@@ -271,9 +272,9 @@ exports.bulkRestoreUsers = async (req, res) => {
|
||||
exports.getUserSessions = async (req, res) => {
|
||||
try {
|
||||
const sessions = await mdl_UserSessions.findAll({
|
||||
where: { user_id: req.params.id },
|
||||
where: { user_id: req.params.id },
|
||||
attributes: { exclude: ['refresh_token_hash'] },
|
||||
order: [['createdAt', 'DESC']],
|
||||
order: [['createdAt', 'DESC']],
|
||||
});
|
||||
return R.success(res, 'Sessions retrieved.', sessions);
|
||||
} catch (err) {
|
||||
@@ -288,7 +289,7 @@ exports.terminateSession = async (req, res) => {
|
||||
if (!session) return R.error(res, 'Session not found.', 404);
|
||||
|
||||
await session.update({
|
||||
is_active: false,
|
||||
is_active: false,
|
||||
logout_info: { date: new Date().toISOString(), forced_by: req.user.user_id },
|
||||
});
|
||||
|
||||
@@ -332,7 +333,7 @@ exports.getUserFieldValues = async (req, res) => {
|
||||
attributes: [[Sequelize.fn('DISTINCT', Sequelize.fn('DATE', Sequelize.col(field))), 'value']],
|
||||
where: { [field]: { [Op.ne]: null } },
|
||||
order: [[Sequelize.fn('DATE', Sequelize.col(field)), 'DESC']],
|
||||
raw: true,
|
||||
raw: true,
|
||||
});
|
||||
return R.success(res, 'Field values retrieved.', results.map((r) => r.value).filter(Boolean));
|
||||
}
|
||||
@@ -340,14 +341,14 @@ exports.getUserFieldValues = async (req, res) => {
|
||||
const results = await mdl_Users.findAll({
|
||||
attributes: [[Sequelize.fn('DISTINCT', Sequelize.col(field)), 'value']],
|
||||
where: { [field]: { [Op.ne]: null } },
|
||||
raw: true,
|
||||
raw: true,
|
||||
});
|
||||
return R.success(res, 'Field values retrieved.', results.map((r) => r.value).filter(Boolean).sort());
|
||||
}
|
||||
|
||||
// ─── JSONB dot-notation ───────────────────────────────────────────────
|
||||
const [column, ...pathParts] = field.split('.');
|
||||
const keys = [...pathParts];
|
||||
const keys = [...pathParts];
|
||||
const lastKey = keys.pop();
|
||||
const jsonbPath = keys.length
|
||||
? `"${column}"->${keys.map((k) => `'${k}'`).join('->')}->>'${lastKey}'`
|
||||
@@ -356,7 +357,7 @@ exports.getUserFieldValues = async (req, res) => {
|
||||
const results = await mdl_Users.findAll({
|
||||
attributes: [[Sequelize.literal(`DISTINCT ${jsonbPath}`), 'value']],
|
||||
where: Sequelize.literal(`${jsonbPath} IS NOT NULL`),
|
||||
raw: true,
|
||||
raw: true,
|
||||
});
|
||||
|
||||
return R.success(res, 'Field values retrieved.', results.map((r) => r.value).filter(Boolean).sort());
|
||||
@@ -372,12 +373,13 @@ exports.getArchivedUsers = async (req, res) => {
|
||||
try {
|
||||
const result = await paginate(mdl_Users, req, {
|
||||
excludeAttributes: usersExclude,
|
||||
jsonbSchemas: usersSchemas,
|
||||
jsonbColumn: 'personal_info',
|
||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||
jsonbSchemas: usersSchemas,
|
||||
jsonbColumn: 'personal_info',
|
||||
context: "archived",
|
||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||
findOptions: {
|
||||
paranoid: false,
|
||||
where: { deletedAt: { [Op.ne]: null }, is_active: false },
|
||||
where: { deletedAt: { [Op.ne]: null }, is_active: false },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user