library-picturebook-activity/backend/scripts/init-super-tenant.ts
2025-12-09 11:10:36 +08:00

323 lines
9.7 KiB
TypeScript

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
// 加载环境变量(必须在其他导入之前)
import * as dotenv from 'dotenv';
import * as path from 'path';
// 根据 NODE_ENV 加载对应的环境配置文件
const nodeEnv = process.env.NODE_ENV || 'development';
const envFile = `.env.${nodeEnv}`;
// scripts 目录的父目录就是 backend 目录
const backendDir = path.resolve(__dirname, '..');
const envPath = path.resolve(backendDir, envFile);
// 尝试加载环境特定的配置文件
dotenv.config({ path: envPath });
// 如果环境特定文件不存在,尝试加载默认的 .env 文件
if (!process.env.DATABASE_URL) {
dotenv.config({ path: path.resolve(backendDir, '.env') });
}
// 验证必要的环境变量
if (!process.env.DATABASE_URL) {
console.error('❌ 错误: 未找到 DATABASE_URL 环境变量');
console.error(` 请确保存在以下文件之一:`);
console.error(` - ${envPath}`);
console.error(` - ${path.resolve(backendDir, '.env')}`);
console.error(` 或者设置 NODE_ENV 环境变量(当前: ${nodeEnv})`);
process.exit(1);
}
import { PrismaClient } from '@prisma/client';
import * as bcrypt from 'bcrypt';
const prisma = new PrismaClient();
async function main() {
console.log('🚀 开始初始化超级租户...\n');
// 检查是否已存在超级租户
let superTenant = await prisma.tenant.findFirst({
where: { isSuper: 1 },
});
if (superTenant) {
console.log('⚠️ 超级租户已存在,将更新菜单分配');
console.log(` 租户编码: ${superTenant.code}\n`);
} else {
// 创建超级租户
superTenant = await prisma.tenant.create({
data: {
name: '超级租户',
code: 'super',
domain: 'super',
description: '系统超级租户,拥有所有权限',
isSuper: 1,
validState: 1,
},
});
console.log('✅ 超级租户创建成功!');
console.log(` 租户ID: ${superTenant.id}`);
console.log(` 租户编码: ${superTenant.code}`);
console.log(` 租户名称: ${superTenant.name}\n`);
}
// 创建或获取超级管理员用户
console.log('📋 步骤 2: 创建或获取超级管理员用户...\n');
let superAdmin = await prisma.user.findFirst({
where: {
tenantId: superTenant.id,
username: 'admin',
},
});
if (!superAdmin) {
const hashedPassword = await bcrypt.hash('admin@super', 10);
superAdmin = await prisma.user.create({
data: {
tenantId: superTenant.id,
username: 'admin',
password: hashedPassword,
nickname: '超级管理员',
email: 'admin@super.com',
validState: 1,
},
});
console.log('✅ 超级管理员用户创建成功!');
console.log(` 用户名: ${superAdmin.username}`);
console.log(` 密码: admin@super`);
console.log(` 用户ID: ${superAdmin.id}\n`);
} else {
console.log('✅ 超级管理员用户已存在');
console.log(` 用户名: ${superAdmin.username}`);
console.log(` 用户ID: ${superAdmin.id}\n`);
}
// 创建或获取超级管理员角色
console.log('📋 步骤 3: 创建或获取超级管理员角色...\n');
let superAdminRole = await prisma.role.findFirst({
where: {
tenantId: superTenant.id,
code: 'super_admin',
},
});
if (!superAdminRole) {
superAdminRole = await prisma.role.create({
data: {
tenantId: superTenant.id,
name: '超级管理员',
code: 'super_admin',
description: '超级管理员角色,拥有所有权限',
validState: 1,
},
});
console.log('✅ 超级管理员角色创建成功!');
console.log(` 角色编码: ${superAdminRole.code}\n`);
} else {
console.log('✅ 超级管理员角色已存在');
console.log(` 角色编码: ${superAdminRole.code}\n`);
}
// 将超级管理员角色分配给用户
const existingUserRole = await prisma.userRole.findUnique({
where: {
userId_roleId: {
userId: superAdmin.id,
roleId: superAdminRole.id,
},
},
});
if (!existingUserRole) {
await prisma.userRole.create({
data: {
userId: superAdmin.id,
roleId: superAdminRole.id,
},
});
console.log('✅ 超级管理员角色已分配给用户');
} else {
console.log('✅ 超级管理员角色已分配给用户,跳过');
}
console.log('💡 提示: 权限初始化请使用 init:admin:permissions 脚本\n');
// 为超级租户分配所有菜单
console.log('📋 步骤 4: 为超级租户分配所有菜单...\n');
// 获取所有有效菜单
const allMenus = await prisma.menu.findMany({
where: {
validState: 1,
},
orderBy: [{ sort: 'asc' }, { id: 'asc' }],
});
if (allMenus.length === 0) {
console.log('⚠️ 警告: 数据库中没有任何菜单');
console.log(' 请先运行 pnpm init:menus 初始化菜单');
} else {
console.log(` 找到 ${allMenus.length} 个菜单\n`);
// 获取超级租户已分配的菜单
const existingTenantMenus = await prisma.tenantMenu.findMany({
where: {
tenantId: superTenant.id,
},
select: {
menuId: true,
},
});
const existingMenuIds = new Set(existingTenantMenus.map((tm) => tm.menuId));
// 为超级租户分配所有菜单
let addedCount = 0;
const menuNames: string[] = [];
for (const menu of allMenus) {
if (!existingMenuIds.has(menu.id)) {
await prisma.tenantMenu.create({
data: {
tenantId: superTenant.id,
menuId: menu.id,
},
});
addedCount++;
menuNames.push(menu.name);
}
}
if (addedCount > 0) {
console.log(`✅ 为超级租户添加了 ${addedCount} 个菜单:`);
menuNames.forEach((name) => {
console.log(`${name}`);
});
console.log(`\n✅ 超级租户现在拥有 ${allMenus.length} 个菜单\n`);
} else {
console.log(`✅ 超级租户已拥有所有菜单(${allMenus.length} 个)\n`);
}
}
// 创建租户管理菜单(如果不存在)
console.log('📋 步骤 5: 创建租户管理菜单(如果不存在)...\n');
// 查找系统管理菜单(父菜单)
const systemMenu = await prisma.menu.findFirst({
where: {
name: '系统管理',
parentId: null,
},
});
if (systemMenu) {
// 检查租户管理菜单是否已存在
const existingTenantMenu = await prisma.menu.findFirst({
where: {
name: '租户管理',
path: '/system/tenants',
},
});
let tenantMenu;
if (!existingTenantMenu) {
tenantMenu = await prisma.menu.create({
data: {
name: '租户管理',
path: '/system/tenants',
icon: 'TeamOutlined',
component: 'system/tenants/Index',
parentId: systemMenu.id,
permission: 'tenant:read',
sort: 7,
validState: 1,
},
});
console.log('✅ 租户管理菜单创建成功');
// 为超级租户分配租户管理菜单
await prisma.tenantMenu.create({
data: {
tenantId: superTenant.id,
menuId: tenantMenu.id,
},
});
console.log('✅ 租户管理菜单已分配给超级租户\n');
} else {
tenantMenu = existingTenantMenu;
console.log('✅ 租户管理菜单已存在');
// 检查是否已分配
const existingTenantMenuRelation = await prisma.tenantMenu.findFirst({
where: {
tenantId: superTenant.id,
menuId: tenantMenu.id,
},
});
if (!existingTenantMenuRelation) {
await prisma.tenantMenu.create({
data: {
tenantId: superTenant.id,
menuId: tenantMenu.id,
},
});
console.log('✅ 租户管理菜单已分配给超级租户\n');
} else {
console.log('✅ 租户管理菜单已分配给超级租户,跳过\n');
}
}
} else {
console.log('⚠️ 警告:未找到系统管理菜单,无法创建租户管理菜单\n');
}
// 验证菜单分配结果
const finalMenus = await prisma.tenantMenu.findMany({
where: {
tenantId: superTenant.id,
},
include: {
menu: true,
},
});
console.log('📊 初始化结果:');
console.log('========================================');
console.log('超级租户信息:');
console.log(` 租户编码: ${superTenant.code}`);
console.log(` 租户名称: ${superTenant.name}`);
console.log(` 访问链接: http://your-domain.com/?tenant=${superTenant.code}`);
console.log('========================================');
console.log('超级管理员登录信息:');
console.log(` 用户名: ${superAdmin.username}`);
console.log(` 密码: admin@super`);
console.log(` 租户编码: ${superTenant.code}`);
console.log('========================================');
console.log('菜单分配情况:');
console.log(` 已分配菜单数: ${finalMenus.length}`);
if (finalMenus.length > 0) {
const topLevelMenus = finalMenus.filter((tm) => !tm.menu.parentId);
console.log(` 顶级菜单数: ${topLevelMenus.length}`);
}
console.log('========================================');
console.log('\n💡 提示:');
console.log(' 权限初始化请使用: pnpm init:admin:permissions');
console.log(' 菜单初始化请使用: pnpm init:menus');
console.log('========================================');
}
main()
.then(() => {
console.log('\n🎉 初始化脚本执行完成!');
process.exit(0);
})
.catch((error) => {
console.error('\n💥 初始化脚本执行失败:', error);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});