Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 1x 1x 1x 4x 4x 4x 3x 3x 4x 4x 2x 2x 4x 4x 2x 2x 2x 2x 2x 3x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | /**
* Cron job: expire bans whose expiresAt has passed.
*
* Queries deviceBans and networkBans for docs with a non-null expiresAt
* that is in the past, deletes them via batch writes, and optionally
* notifies admin via FCM using the shared utility.
*/
const { db } = require('../utils/firebase');
const { sendFcmToTokens, cleanupInvalidTokens } = require('../utils/fcm');
const log = require('../utils/log');
async function expireBans() {
const nowIso = new Date().toISOString();
// Query expired device bans
const deviceSnap = await db.collection('deviceBans').where('expiresAt', '!=', null).get();
const expiredDeviceDocs = deviceSnap.docs.filter((d) => {
const expiresAt = d.data().expiresAt;
return expiresAt && expiresAt < nowIso;
});
// Query expired network bans
const networkSnap = await db.collection('networkBans').where('expiresAt', '!=', null).get();
const expiredNetworkDocs = networkSnap.docs.filter((d) => {
const expiresAt = d.data().expiresAt;
return expiresAt && expiresAt < nowIso;
});
const allExpired = [...expiredDeviceDocs, ...expiredNetworkDocs];
if (allExpired.length === 0) {
return;
}
// Batch delete expired bans (max 500 per batch)
for (let i = 0; i < allExpired.length; i += 500) {
const batch = db.batch();
const chunk = allExpired.slice(i, i + 500);
for (const doc of chunk) {
batch.delete(doc.ref);
}
await batch.commit();
}
const removed = allExpired.length;
log.info('cron', 'expireBans: removed expired bans', { count: removed });
// Notify admin users via FCM
try {
const configSnap = await db.doc('alertConfig/settings').get();
if (!configSnap.exists) return;
const config = configSnap.data();
const recipientUserIds = config.fcmRecipientUserIds || [];
Iif (recipientUserIds.length === 0) return;
for (const userId of recipientUserIds) {
const userSnap = await db.doc(`users/${userId}`).get();
Iif (!userSnap.exists) continue;
const userData = userSnap.data();
const fcmTokens = userData.fcmTokens || [];
Iif (fcmTokens.length === 0) continue;
const invalidTokens = await sendFcmToTokens(fcmTokens, {
type: 'admin_notification',
title: 'Bans Expired',
body: `${removed} ban(s) have expired and been removed.`,
});
await cleanupInvalidTokens(invalidTokens, userId);
}
} catch (err) {
log.error('cron', 'expireBans notification error', { error: err.message });
}
}
module.exports = expireBans;
|