Skip to Content
文档迁移和升级从其他系统迁移

从其他系统迁移

本文档介绍如何从其他权限系统迁移到 MTPC。

支持的迁移来源

MTPC 支持从以下系统迁移:

迁移步骤

1. 分析现有系统

在开始迁移之前,需要分析现有权限系统的结构:

// 分析现有系统的权限模型 const existingSystem = { resources: ['user', 'order', 'product'], actions: ['create', 'read', 'update', 'delete'], roles: ['admin', 'user', 'guest'], policies: [ { role: 'admin', resource: '*', action: '*' }, { role: 'user', resource: 'order', action: 'read' }, ], }

2. 映射到 MTPC 概念

将现有系统的概念映射到 MTPC:

现有系统MTPC说明
ResourceResource资源
ActionPermission权限
RoleRole角色
PolicyPolicy策略
UserSubject主体

3. 创建迁移脚本

创建迁移脚本将现有数据转换为 MTPC 格式:

import { createMTPC } from '@mtpc/core' import { createRBACPlugin } from '@mtpc/rbac' async function migrateFromCasbin() { // 1. 创建 MTPC 实例 const mtpc = createMTPC() const rbacPlugin = createRBACPlugin() mtpc.use(rbacPlugin) await mtpc.init() // 2. 迁移资源 for (const resource of existingSystem.resources) { const mtpcResource = defineResource({ name: resource, schema: z.object({ id: z.string() }), features: { creatable: true, readable: true, updatable: true, deletable: true, listable: true, }, }) mtpc.registry.register(mtpcResource) } // 3. 迁移角色 for (const role of existingSystem.roles) { await rbacPlugin.createRole(role, { permissions: existingSystem.policies .filter(p => p.role === role) .map(p => ({ resource: p.resource, action: p.action, })), }) } // 4. 迁移角色绑定 for (const binding of existingSystem.roleBindings) { await rbacPlugin.bindRole(binding.userId, binding.role) } console.log('Migration completed!') }

从 Casbin 迁移

Casbin 模型

Casbin 使用以下模型定义权限:

[request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

迁移脚本

import { enforcer } from './casbin-config' import { createMTPC } from '@mtpc/core' import { createRBACPlugin } from '@mtpc/rbac' async function migrateFromCasbin() { const mtpc = createMTPC() const rbacPlugin = createRBACPlugin() mtpc.use(rbacPlugin) await mtpc.init() // 获取所有策略 const policies = await enforcer.getPolicy() // 按角色分组 const rolePolicies = new Map<string, any[]>() for (const policy of policies) { const [role, resource, action] = policy if (!rolePolicies.has(role)) { rolePolicies.set(role, []) } rolePolicies.get(role)!.push({ resource, action }) } // 创建角色 for (const [role, permissions] of rolePolicies) { await rbacPlugin.createRole(role, { permissions }) } // 获取所有角色绑定 const roleBindings = await enforcer.getGroupingPolicy() // 创建角色绑定 for (const binding of roleBindings) { const [userId, role] = binding await rbacPlugin.bindRole(userId, role) } console.log('Casbin migration completed!') }

从 AccessControl 迁移

AccessControl 模型

AccessControl 使用以下格式定义权限:

const ac = new AccessControl(grants) const grants = { admin: { user: { 'create:any': ['*'], 'read:any': ['*'], 'update:any': ['*'], 'delete:any': ['*'], }, }, user: { order: { 'read:own': ['*'], }, }, }

迁移脚本

import { createMTPC } from '@mtpc/core' import { createRBACPlugin } from '@mtpc/rbac' async function migrateFromAccessControl() { const mtpc = createMTPC() const rbacPlugin = createRBACPlugin() mtpc.use(rbacPlugin) await mtpc.init() // 遍历所有角色 for (const [role, resources] of Object.entries(grants)) { const permissions = [] // 遍历所有资源 for (const [resource, actions] of Object.entries(resources)) { for (const [action, attributes] of Object.entries(actions)) { const [actionName, scope] = action.split(':') permissions.push({ resource, action: actionName, scope: scope === 'any' ? 'tenant' : 'own', }) } } // 创建角色 await rbacPlugin.createRole(role, { permissions }) } console.log('AccessControl migration completed!') }

从自定义系统迁移

分析现有系统

首先需要分析现有系统的数据结构:

// 示例:自定义权限系统 interface CustomPermission { userId: string resource: string action: string conditions?: Record<string, any> } interface CustomRole { id: string name: string permissions: CustomPermission[] }

创建迁移脚本

import { createMTPC } from '@mtpc/core' import { createRBACPlugin } from '@mtpc/rbac' async function migrateFromCustomSystem() { const mtpc = createMTPC() const rbacPlugin = createRBACPlugin() mtpc.use(rbacPlugin) await mtpc.init() // 1. 从现有系统获取角色 const customRoles = await getCustomRoles() // 2. 迁移角色 for (const customRole of customRoles) { const permissions = customRole.permissions.map(p => ({ resource: p.resource, action: p.action, scope: p.conditions?.own ? 'own' : 'tenant', })) await rbacPlugin.createRole(customRole.name, { permissions }) } // 3. 从现有系统获取角色绑定 const customBindings = await getCustomRoleBindings() // 4. 迁移角色绑定 for (const binding of customBindings) { await rbacPlugin.bindRole(binding.userId, binding.roleName) } console.log('Custom system migration completed!') }

验证迁移

验证脚本

创建验证脚本确保迁移正确:

async function validateMigration() { const mtpc = createMTPC() const rbacPlugin = createRBACPlugin() mtpc.use(rbacPlugin) await mtpc.init() // 1. 验证角色 const roles = await rbacPlugin.getRoles() console.log('Roles:', roles) // 2. 验证角色权限 for (const role of roles) { const permissions = await rbacPlugin.getRolePermissions(role.id) console.log(`Role ${role.name} permissions:`, permissions) } // 3. 验证角色绑定 const bindings = await rbacPlugin.getRoleBindings('user-id') console.log('Role bindings:', bindings) // 4. 验证权限检查 const ctx = createContext({ subject: { id: 'user-id', roles: ['user'] }, tenant: { id: 'tenant-id' }, }) const result = await mtpc.checkPermission(ctx, 'user', 'read') console.log('Permission check result:', result) }

回滚计划

如果迁移出现问题,需要能够回滚:

async function rollbackMigration() { const mtpc = createMTPC() const rbacPlugin = createRBACPlugin() mtpc.use(rbacPlugin) await mtpc.init() // 1. 删除所有角色绑定 const bindings = await rbacPlugin.getAllRoleBindings() for (const binding of bindings) { await rbacPlugin.unbindRole(binding.userId, binding.roleId) } // 2. 删除所有角色 const roles = await rbacPlugin.getRoles() for (const role of roles) { await rbacPlugin.deleteRole(role.id) } console.log('Rollback completed!') }

最佳实践

1. 分阶段迁移

建议分阶段进行迁移:

  1. 第一阶段:迁移基础资源和角色
  2. 第二阶段:迁移角色绑定
  3. 第三阶段:验证和测试
  4. 第四阶段:切换到 MTPC

2. 并行运行

在迁移期间,保持新旧系统并行运行:

async function checkPermissionWithFallback(ctx, resource, action) { // 首先尝试 MTPC try { const result = await mtpc.checkPermission(ctx, resource, action) return result } catch (error) { // 如果 MTPC 失败,使用旧系统 return oldSystem.checkPermission(ctx, resource, action) } }

3. 数据备份

在迁移前备份所有数据:

async function backupData() { const backup = { roles: await getCustomRoles(), bindings: await getCustomRoleBindings(), timestamp: new Date().toISOString(), } await fs.writeFile('backup.json', JSON.stringify(backup, null, 2)) console.log('Backup completed!') }

4. 监控和日志

在迁移期间启用详细日志:

const mtpc = createMTPC({ logging: { level: 'debug', file: 'migration.log', }, })

继续学习: 版本升级指南

Last updated on