import dotenv from "dotenv"; import path from "path"; dotenv.config({ path: path.resolve(__dirname, "../.env.local") }); import mongoose from "mongoose"; import { connectDb } from "../src/lib/server/db"; import { User } from "../src/lib/server/models/User"; import { platformAdminEmails } from "../src/lib/server/platform"; import { crossTenant } from "../src/lib/server/tenantGuard"; /** * One-off, safe to re-run. Moves user identity from platform-wide to * per-business uniqueness: * * 1. Marks today's platform operators. Until now an operator was anyone * whose email was in PLATFORM_ADMIN_EMAILS; emails were unique, so * that was one account each. From now on emails are only unique per * business, so access also needs the platformAdmin flag on the account. * Run this BEFORE dropping the old index, while each listed email * still matches exactly one account. * 2. Syncs the User indexes: drops the old unique `email_1` and * `phoneNumber_1`, creates unique (businessId, email) and * (businessId, phoneNumber), and a plain email lookup index. * * npm run migrate:identity */ async function main() { await connectDb(); for (const email of platformAdminEmails()) { const accounts = await User.find({ email }).select("_id").lean(); if (accounts.length === 1) { await User.updateOne({ _id: accounts[0]._id }, { $set: { platformAdmin: true } }); console.log(`Platform operator: ${email}`); } else if (accounts.length === 0) { console.warn(`No account for ${email} - create it with npm run seed.`); } else { console.warn(`${email} has ${accounts.length} accounts - set platformAdmin on the right one by hand.`); } } const dropped = await User.syncIndexes(); console.log(`User indexes synced. Dropped: ${dropped.length ? dropped.join(", ") : "none"}.`); await mongoose.disconnect(); } crossTenant("identity migration spans every business", main).catch((err) => { console.error("migration failed:", err.message); process.exit(1); });