mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -34,10 +34,48 @@ const { excludeAttributes: usersExclude, jsonbSchemas: usersSchemas, computedAtt
|
||||
const EXCLUDED = ['password', 'otp_code', 'otp_expires_at', 'must_change_password', 'password_expires_at'];
|
||||
const auditByFields = ['createdBy', 'updatedBy', 'deletedBy'];
|
||||
|
||||
// ─── GROUPS FILTER ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// "groups" is a M2M association, not a real column on `users` — buildQuery's
|
||||
// generic Sequelize.col()-based filtering can't touch it. Pull any `groups`
|
||||
// filter out of the request's filter list (so paginate() never sees a field
|
||||
// it can't resolve) and turn it into an EXISTS subquery instead. EXISTS keeps
|
||||
// the LEFT JOIN group data on each row intact (all of a user's groups still
|
||||
// show up), while only matching users who belong to at least one of the
|
||||
// selected groups.
|
||||
function extractGroupsFilter(req) {
|
||||
let filters = [];
|
||||
try { filters = JSON.parse(req.query.filters || '[]'); } catch { filters = []; }
|
||||
|
||||
const groupsFilter = filters.find((f) => f.id === 'groups');
|
||||
const remaining = filters.filter((f) => f.id !== 'groups');
|
||||
req.query.filters = JSON.stringify(remaining);
|
||||
|
||||
if (!groupsFilter?.value) return null;
|
||||
|
||||
const groupIds = (Array.isArray(groupsFilter.value) ? groupsFilter.value : [groupsFilter.value])
|
||||
.map((v) => parseInt(v, 10))
|
||||
.filter((v) => !Number.isNaN(v));
|
||||
|
||||
return groupIds.length ? groupIds : null;
|
||||
}
|
||||
|
||||
function groupsExistsWhere(groupIds) {
|
||||
if (!groupIds) return undefined;
|
||||
return Sequelize.literal(`EXISTS (
|
||||
SELECT 1 FROM "user_group_members" ugm
|
||||
WHERE ugm.user_id = "User"."user_id"
|
||||
AND ugm."deletedAt" IS NULL
|
||||
AND ugm.group_id IN (${groupIds.join(',')})
|
||||
)`);
|
||||
}
|
||||
|
||||
// ─── GET ALL ──────────────────────────────────────────────────────────────────
|
||||
|
||||
exports.getUsers = async (req, res) => {
|
||||
try {
|
||||
const groupIds = extractGroupsFilter(req);
|
||||
|
||||
const result = await paginate(mdl_Users, req, {
|
||||
excludeAttributes: usersExclude,
|
||||
jsonbSchemas: usersSchemas,
|
||||
@@ -46,6 +84,7 @@ exports.getUsers = async (req, res) => {
|
||||
context: "list",
|
||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||
findOptions: {
|
||||
where: groupsExistsWhere(groupIds),
|
||||
include: [{
|
||||
model: mdl_UserGroups,
|
||||
as: 'groups',
|
||||
@@ -470,18 +509,37 @@ exports.terminateSession = async (req, res) => {
|
||||
|
||||
// ─── FIELD VALUES ─────────────────────────────────────────────────────────────
|
||||
|
||||
exports.getUserFieldValues = getFieldValues(mdl_Users, "USER", {
|
||||
const getUserFieldValuesBase = getFieldValues(mdl_Users, "USER", {
|
||||
blockedFields: ["password", "otp_code", "otp_expires_at", "personal_info"],
|
||||
extraDateFields: ["modifiedAt", "ban_expires_at"],
|
||||
allowJsonb: true,
|
||||
selfJoin: true,
|
||||
});
|
||||
|
||||
// "groups" isn't a Users model attribute, so the generic getFieldValues()
|
||||
// helper can't resolve it — special-case it here, delegate everything else.
|
||||
exports.getUserFieldValues = async (req, res) => {
|
||||
if (req.query.field === 'groups') {
|
||||
const groups = await mdl_UserGroups.findAll({
|
||||
attributes: [['group_id', 'value'], ['name', 'label']],
|
||||
order: [['name', 'ASC']],
|
||||
raw: true,
|
||||
});
|
||||
return R.success(res, 'Field values retrieved.', groups);
|
||||
}
|
||||
|
||||
return getUserFieldValuesBase(req, res);
|
||||
};
|
||||
|
||||
// ─── ARCHIVED ─────────────────────────────────────────────────────────────────
|
||||
|
||||
// ─── GET ARCHIVED USERS ───────────────────────────────────────────────────────
|
||||
exports.getArchivedUsers = async (req, res) => {
|
||||
try {
|
||||
const groupIds = extractGroupsFilter(req);
|
||||
const archivedWhere = { deletedAt: { [Op.ne]: null }, is_active: false };
|
||||
const groupsWhere = groupsExistsWhere(groupIds);
|
||||
|
||||
const result = await paginate(mdl_Users, req, {
|
||||
excludeAttributes: usersExclude,
|
||||
jsonbSchemas: usersSchemas,
|
||||
@@ -491,7 +549,7 @@ exports.getArchivedUsers = async (req, res) => {
|
||||
auditOptions: { mdl_Users, parentAlias: 'User' },
|
||||
findOptions: {
|
||||
paranoid: false,
|
||||
where: { deletedAt: { [Op.ne]: null }, is_active: false },
|
||||
where: groupsWhere ? { [Op.and]: [archivedWhere, groupsWhere] } : archivedWhere,
|
||||
include: [{
|
||||
model: mdl_UserGroups,
|
||||
as: 'groups',
|
||||
|
||||
Reference in New Issue
Block a user