- withSuperAdmin() HOF: checks isSuperAdmin from session, returns 401/403 - GET /api/admin/tenants: lists all tenants with userCount, subscriberCount - GET /api/admin/tenants/[id]: single tenant detail with users list - POST /api/admin/tenants/[id]/suspend: suspend/activate with 7-day grace - prisma/seed.ts: add Test ISP 2 tenant and admin2@demo.com for isolation tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
141 lines
4.2 KiB
TypeScript
141 lines
4.2 KiB
TypeScript
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();
|
|
});
|