SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
11 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
2.4 KB · 36 lines typescript
Raw Blame History
1import { and, eq, inArray, lt, sql } from 'drizzle-orm';2import type { Database } from '@rareindex/database';3import { users, sessions, trustedDevices, authCodes, rateLimits, collections, collectionItems, watchlists, watchlistItems, alerts, alertEvents, notifications, savedSearches, priceTargets, recoveryCodes, loginEvents, apiKeys, userBadges, uploads, collectionSnapshots } from '@rareindex/database';4import { logger } from '@rareindex/shared';56const log = logger.child({ job: 'account.maintenance' });78/** Purge accounts past their grace period, expire codes/sessions, trim rate-limit rows. */9export async function runMaintenance(db: Database, now = new Date()): Promise<{ purged: number }> {10  const due = await db.select({ id: users.id }).from(users).where(and(sql`${users.deletedAt} is not null`, lt(users.purgeAfter, now)));11  for (const u of due) {12    const cols = await db.select({ id: collections.id }).from(collections).where(eq(collections.userId, u.id));13    const colIds = cols.map((c) => c.id);14    if (colIds.length) {15      await db.delete(collectionItems).where(inArray(collectionItems.collectionId, colIds));16      await db.delete(collectionSnapshots).where(inArray(collectionSnapshots.collectionId, colIds));17      await db.delete(collections).where(inArray(collections.id, colIds));18    }19    const wls = await db.select({ id: watchlists.id }).from(watchlists).where(eq(watchlists.userId, u.id));20    if (wls.length) {21      await db.delete(watchlistItems).where(inArray(watchlistItems.watchlistId, wls.map((w) => w.id)));22      await db.delete(watchlists).where(eq(watchlists.userId, u.id));23    }24    for (const t of [alertEvents, alerts, notifications, savedSearches, priceTargets, recoveryCodes, trustedDevices, sessions, loginEvents, apiKeys, userBadges, uploads]) {25      await db.delete(t).where(eq((t as unknown as { userId: typeof users.id }).userId, u.id));26    }27    await db.delete(authCodes).where(eq(authCodes.userId, u.id));28    await db.delete(users).where(eq(users.id, u.id));29    log.info({ userId: u.id }, 'account purged after grace period');30  }31  await db.delete(authCodes).where(lt(authCodes.expiresAt, new Date(now.getTime() - 7 * 86_400_000)));32  await db.delete(sessions).where(lt(sessions.expiresAt, new Date(now.getTime() - 30 * 86_400_000)));33  await db.delete(rateLimits).where(lt(rateLimits.resetAt, new Date(now.getTime() - 86_400_000)));34  return { purged: due.length };35}36