test again

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-13 12:46:38 +08:00
parent e5e2580c7d
commit f5254f7571
12 changed files with 441 additions and 461 deletions
+60 -2
View File
@@ -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',