changemaker.lite/map/app/services/accountExpiration.js
bunker-admin a77306fac2 Initial v2 commit: complete rebuild with unified API + React admin
Phase 1-14 complete:
- Unified Express.js API (TypeScript, Prisma ORM, PostgreSQL 16)
- React Admin GUI (Vite + Ant Design + Zustand)
- JWT auth with refresh tokens
- Influence: Campaigns, Representatives, Responses, Email Queue
- Map: Locations, Cuts, Shifts, Canvassing System
- NAR data import infrastructure (2025 format)
- Listmonk newsletter integration
- Landing page builder (GrapesJS)
- MkDocs + Code Server integration
- Volunteer portal with GPS tracking
- Monitoring stack (Prometheus, Grafana, Alertmanager)
- Pangolin tunnel integration

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 10:05:04 -07:00

89 lines
2.5 KiB
JavaScript

const nocodbService = require('./nocodb');
const logger = require('../utils/logger');
const config = require('../config');
class AccountExpirationService {
constructor() {
this.checkInterval = null;
}
// Start the expiration check service
start() {
// Run check every hour
this.checkInterval = setInterval(() => {
this.checkExpiredAccounts();
}, 60 * 60 * 1000); // 1 hour
// Also run immediately on start
this.checkExpiredAccounts();
logger.info('Account expiration service started');
}
// Stop the service
stop() {
if (this.checkInterval) {
clearInterval(this.checkInterval);
this.checkInterval = null;
}
}
// Check and handle expired accounts
async checkExpiredAccounts() {
try {
// Get all users
const users = await nocodbService.getLoginRecords();
const now = new Date();
const expiredUsers = [];
for (const user of users) {
if (user.ExpiresAt && new Date(user.ExpiresAt) < now) {
expiredUsers.push(user);
}
}
// Delete expired accounts
for (const user of expiredUsers) {
await this.deleteExpiredAccount(user);
}
if (expiredUsers.length > 0) {
logger.info(`Deleted ${expiredUsers.length} expired temp accounts`);
}
} catch (error) {
logger.error('Error checking expired accounts:', error);
}
}
// Delete a single expired account
async deleteExpiredAccount(user) {
try {
await nocodbService.deleteRecord(
config.nocodb.loginSheetId,
user.Id
);
logger.info(`Deleted expired temp account: ${user.Email}`);
// Optional: Send notification email before deletion
// await emailService.sendAccountExpirationNotice(user.Email);
} catch (error) {
logger.error(`Failed to delete expired account ${user.Email}:`, error);
}
}
// Calculate expiration date based on admin settings
static calculateExpirationDate(expireDays) {
if (!expireDays || expireDays <= 0) return null;
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + expireDays);
return expirationDate;
}
}
module.exports = new AccountExpirationService();