add: more things

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-06 15:21:55 +08:00
parent 7ba03ad4db
commit 095a0d4b3c
15 changed files with 756 additions and 211 deletions
@@ -104,6 +104,46 @@ exports.getActiveAdvertisement = async (req, res) => {
}
};
// ─── GET ACTIVE (list) ──────────────────────────────────────────────────────
//
// Resolves every live advertisement for a single placement, ordered by
// priority — used by carousel-style slots (e.g. dashboard.hero) that rotate
// through several ads instead of showing only the single highest-priority one.
//
// GET /api/client/advertisements/active-list?placement=dashboard.hero&limit=8
//
exports.getActiveAdvertisementList = async (req, res) => {
try {
const { placement } = req.query;
if (!placement) return R.error(res, "placement is required.", 400);
if (!PLACEMENT_MAP[placement]) return R.error(res, "Invalid placement.", 400);
const limit = Math.min(Math.max(parseInt(req.query.limit, 10) || 8, 1), 20);
const advertisements = await Advertisement.findAll({
where: liveWhere({ placement }),
order: [["order", "ASC"], ["createdAt", "DESC"]],
include: [AD_IMAGE_INCLUDE],
attributes: { exclude: AD_CLIENT_EXCLUDE },
limit,
});
const data = [];
for (const ad of advertisements) {
const json = ad.toJSON();
json.status = deriveStatus(json);
if (json.image) await attachImageStreamToken(json.image, req);
data.push(json);
}
return R.success(res, "Active advertisements retrieved.", { data });
} catch (err) {
console.error("[CLIENT][ADVERTISEMENT][GET ACTIVE LIST]", err);
return R.error(res, "Could not retrieve advertisements.", 500);
}
};
// ─── GET ACTIVE (batch) ─────────────────────────────────────────────────────
//
// Resolves the highest-priority live advertisement for each of several
+3
View File
@@ -17,6 +17,7 @@
const mdl_Users = require('../../models/users/users.mdl');
const mdl_UserSessions = require('../../models/users/user_sessions.mdl');
const mdl_Achievements = require('../../models/users/achievements.mdl');
const trustedDevice = require('../../services/trustedDevice.service');
const logActivity = require('../../utils/logActivity.util');
const R = require('../../utils/response.util');
const { uploadFile, deleteFile } = require('../../services/s3.service');
@@ -94,6 +95,7 @@ exports.revokeSession = async (req, res) => {
is_active: false,
logout_info: { date: new Date().toISOString(), ip_address: req.ip },
});
await trustedDevice.revokeBySessionId(session.session_id);
logActivity(req.user.user_id, 'revoke_session', { entityType: 'session', entityId: session.session_id });
@@ -177,6 +179,7 @@ exports.deleteAccount = async (req, res) => {
{ is_active: false, logout_info: { date: new Date().toISOString(), ip_address: req.ip, reason: 'account_deleted' } },
{ where: { user_id: req.user.user_id, is_active: true } },
);
await trustedDevice.revokeAllForUser(req.user.user_id);
// Anonymize email before soft-delete so the unique slot is freed for re-registration
await user.update({ email: `deleted_${req.user.user_id}@deleted.invalid`, deletedBy: req.user.user_id });