/** * Ensure remoteApiToken for SMS pilot tenants (montpar.ir, k.montzar.ir). * Does NOT print token values — only reports which tenants were updated. * * Usage: npx ts-node --transpile-only prisma/ensure-pilot-sms-tokens.ts */ import { randomBytes } from 'crypto'; import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); const PILOT_DOMAINS = ['montpar.ir', 'k.montzar.ir']; function domainKeys(tenant: { domain: string | null; domains: unknown; }): string[] { const keys = [ tenant.domain?.toLowerCase(), ...((Array.isArray(tenant.domains) ? tenant.domains : []) as string[]).map((d) => String(d).toLowerCase(), ), ].filter(Boolean) as string[]; return keys; } async function main() { const tenants = await prisma.tenant.findMany({ where: { isActive: true }, select: { id: true, nameFa: true, domain: true, domains: true, remoteApiToken: true, product: true, }, }); let created = 0; let kept = 0; for (const domain of PILOT_DOMAINS) { const tenant = tenants.find((row) => domainKeys(row).includes(domain)); if (!tenant) { console.log(`missing tenant for domain=${domain}`); continue; } if (tenant.remoteApiToken && tenant.remoteApiToken.length >= 24) { kept += 1; console.log(`ok (token exists): ${tenant.nameFa} [${tenant.product}] ${domain}`); continue; } const token = randomBytes(32).toString('hex'); await prisma.tenant.update({ where: { id: tenant.id }, data: { remoteApiToken: token }, }); created += 1; console.log( `token created: ${tenant.nameFa} [${tenant.product}] ${domain} — copy from DB/UI into product SUPERADMIN_REMOTE_TOKEN`, ); } console.log({ pilots: PILOT_DOMAINS.length, created, kept }); } main() .catch((err) => { console.error(err); process.exitCode = 1; }) .finally(async () => { await prisma.$disconnect(); });