library-picturebook-activity/backend/scripts/cleanup-tenant-permissions.ts
aid 418aa57ea8 Day4: 超管端设计优化 + UGC绘本创作社区P0实现
一、超管端设计优化
- 文档管理SOP体系建立,docs目录重组
- 统一用户管理:跨租户全局视角,合并用户管理+公众用户
- 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作)
- 菜单精简:移除评委管理/评审规则/通知管理
- Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一

二、UGC绘本创作社区P0
- 数据库:10张新表(user_works/user_work_pages/work_tags等)
- 子女账号独立化:Child升级为独立User,家长切换+独立登录
- 用户作品库:CRUD+发布审核,8个API
- AI创作流程:提交→生成→保存到作品库,4个API
- 作品广场:首页改造为推荐流,标签+搜索+排序
- 内容审核(超管端):作品审核+作品管理+标签管理
- 活动联动:WorkSelector作品选择器
- 布局改造:底部5Tab(发现/创作/活动/作品库/我的)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:20:25 +08:00

128 lines
3.9 KiB
TypeScript

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import * as dotenv from 'dotenv';
import * as path from 'path';
const nodeEnv = process.env.NODE_ENV || 'development';
const envFile = `.env.${nodeEnv}`;
const backendDir = path.resolve(__dirname, '..');
const envPath = path.resolve(backendDir, envFile);
dotenv.config({ path: envPath });
if (!process.env.DATABASE_URL) {
dotenv.config({ path: path.resolve(backendDir, '.env') });
}
if (!process.env.DATABASE_URL) {
console.error('DATABASE_URL not found');
process.exit(1);
}
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// 超级管理员专属权限(普通租户不应该有这些权限)
const superAdminOnlyPermissions = [
'tenant:create',
'tenant:update',
'tenant:delete',
];
async function cleanupTenantPermissions() {
try {
console.log('🚀 开始清理普通租户的超级管理员权限...\n');
// 1. 获取所有非超级租户
const normalTenants = await prisma.tenant.findMany({
where: {
isSuper: { not: 1 },
validState: 1,
},
});
console.log(`找到 ${normalTenants.length} 个普通租户\n`);
for (const tenant of normalTenants) {
console.log(`处理租户: ${tenant.name} (${tenant.code})`);
// 2. 找到该租户下的超级管理员专属权限
const permissionsToRemove = await prisma.permission.findMany({
where: {
tenantId: tenant.id,
code: { in: superAdminOnlyPermissions },
},
});
if (permissionsToRemove.length === 0) {
console.log(` ✓ 没有需要清理的权限\n`);
continue;
}
const permissionIds = permissionsToRemove.map((p) => p.id);
console.log(` 找到 ${permissionsToRemove.length} 个需要清理的权限: ${permissionsToRemove.map((p) => p.code).join(', ')}`);
// 3. 删除角色-权限关联
const deletedRolePermissions = await prisma.rolePermission.deleteMany({
where: {
permissionId: { in: permissionIds },
},
});
console.log(` 删除了 ${deletedRolePermissions.count} 条角色-权限关联`);
// 4. 删除权限记录
const deletedPermissions = await prisma.permission.deleteMany({
where: {
id: { in: permissionIds },
},
});
console.log(` 删除了 ${deletedPermissions.count} 条权限记录\n`);
}
// 5. 更新租户管理菜单权限
console.log('更新租户管理菜单权限...');
const tenantMenu = await prisma.menu.findFirst({
where: {
name: '租户管理',
path: '/system/tenants',
},
});
if (tenantMenu) {
if (tenantMenu.permission !== 'tenant:update') {
await prisma.menu.update({
where: { id: tenantMenu.id },
data: { permission: 'tenant:update' },
});
console.log(`✅ 菜单权限已更新为 tenant:update (原: ${tenantMenu.permission})`);
} else {
console.log('✅ 菜单权限已经是 tenant:update');
}
} else {
console.log('⚠️ 未找到租户管理菜单');
}
console.log('\n✅ 清理完成!');
console.log('\n说明:');
console.log(' - 普通租户现在只有 tenant:read 权限(用于读取租户列表)');
console.log(' - 租户管理菜单需要 tenant:update 权限才能看到');
console.log(' - 只有超级租户才有 tenant:create/update/delete 权限');
} catch (error) {
console.error('❌ 清理失败:', error);
throw error;
} finally {
await prisma.$disconnect();
}
}
cleanupTenantPermissions()
.then(() => {
console.log('\n🎉 脚本执行完成!');
process.exit(0);
})
.catch((error) => {
console.error('\n💥 脚本执行失败:', error);
process.exit(1);
});