// backfill email_lookup from user_profile.email (decrypt if needed) import dotenv from 'dotenv'; dotenv.config(); // only used if you run outside compose import crypto from 'crypto'; import mysqlPool from '../config/mysqlPool.js'; import { initEncryption, decrypt } from '../shared/crypto/encryption.js'; const sql = mysqlPool.raw || mysqlPool; const EMAIL_INDEX_KEY = process.env.EMAIL_INDEX_SECRET || process.env.JWT_SECRET || 'dev-fallback'; function emailLookup(s) { return crypto .createHmac('sha256', EMAIL_INDEX_KEY) .update(String(s).trim().toLowerCase()) .digest('hex'); } async function run() { await initEncryption(); // needed if some emails are gcm:… encrypted const [rows] = await sql.query('SELECT id, email FROM user_profile'); let updated = 0, skipped = 0, failed = 0; for (const r of rows) { try { let plain = r.email || ''; if (plain && plain.startsWith('gcm:')) { // decrypt returns plaintext email plain = await decrypt(plain); } if (!plain) { skipped++; continue; } const lookup = emailLookup(plain); await sql.query( 'UPDATE user_profile SET email_lookup = ? WHERE id = ? LIMIT 1', [lookup, r.id] ); updated++; } catch (e) { failed++; console.error('[backfill]', r.id, e?.message || e); } } console.log(`✅ backfill complete updated=${updated} skipped=${skipped} failed=${failed}`); } // Allow top‑level await in ESM; otherwise wrap: run().then(() => process.exit(0)).catch(err => { console.error(err); process.exit(1); });