import { PrismaClient, TenantStatus } from "@prisma/client"; import bcrypt from "bcryptjs"; const prisma = new PrismaClient(); async function main() { console.log("Seeding database..."); // ----------------------------------------------------------------------- // Tenant: Demo ISP // ----------------------------------------------------------------------- const demoTenant = await prisma.tenant.upsert({ where: { slug: "demo-isp" }, update: {}, create: { name: "Demo ISP", slug: "demo-isp", ownerEmail: "admin@demo.com", status: TenantStatus.ACTIVE, }, }); console.log(`Tenant upserted: ${demoTenant.name} (${demoTenant.id})`); // ----------------------------------------------------------------------- // Admin user: admin@demo.com / admin123 // Scoped to Demo ISP tenant // ----------------------------------------------------------------------- const adminPasswordHash = await bcrypt.hash("admin123", 12); const adminUser = await prisma.user.upsert({ where: { email_tenantId: { email: "admin@demo.com", tenantId: demoTenant.id, }, }, update: {}, create: { email: "admin@demo.com", passwordHash: adminPasswordHash, firstName: "Demo", lastName: "Admin", tenantId: demoTenant.id, roles: ["ADMIN"], isActive: true, isSuperAdmin: false, }, }); console.log(`Admin user upserted: ${adminUser.email} (${adminUser.id})`); // ----------------------------------------------------------------------- // Super-admin: superadmin@netforge.com / super123 // No tenant — platform-wide access // ----------------------------------------------------------------------- const superAdminPasswordHash = await bcrypt.hash("super123", 12); // Super-admin has tenantId=null — use findFirst + create pattern since // @@unique([email, tenantId]) with null tenantId behaves differently across DBs const existingSuperAdmin = await prisma.user.findFirst({ where: { email: "superadmin@netforge.com", tenantId: null, }, }); const superAdmin = existingSuperAdmin ? existingSuperAdmin : await prisma.user.create({ data: { email: "superadmin@netforge.com", passwordHash: superAdminPasswordHash, firstName: "Super", lastName: "Admin", tenantId: null, roles: [], isActive: true, isSuperAdmin: true, }, }); console.log(`Super-admin upserted: ${superAdmin.email} (${superAdmin.id})`); // ----------------------------------------------------------------------- // Tenant: Test ISP 2 (for cross-tenant isolation testing) // ----------------------------------------------------------------------- const demoTenant2 = await prisma.tenant.upsert({ where: { slug: "test-isp-2" }, update: {}, create: { name: "Test ISP 2", slug: "test-isp-2", ownerEmail: "admin2@demo.com", status: TenantStatus.ACTIVE, }, }); console.log(`Tenant upserted: ${demoTenant2.name} (${demoTenant2.id})`); // ----------------------------------------------------------------------- // Admin user: admin2@demo.com / admin123 // Scoped to Test ISP 2 tenant (for cross-tenant isolation tests) // ----------------------------------------------------------------------- const admin2User = await prisma.user.upsert({ where: { email_tenantId: { email: "admin2@demo.com", tenantId: demoTenant2.id, }, }, update: {}, create: { email: "admin2@demo.com", passwordHash: adminPasswordHash, firstName: "Demo", lastName: "Admin2", tenantId: demoTenant2.id, roles: ["ADMIN"], isActive: true, isSuperAdmin: false, }, }); console.log(`Admin2 user upserted: ${admin2User.email} (${admin2User.id})`); console.log("\nSeed complete. Test credentials:"); console.log(" Admin: admin@demo.com / admin123"); console.log(" Admin2: admin2@demo.com / admin123"); console.log(" Super-admin: superadmin@netforge.com / super123"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });