import { PrismaClient } from '@prisma/client'; import * as bcrypt from 'bcryptjs'; import * as crypto from 'crypto'; const prisma = new PrismaClient(); function sha256(input: string): string { return crypto.createHash('sha256').update(input).digest('hex'); } async function main() { const email = process.env.SUPER_ADMIN_EMAIL; const password = process.env.SUPER_ADMIN_PASSWORD; const testEmail = process.env.TEST_ADMIN_EMAIL || 'test-admin@zhixi.com'; const testPassword = process.env.TEST_ADMIN_PASSWORD || 'test-zhixi-admin-2026'; if (!email || !password) { console.error('❌ 请设置环境变量 SUPER_ADMIN_EMAIL 和 SUPER_ADMIN_PASSWORD'); process.exit(1); } if (password.length < 8) { console.error('❌ SUPER_ADMIN_PASSWORD 长度不能少于 8 位'); process.exit(1); } const passwordHash = await bcrypt.hash(password, 12); const adminUser = await prisma.adminUser.upsert({ where: { email }, update: { passwordHash, role: 'SUPER_ADMIN', status: 'ACTIVE', displayName: '超级管理员', }, create: { email, passwordHash, displayName: '超级管理员', role: 'SUPER_ADMIN', status: 'ACTIVE', }, }); console.log(`✅ 超级管理员已创建/更新: ${adminUser.email} (id: ${adminUser.id})`); // ── 测试专用管理员 + 永久 API Key ── const testPasswordHash = await bcrypt.hash(testPassword, 12); const testAdmin = await prisma.adminUser.upsert({ where: { email: testEmail }, update: { passwordHash: testPasswordHash, role: 'SUPER_ADMIN', status: 'ACTIVE', displayName: '自动化测试', }, create: { email: testEmail, passwordHash: testPasswordHash, displayName: '自动化测试', role: 'SUPER_ADMIN', status: 'ACTIVE', }, }); console.log(`✅ 测试管理员已创建/更新: ${testAdmin.email} (id: ${testAdmin.id})`); // Generate permanent API key (only if --new-key flag or first time) const args = process.argv.slice(2); const forceNew = args.includes('--new-key'); const existingKey = !forceNew ? await prisma.adminApiKey.findFirst({ where: { adminUserId: testAdmin.id, name: 'auto-test-key', expiresAt: null }, }) : null; if (existingKey) { console.log(`ℹ️ 永久 API Key 已存在 (prefix: ${existingKey.prefix}...),跳过生成。使用 --new-key 强制重新生成`); } else { const rawKey = `zxat_${crypto.randomBytes(32).toString('hex')}`; const keyHash = sha256(rawKey); const prefix = rawKey.slice(0, 8); await prisma.adminApiKey.create({ data: { adminUserId: testAdmin.id, name: 'auto-test-key', keyHash, prefix, expiresAt: null, // 永不过期 createdBy: 'seed', }, }); console.log(''); console.log('═══════════════════════════════════════════════════════'); console.log('🔑 测试管理员永久 API Key(请妥善保存):'); console.log(` ${rawKey}`); console.log('═══════════════════════════════════════════════════════'); console.log(` Email: ${testEmail}`); console.log(` Password: ${testPassword}`); console.log(' 使用方式: x-api-key header'); console.log('═══════════════════════════════════════════════════════'); } } main() .catch((e) => { console.error('❌ Seed 失败:', e); process.exit(1); }) .finally(() => prisma.$disconnect());