mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
86 lines
3.4 KiB
JavaScript
86 lines
3.4 KiB
JavaScript
/***********************************************************************************************************************************************************************
|
|
* File Name : lift_expired_bans.cron.js
|
|
* Type : Cron Job
|
|
* Description : Automatically lifts temporary bans whose expires_at has passed.
|
|
* Clears is_banned + ban_expires_at on the user record and marks
|
|
* the ban row as lifted with a system lift_reason.
|
|
*
|
|
* Note: The auth middleware also auto-lifts expired bans inline on
|
|
* the next login attempt, so this cron is a safety net — it keeps
|
|
* the DB state clean even if a user never logs in again.
|
|
*
|
|
* Schedule : Every hour, on the hour ("0 * * * *"). Registered by
|
|
* cron/admin.cron.js.
|
|
*
|
|
* Author: Kenneth Obsequio
|
|
* Date Created: Jun. 27, 2026
|
|
***********************************************************************************************************************************************************************/
|
|
const { Op } = require('sequelize');
|
|
const sequelize = require('../../config/db.config');
|
|
const mdl_Users = require('../../models/users/users.mdl');
|
|
const mdl_UserBans = require('../../models/users/user_bans.mdl');
|
|
const { sendEmail } = require('../../services/email.service');
|
|
const { fmtDate } = require('../../utils/datetime.util');
|
|
|
|
async function run() {
|
|
try {
|
|
const expiredBans = await mdl_UserBans.findAll({
|
|
where: {
|
|
ban_type: 'temporary',
|
|
is_lifted: false,
|
|
expires_at: { [Op.lte]: new Date() },
|
|
},
|
|
});
|
|
|
|
if (!expiredBans.length) return;
|
|
|
|
const banIds = expiredBans.map((b) => b.ban_id);
|
|
const userIds = [...new Set(expiredBans.map((b) => Number(b.user_id)))];
|
|
const usersMap = await mdl_Users.findAll({
|
|
where: { user_id: userIds },
|
|
attributes: ['user_id', 'email', 'personal_info'],
|
|
}).then((rows) => Object.fromEntries(rows.map((u) => [u.user_id, u])));
|
|
|
|
await sequelize.transaction(async (t) => {
|
|
await mdl_UserBans.update(
|
|
{
|
|
is_lifted: true,
|
|
lifted_at: new Date(),
|
|
lift_reason: 'Automatically lifted — ban period expired.',
|
|
},
|
|
{ where: { ban_id: banIds }, transaction: t }
|
|
);
|
|
|
|
await mdl_Users.update(
|
|
{ is_banned: false, ban_expires_at: null },
|
|
{ where: { user_id: userIds }, transaction: t }
|
|
);
|
|
});
|
|
|
|
const dateStr = fmtDate(new Date());
|
|
userIds.forEach((uid) => {
|
|
const u = usersMap[uid];
|
|
if (!u) return;
|
|
sendEmail({
|
|
to: u.email,
|
|
type: 'BAN_LIFTED',
|
|
data: {
|
|
name: u.personal_info?.name?.full_name ?? 'User',
|
|
email: u.email,
|
|
date: dateStr,
|
|
},
|
|
}).catch((err) => console.error('[CRON][LIFT EXPIRED BANS] Email failed:', u.email, err));
|
|
});
|
|
|
|
console.log(`[CRON][LIFT EXPIRED BANS] Lifted ${expiredBans.length} ban(s) for ${userIds.length} user(s).`);
|
|
} catch (err) {
|
|
console.error('[CRON][LIFT EXPIRED BANS] Failed:', err);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
name: 'liftExpiredBans',
|
|
schedule: '0 * * * *',
|
|
run,
|
|
};
|