mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Adjusted
This commit is contained in:
@@ -129,6 +129,66 @@ exports.deactivateUser = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ─── BULK DEACTIVATE users ────────────────────────────────────────────────────
|
||||||
|
exports.bulkDeactivateUsers = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { ids } = req.body; // expects { ids: [1, 2, 3] }
|
||||||
|
|
||||||
|
if (!Array.isArray(ids) || ids.length === 0)
|
||||||
|
return R.error(res, 'No user IDs provided.', 400);
|
||||||
|
|
||||||
|
if (ids.includes(req.user.user_id))
|
||||||
|
return R.error(res, 'You cannot deactivate your own account.', 400);
|
||||||
|
|
||||||
|
const users = await mdl_Users.findAll({
|
||||||
|
where: { user_id: ids },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!users.length)
|
||||||
|
return R.error(res, 'No users found.', 404);
|
||||||
|
|
||||||
|
// Filter only currently active users — skip already-deactivated ones
|
||||||
|
const activeUsers = users.filter((u) => u.is_active && !u.deletedAt);
|
||||||
|
|
||||||
|
if (!activeUsers.length)
|
||||||
|
return R.error(res, 'All selected users are already deactivated.', 400);
|
||||||
|
|
||||||
|
const activeIds = activeUsers.map((u) => u.user_id);
|
||||||
|
|
||||||
|
// Soft-delete + mark who deactivated them
|
||||||
|
await mdl_Users.update(
|
||||||
|
{ is_active: false, deletedBy: req.user.user_id },
|
||||||
|
{ where: { user_id: activeIds } }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sequelize paranoid bulk destroy (sets deletedAt)
|
||||||
|
await mdl_Users.destroy({
|
||||||
|
where: { user_id: activeIds },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Force logout all their active sessions
|
||||||
|
await mdl_UserSessions.update(
|
||||||
|
{
|
||||||
|
is_active: false,
|
||||||
|
logout_info: {
|
||||||
|
date: new Date().toISOString(),
|
||||||
|
forced_by: req.user.user_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ where: { user_id: activeIds } }
|
||||||
|
);
|
||||||
|
|
||||||
|
return R.success(res, `${activeIds.length} user(s) deactivated successfully.`, {
|
||||||
|
deactivated_ids: activeIds,
|
||||||
|
// Inform caller if some were already inactive and got skipped
|
||||||
|
skipped_ids: ids.filter((id) => !activeIds.includes(id)),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[ADMIN][BULK DEACTIVATE USERS]", err);
|
||||||
|
return R.error(res, 'Could not deactivate users.', 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ─── RESTORE user ──────────────────────────────────────────────────────────────
|
// ─── RESTORE user ──────────────────────────────────────────────────────────────
|
||||||
exports.restoreUser = async (req, res) => {
|
exports.restoreUser = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
@@ -143,6 +203,7 @@ exports.restoreUser = async (req, res) => {
|
|||||||
await user.update({
|
await user.update({
|
||||||
is_active: true,
|
is_active: true,
|
||||||
updatedBy: req.user.user_id, // ← who restored
|
updatedBy: req.user.user_id, // ← who restored
|
||||||
|
deletedBy: null
|
||||||
});
|
});
|
||||||
|
|
||||||
return R.success(res, 'User restored successfully.');
|
return R.success(res, 'User restored successfully.');
|
||||||
@@ -152,6 +213,47 @@ exports.restoreUser = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ─── BULK RESTORE users ────────────────────────────────────────────────────────
|
||||||
|
exports.bulkRestoreUsers = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { ids } = req.body;
|
||||||
|
|
||||||
|
if (!Array.isArray(ids) || ids.length === 0)
|
||||||
|
return R.error(res, 'No user IDs provided.', 400);
|
||||||
|
|
||||||
|
const users = await mdl_Users.findAll({
|
||||||
|
where: { user_id: ids },
|
||||||
|
paranoid: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!users.length)
|
||||||
|
return R.error(res, 'No users found.', 404);
|
||||||
|
|
||||||
|
// Filter only soft-deleted users — skip already-active ones
|
||||||
|
const deletedUsers = users.filter((u) => u.deletedAt);
|
||||||
|
|
||||||
|
if (!deletedUsers.length)
|
||||||
|
return R.error(res, 'All selected users are already active.', 400);
|
||||||
|
|
||||||
|
const deletedIds = deletedUsers.map((u) => u.user_id);
|
||||||
|
|
||||||
|
await mdl_Users.restore({ where: { user_id: deletedIds } });
|
||||||
|
|
||||||
|
await mdl_Users.update(
|
||||||
|
{ is_active: true, updatedBy: req.user.user_id, deletedBy: null },
|
||||||
|
{ where: { user_id: deletedIds }, paranoid: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
return R.success(res, `${deletedIds.length} user(s) restored successfully.`, {
|
||||||
|
restored_ids: deletedIds,
|
||||||
|
skipped_ids: ids.filter((id) => !deletedIds.includes(id)),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[ADMIN][BULK RESTORE USERS]", err);
|
||||||
|
return R.error(res, 'Could not restore users.', 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
exports.getGroups = async (req, res) => {
|
exports.getGroups = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const result = await paginate(mdl_UserGroups, req, {
|
const result = await paginate(mdl_UserGroups, req, {
|
||||||
@@ -530,9 +632,9 @@ exports.getArchivedUsers = async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const result = await paginate(mdl_Users, req, {
|
const result = await paginate(mdl_Users, req, {
|
||||||
excludeAttributes: usersExclude,
|
excludeAttributes: usersExclude,
|
||||||
jsonbSchemas: usersSchemas,
|
jsonbSchemas: usersSchemas,
|
||||||
jsonbColumn: 'personal_info',
|
jsonbColumn: 'personal_info',
|
||||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||||
findOptions: {
|
findOptions: {
|
||||||
paranoid: false, // ← include soft-deleted rows
|
paranoid: false, // ← include soft-deleted rows
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ const { adminLimiter, sensitiveOpsLimiter } = require('../../middleware/rateLimi
|
|||||||
router.use(authenticate, requireAdmin(), adminLimiter);
|
router.use(authenticate, requireAdmin(), adminLimiter);
|
||||||
|
|
||||||
// ── User management ────────────────────────────────────────────────────────────
|
// ── User management ────────────────────────────────────────────────────────────
|
||||||
|
router.post('/users/bulk/restore', sensitiveOpsLimiter, usersCtrl.bulkRestoreUsers); // ← before /:id
|
||||||
|
router.delete('/users/bulk', sensitiveOpsLimiter, usersCtrl.bulkDeactivateUsers); // ← before /:id
|
||||||
router.get('/users/field-values', usersCtrl.getUserFieldValues); // ← before /:id
|
router.get('/users/field-values', usersCtrl.getUserFieldValues); // ← before /:id
|
||||||
router.get('/users/archived', usersCtrl.getArchivedUsers); // ← before /:id
|
router.get('/users/archived', usersCtrl.getArchivedUsers); // ← before /:id
|
||||||
router.get('/users', usersCtrl.getUsers);
|
router.get('/users', usersCtrl.getUsers);
|
||||||
|
|||||||
Reference in New Issue
Block a user