title: mtpc/core 核心包 description: 详细介绍 MTPC 核心包的所有功能、API 和使用方法
MTPC Core 使用指南
目录
1. 概述
1.1 什么是 MTPC Core
MTPC (Multi-Tenant Permission Core) 是一个业务无关、可嵌入、可组合的多租户权限内核。它不是一个可直接部署的系统,而是作为依赖被真实业务系统(SaaS、内部后台、B端系统等)引入。
1.2 核心特性
- 业务无关: 不绑定任何特定业务逻辑,可适用于任何需要权限控制的场景
- 可嵌入: 作为 npm 包引入,不依赖外部服务
- 可组合: 通过插件系统和钩子系统实现灵活扩展
- 编译期优先: 在编译期和启动期完成大部分配置,减少运行时开销
- 默认拒绝: 遵循安全最佳实践,默认拒绝所有访问
- 多租户支持: 内置多租户隔离能力
1.3 架构设计原则
- Schema 驱动: 使用 Zod Schema 定义资源结构作为单一事实源
- 声明式配置: 通过声明式 API 定义资源和策略
- 可扩展性: 通过插件系统扩展功能
- 类型安全: 完整的 TypeScript 类型支持
2. 快速开始
2.1 安装依赖
# 使用 pnpm 安装
pnpm add @mtpc/core
# 安装可选依赖(用于 Schema 定义)
pnpm add zod2.2 创建 MTPC 实例
import { createMTPC } from '@mtpc/core';
// 创建 MTPC 实例
const mtpc = createMTPC({
// 配置选项(可选)
defaultPermissionResolver: async (tenantId: string, subjectId: string) => {
// 实现自定义权限解析逻辑
// 返回权限代码集合
return new Set(['user:read', 'user:create']);
}
});2.3 定义和注册资源
import { defineResource } from '@mtpc/core';
import { z } from 'zod';
// 定义用户资源
const userResource = defineResource({
name: 'user',
schema: z.object({
id: z.string(),
name: z.string().min(2),
email: z.string().email(),
role: z.enum(['admin', 'user', 'guest'])
}),
features: {
create: true,
read: true,
update: true,
delete: true,
// 自定义特性
export: true
},
// 自定义权限(除了 CRUD 自动生成的权限外)
permissions: [
{
action: 'impersonate',
description: '模拟用户',
metadata: { requiresAdmin: true }
}
],
metadata: {
displayName: '用户',
group: '核心模块',
icon: 'user'
}
});
// 注册资源到 MTPC 实例
mtpc.registerResource(userResource);2.4 定义和注册策略
// 注册策略
mtpc.registerPolicy({
id: 'admin-only-delete',
name: '仅管理员可删除用户',
rules: [{
permissions: ['user:delete'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
}]
}],
priority: 'high',
enabled: true
});2.5 初始化 MTPC
// 初始化 MTPC 实例
await mtpc.init();
// 检查初始化状态
console.log('MTPC 初始化状态:', mtpc.isInitialized());
// 获取系统摘要
console.log('系统摘要:', mtpc.getSummary());2.6 权限检查
// 创建上下文
const context = mtpc.createContext(
{ id: 'tenant-123' }, // 租户上下文
{
id: 'user-123',
type: 'user',
attributes: { role: 'user' }
} // 主体上下文
);
// 检查单个权限
const result = await mtpc.checkPermission({
...context,
resource: 'user',
action: 'read'
});
console.log('权限检查结果:', result);
// 输出: { allowed: true, permission: 'user:read', reason: 'Permission granted', evaluationTime: 2 }
// 检查权限并在无权限时抛出异常
try {
await mtpc.requirePermission({
...context,
resource: 'user',
action: 'delete'
});
console.log('有权限执行删除操作');
} catch (error) {
console.log('无权限执行删除操作:', error.message);
}3. 核心概念
3.1 Resource(资源)
资源是系统中需要进行权限控制的实体,例如用户、订单、文章等。资源通过 defineResource 函数定义,包含:
- Schema: 使用 Zod 定义的数据结构
- Features: 支持的操作特性(CRUD + 自定义)
- Permissions: 资源关联的权限列表
- Hooks: 资源级别的钩子函数
- Metadata: 资源的元数据信息
3.2 Permission(权限)
权限是对资源执行特定操作的许可。权限代码格式为 resource:action,例如:
user:read- 读取用户user:create- 创建用户user:update- 更新用户user:delete- 删除用户user:impersonate- 模拟用户(自定义权限)
3.3 Policy(策略)
策略定义了权限的授予规则,包含:
- Rules: 规则列表,每个规则包含权限、效果和条件
- Priority: 策略优先级(critical > high > medium > low)
- Enabled: 是否启用策略
- TenantId: 租户 ID(可选,用于租户隔离)
3.4 Context(上下文)
上下文包含权限检查所需的信息:
- TenantContext: 租户上下文,包含租户 ID、状态和元数据
- SubjectContext: 主体上下文,包含主体 ID、类型、属性和权限集合
3.5 Plugin(插件)
插件是扩展 MTPC 功能的机制,通过实现 PluginDefinition 接口来定义插件:
- Register: 注册阶段,用于注册资源、策略等
- Install: 安装阶段,用于设置全局钩子等
- Init: 初始化阶段,用于执行初始化逻辑
- Destroy: 销毁阶段,用于清理资源
3.6 Hook(钩子)
钩子是在特定事件发生时执行的回调函数,分为:
- Resource Hooks: 资源级别的钩子(beforeCreate, afterCreate, beforeRead, afterRead 等)
- Global Hooks: 全局级别的钩子(beforeAny, afterAny, onError)
4. 资源定义与管理
4.1 基本资源定义
import { defineResource } from '@mtpc/core';
import { z } from 'zod';
const userResource = defineResource({
name: 'user',
schema: z.object({
id: z.string(),
name: z.string().min(2),
email: z.string().email(),
role: z.enum(['admin', 'user', 'guest'])
}),
features: {
create: true,
read: true,
update: true,
delete: true
},
metadata: {
displayName: '用户',
group: '核心模块',
icon: 'user'
}
});4.2 使用 ResourceBuilder
import { ResourceBuilder } from '@mtpc/core';
import { z } from 'zod';
const userResource = new ResourceBuilder('user')
.setSchema(z.object({
id: z.string(),
name: z.string(),
email: z.string().email()
}))
.setFeatures({
create: true,
read: true,
update: true,
delete: true
})
.setMetadata({
displayName: '用户',
group: '核心模块'
})
.addPermission({
action: 'impersonate',
description: '模拟用户'
})
.addHook('beforeCreate', async (context, data) => {
// 验证逻辑
return data;
})
.build();4.3 资源特性配置
const productResource = defineResource({
name: 'product',
schema: z.object({
id: z.string(),
name: z.string(),
price: z.number(),
stock: z.number()
}),
features: {
// 基础 CRUD 特性
create: true,
read: true,
update: true,
delete: false, // 禁用删除
// 高级特性
list: true, // 列表查询
search: true, // 搜索
export: true, // 导出
import: false, // 禁用导入
archive: true, // 归档
restore: true // 恢复
}
});4.4 资源钩子
const orderResource = defineResource({
name: 'order',
schema: z.object({
id: z.string(),
amount: z.number(),
status: z.enum(['pending', 'paid', 'shipped', 'delivered'])
}),
features: {
create: true,
read: true,
update: true,
delete: true
},
hooks: {
// 创建前钩子
beforeCreate: async (context, input) => {
// 验证订单金额
if (input.amount <= 0) {
throw new Error('订单金额必须大于0');
}
// 可以修改输入数据
return { ...input, createdAt: new Date() };
},
// 创建后钩子
afterCreate: async (context, input, created) => {
// 发送通知
console.log(`订单 ${created.id} 创建成功`);
// 可以执行异步操作
await sendOrderConfirmationEmail(created);
},
// 更新前钩子
beforeUpdate: async (context, id, data) => {
// 验证状态转换
const order = await getOrderById(id);
if (order.status === 'delivered' && data.status) {
throw new Error('已送达的订单不能修改状态');
}
return data;
},
// 更新后钩子
afterUpdate: async (context, id, data, updated) => {
// 记录变更日志
await logOrderChange(id, data, updated);
},
// 删除前钩子
beforeDelete: async (context, id) => {
// 检查是否可以删除
const order = await getOrderById(id);
if (order.status === 'paid') {
throw new Error('已支付的订单不能删除');
}
return id;
},
// 删除后钩子
afterDelete: async (context, id, deleted) => {
// 清理关联数据
await cleanupOrderItems(id);
},
// 列表查询前钩子
beforeList: async (context, options) => {
// 添加默认过滤条件
return {
...options,
filters: [
...(options.filters || []),
{ field: 'deleted', operator: 'eq', value: false }
]
};
},
// 列表查询后钩子
afterList: async (context, options, results) => {
// 添加计算字段
return results.map(order => ({
...order,
totalAmount: order.amount + order.tax
}));
},
// 过滤查询钩子
filterQuery: async (context, filters) => {
// 添加租户隔离过滤
return [
...filters,
{ field: 'tenantId', operator: 'eq', value: context.tenant.id }
];
}
}
});4.5 资源关系
const orderResource = defineResource({
name: 'order',
schema: z.object({
id: z.string(),
userId: z.string(),
productId: z.string(),
amount: z.number()
}),
features: {
create: true,
read: true,
update: true,
delete: true
},
relations: {
// 一对一关系
user: {
type: 'one',
resource: 'user',
foreignKey: 'userId'
},
// 一对多关系
items: {
type: 'many',
resource: 'orderItem',
foreignKey: 'orderId'
}
}
});4.6 批量注册资源
// 批量注册资源
mtpc.registerResources([
userResource,
productResource,
orderResource
]);
// 或者使用数组展开
mtpc.registerResources(...[
userResource,
productResource,
orderResource
]);5. 权限系统
5.1 权限生成
MTPC 会根据资源的 features 自动生成权限:
const userResource = defineResource({
name: 'user',
features: {
create: true,
read: true,
update: true,
delete: true,
export: true
}
});
// 自动生成的权限:
// - user:create
// - user:read
// - user:update
// - user:delete
// - user:export
// - user:list (如果 list 特性启用)
// - user:search (如果 search 特性启用)5.2 自定义权限
const userResource = defineResource({
name: 'user',
features: {
create: true,
read: true,
update: true,
delete: true
},
permissions: [
{
action: 'impersonate',
description: '模拟用户',
metadata: { requiresAdmin: true }
},
{
action: 'resetPassword',
description: '重置用户密码',
metadata: { requiresAdmin: true }
},
{
action: 'changeRole',
description: '更改用户角色',
metadata: { requiresManager: true }
}
]
});5.3 权限检查
// 创建上下文
const context = mtpc.createContext(
{ id: 'tenant-123' },
{ id: 'user-123', type: 'user' }
);
// 检查单个权限
const result = await mtpc.checkPermission({
...context,
resource: 'user',
action: 'read'
});
console.log(result);
// {
// allowed: true,
// permission: 'user:read',
// reason: 'Permission granted',
// evaluationTime: 2
// }
// 检查权限并在无权限时抛出异常
try {
await mtpc.requirePermission({
...context,
resource: 'user',
action: 'delete'
});
console.log('有权限执行删除操作');
} catch (error) {
console.log('无权限执行删除操作:', error.message);
}5.4 批量权限检查
// 并行检查多个权限
const checkResults = await Promise.all([
mtpc.checkPermission({ ...context, resource: 'user', action: 'read' }),
mtpc.checkPermission({ ...context, resource: 'user', action: 'update' }),
mtpc.checkPermission({ ...context, resource: 'user', action: 'delete' }),
mtpc.checkPermission({ ...context, resource: 'user', action: 'export' })
]);
console.log('批量检查结果:', checkResults);
console.log('是否所有权限都允许:', checkResults.every(r => r.allowed));
console.log('是否有任意权限允许:', checkResults.some(r => r.allowed));
// 使用循环批量检查
const permissions = [
{ resource: 'user', action: 'read' },
{ resource: 'user', action: 'update' },
{ resource: 'user', action: 'delete' }
];
const results = new Map();
for (const perm of permissions) {
const result = await mtpc.checkPermission({ ...context, ...perm });
results.set(`${perm.resource}:${perm.action}`, result);
}5.5 通配符权限
// 通配符权限表示所有权限
const adminPermissions = new Set(['*']);
// 通配符资源权限表示资源的所有操作
const userAdminPermissions = new Set(['user:*']);
// 通配符操作权限表示所有资源的指定操作
const readAllPermissions = new Set(['*:read']);5.6 权限缓存
PermissionChecker 内置了权限缓存机制,可以显著提高性能:
import { PermissionChecker } from '@mtpc/core';
const checker = new PermissionChecker({
cacheSize: 1000, // 缓存大小
cacheTtl: 60000, // 缓存生存时间(毫秒)
permissionResolver: async (tenantId, subjectId) => {
// 从数据库或缓存获取权限
return await getPermissions(tenantId, subjectId);
}
});
// 清除缓存
checker.clearCache();
// 清除特定主体的缓存
checker.clearSubjectCache(tenantId, subjectId);6. 策略引擎
6.1 策略定义
mtpc.registerPolicy({
id: 'admin-full-access',
name: '管理员完全访问',
description: '管理员拥有所有资源的完全访问权限',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
}]
}],
priority: 'critical',
enabled: true
});6.2 使用 PolicyBuilder
import { PolicyBuilder } from '@mtpc/core';
const policy = new PolicyBuilder('admin-full-access')
.setName('管理员完全访问')
.setDescription('管理员拥有所有资源的完全访问权限')
.setPriority('critical')
.setEnabled(true)
.addRule({
permissions: ['*'],
effect: 'allow'
})
.withCondition({
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
})
.build();
mtpc.registerPolicy(policy);6.3 策略条件类型
6.3.1 字段条件
mtpc.registerPolicy({
id: 'field-condition-policy',
name: '基于字段的策略',
rules: [{
permissions: ['order:approve'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'manager'
}]
}]
});
// 支持的操作符:
// - eq: 等于
// - neq: 不等于
// - in: 在列表中
// - notIn: 不在列表中
// - contains: 包含(用于数组字段)
// - gt: 大于
// - gte: 大于等于
// - lt: 小于
// - lte: 小于等于6.3.2 时间条件
mtpc.registerPolicy({
id: 'business-hours-policy',
name: '工作时间访问策略',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'time',
operator: 'between',
value: { start: '09:00', end: '18:00' }
}]
}]
});
// 支持的操作符:
// - between: 在时间范围内
// - notBetween: 不在时间范围内
// - before: 在指定时间之前
// - after: 在指定时间之后6.3.3 IP 条件
mtpc.registerPolicy({
id: 'ip-whitelist-policy',
name: 'IP 白名单策略',
rules: [{
permissions: ['admin:*'],
effect: 'allow',
conditions: [{
type: 'ip',
operator: 'in',
value: ['192.168.1.0/24', '10.0.0.0/8']
}]
}]
});
// 支持的操作符:
// - in: 在 IP 列表中
// - notIn: 不在 IP 列表中6.3.4 自定义条件
// 添加自定义条件处理器
mtpc.policyEngine.addConditionHandler('custom', async (condition, context) => {
// 实现自定义条件逻辑
const { field, operator, value } = condition;
// 获取字段值
const fieldValue = getFieldValue(context, field);
// 执行自定义比较
return customCompare(fieldValue, operator, value);
});
// 使用自定义条件
mtpc.registerPolicy({
id: 'custom-condition-policy',
name: '自定义条件策略',
rules: [{
permissions: ['resource:action'],
effect: 'allow',
conditions: [{
type: 'custom',
field: 'subject.attributes.customField',
operator: 'customOperator',
value: 'customValue'
}]
}]
});6.4 多条件组合
mtpc.registerPolicy({
id: 'multi-condition-policy',
name: '多条件策略',
rules: [{
permissions: ['order:approve'],
effect: 'allow',
conditions: [
{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'manager'
},
{
type: 'field',
field: 'subject.attributes.department',
operator: 'in',
value: ['finance', 'sales']
},
{
type: 'time',
operator: 'between',
value: { start: '09:00', end: '18:00' }
}
]
}]
});6.5 策略优先级
// 策略优先级:critical > high > medium > low
mtpc.registerPolicy({
id: 'super-admin-policy',
name: '超级管理员策略',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.id',
operator: 'eq',
value: 'super-admin'
}]
}],
priority: 'critical', // 最高优先级
enabled: true
});
mtpc.registerPolicy({
id: 'admin-policy',
name: '管理员策略',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
}]
}],
priority: 'high',
enabled: true
});
mtpc.registerPolicy({
id: 'user-policy',
name: '用户策略',
rules: [{
permissions: ['user:read', 'article:read'],
effect: 'allow'
}],
priority: 'medium',
enabled: true
});6.6 批量注册策略
// 批量注册策略
mtpc.registerPolicies([
{
id: 'admin-full-access',
name: '管理员完全访问',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
}]
}],
priority: 'critical',
enabled: true
},
{
id: 'user-read-only',
name: '用户只读',
rules: [{
permissions: ['user:read', 'article:read'],
effect: 'allow'
}],
priority: 'medium',
enabled: true
}
]);7. 注册表系统
7.1 UnifiedRegistry(统一注册表)
UnifiedRegistry 是一站式管理所有注册表的接口,包含 ResourceRegistry、PermissionRegistry 和 PolicyRegistry。
import { UnifiedRegistry } from '@mtpc/core';
const registry = new UnifiedRegistry();
// 注册资源
registry.registerResource({
name: 'user',
displayName: '用户',
description: '用户资源管理',
group: 'core',
visible: true,
permissions: [
{
code: 'user:read',
displayName: '查看用户',
description: '允许查看用户信息',
defaultGrant: true
},
{
code: 'user:create',
displayName: '创建用户',
description: '允许创建新用户',
defaultGrant: false
}
]
});
// 注册策略
registry.registerPolicy({
id: 'admin-full-access',
name: '管理员完全访问',
description: '管理员拥有所有资源的完全访问权限',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
}]
}],
priority: 'critical',
enabled: true
});
// 访问子注册表
const userResource = registry.resources.get('user');
const userReadPermission = registry.permissions.get('user:read');
const adminPolicy = registry.policies.get('admin-full-access');
// 导出元数据
const metadata = registry.exportMetadata();
console.log('Resources:', metadata.resources);
console.log('Permissions:', metadata.permissions);
console.log('Policies:', metadata.policies);
// 冻结所有注册表
registry.freeze();7.2 ResourceRegistry(资源注册表)
import { ResourceRegistry } from '@mtpc/core';
const resourceRegistry = new ResourceRegistry();
// 注册资源
resourceRegistry.register({
name: 'user',
displayName: '用户',
description: '用户资源管理',
group: 'core',
visible: true,
permissions: [
{
code: 'user:read',
displayName: '查看用户',
description: '允许查看用户信息',
defaultGrant: true
},
{
code: 'user:create',
displayName: '创建用户',
description: '允许创建新用户',
defaultGrant: false
}
]
});
// 查询资源
const userResource = resourceRegistry.get('user');
console.log(userResource.displayName);
const allResources = resourceRegistry.getAll();
console.log(allResources.length);
const coreResources = resourceRegistry.getByGroup('core');
console.log(coreResources);
const hasUser = resourceRegistry.has('user');
console.log(hasUser);
const names = resourceRegistry.getNames();
console.log(names);
// 冻结注册表
resourceRegistry.freeze();7.3 PermissionRegistry(权限注册表)
import { PermissionRegistry } from '@mtpc/core';
const permissionRegistry = new PermissionRegistry();
// 注册单个权限
permissionRegistry.register('user', {
code: 'user:read',
displayName: '查看用户',
description: '允许查看用户信息',
defaultGrant: true
});
// 批量注册权限
permissionRegistry.registerMany('user', [
{
code: 'user:read',
displayName: '查看用户',
description: '允许查看用户信息',
defaultGrant: true
},
{
code: 'user:create',
displayName: '创建用户',
description: '允许创建新用户',
defaultGrant: false
},
{
code: 'user:update',
displayName: '更新用户',
description: '允许更新用户信息',
defaultGrant: false
},
{
code: 'user:delete',
displayName: '删除用户',
description: '允许删除用户',
defaultGrant: false
}
]);
// 查询权限
const userReadPermission = permissionRegistry.get('user:read');
console.log(userReadPermission.displayName);
const allPermissions = permissionRegistry.getAll();
console.log(allPermissions.length);
const userPermissions = permissionRegistry.getByResource('user');
console.log(userPermissions);
const hasPermission = permissionRegistry.has('user:read');
console.log(hasPermission);
const codes = permissionRegistry.getCodes();
console.log(codes);7.4 PolicyRegistry(策略注册表)
import { PolicyRegistry } from '@mtpc/core';
const policyRegistry = new PolicyRegistry();
// 注册策略
policyRegistry.register({
id: 'admin-full-access',
name: '管理员完全访问',
description: '管理员拥有所有资源的完全访问权限',
rules: [{
permissions: ['*'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.role',
operator: 'eq',
value: 'admin'
}]
}],
priority: 'critical',
enabled: true
});
// 查询策略
const adminPolicy = policyRegistry.get('admin-full-access');
console.log(adminPolicy.name);
const allPolicies = policyRegistry.getAll();
console.log(allPolicies.length);
const enabledPolicies = policyRegistry.getEnabledPolicies();
console.log(enabledPolicies);
const hasPolicy = policyRegistry.has('admin-full-access');
console.log(hasPolicy);7.5 全局注册表
import { getGlobalRegistry } from '@mtpc/core';
// 获取全局注册表实例
const globalRegistry = getGlobalRegistry();
// 使用全局注册表
globalRegistry.registerResource({
name: 'product',
displayName: '产品',
description: '产品资源管理',
group: 'business',
visible: true,
permissions: [
{
code: 'product:read',
displayName: '查看产品',
description: '允许查看产品信息',
defaultGrant: true
}
]
});
const productResource = globalRegistry.resources.get('product');
console.log(productResource.displayName);8. 插件系统
8.1 插件定义
import { PluginDefinition } from '@mtpc/core';
const auditPlugin: PluginDefinition = {
name: 'audit-log',
version: '1.0.0',
// 注册阶段:注册资源、策略等
register(ctx) {
console.log('注册审计插件');
},
// 安装阶段:设置全局钩子等
install(ctx) {
ctx.registerGlobalHooks({
afterAny: async (context, operation, resource, result) => {
console.log(`[审计日志] ${context.subject.id} 执行 ${operation} 于 ${resource},结果:`, result);
},
beforeAny: async (context, operation, resource) => {
console.log(`[审计日志] ${context.subject.id} 即将执行 ${operation} 于 ${resource}`);
return { proceed: true };
},
onError: async (context, operation, resource, error) => {
console.error(`[审计日志] ${context.subject.id} 执行 ${operation} 于 ${resource} 时出错:`, error.message);
}
});
},
// 初始化阶段:执行初始化逻辑
async init(ctx) {
console.log('初始化审计插件');
},
// 销毁阶段:清理资源
async destroy(ctx) {
console.log('销毁审计插件');
}
};8.2 插件依赖
const pluginA: PluginDefinition = {
name: 'plugin-a',
version: '1.0.0',
register(ctx) {
console.log('注册插件 A');
}
};
const pluginB: PluginDefinition = {
name: 'plugin-b',
version: '1.0.0',
dependencies: ['plugin-a'], // 依赖插件 A
register(ctx) {
console.log('注册插件 B(依赖插件 A)');
}
};
// 注册插件(会自动处理依赖关系)
mtpc.use(pluginA);
mtpc.use(pluginB);8.3 使用插件
// 注册插件
mtpc.use(auditPlugin);
// 初始化 MTPC
await mtpc.init();
// 获取已安装的插件实例
const audit = mtpc.getPlugin('audit-log');
if (audit) {
console.log('审计插件已安装:', audit.installed);
console.log('插件状态:', audit.state);
}8.4 插件状态管理
// 获取所有已注册的插件
const allPlugins = mtpc.getPlugins();
console.log('所有插件:', allPlugins);
// 检查插件是否已安装
const isInstalled = mtpc.hasPlugin('audit-log');
console.log('审计插件已安装:', isInstalled);
// 获取插件实例
const plugin = mtpc.getPlugin('audit-log');
if (plugin) {
console.log('插件名称:', plugin.definition.name);
console.log('插件版本:', plugin.definition.version);
console.log('是否已安装:', plugin.installed);
console.log('插件状态:', plugin.state);
}9. 钩子系统
9.1 全局钩子
import { GlobalHooksManager, createGlobalHooksManager } from '@mtpc/core';
// 创建全局钩子管理器
const globalHooks = createGlobalHooksManager();
// 添加操作前钩子
globalHooks.addBeforeAny(async (context, operation, resourceName) => {
console.log(`操作 ${operation} 即将在资源 ${resourceName} 上执行`);
// 检查全局限制
const isAllowed = await checkGlobalLimits(context);
if (!isAllowed) {
return { proceed: false, error: '超出全局限制' };
}
return { proceed: true };
});
// 添加操作后钩子
globalHooks.addAfterAny(async (context, operation, resourceName, result) => {
console.log(`操作 ${operation} 在资源 ${resourceName} 上执行完成`);
await auditLogger.log({
userId: context.subject.id,
operation,
resource: resourceName,
result,
timestamp: new Date()
});
});
// 添加错误钩子
globalHooks.addOnError(async (context, operation, resourceName, error) => {
console.error(`操作 ${operation} 在资源 ${resourceName} 上执行失败:`, error.message);
await alertService.send({
level: 'error',
message: `操作失败: ${operation}`,
userId: context.subject.id,
error: error.message
});
});
// 执行钩子
await globalHooks.executeBeforeAny(context, 'create', 'user');
await globalHooks.executeAfterAny(context, 'create', 'user', result);
await globalHooks.executeOnError(context, 'create', 'user', error);
// 清除所有钩子
globalHooks.clear();
// 获取钩子集合
const hooks = globalHooks.getHooks();9.2 资源钩子
import { HookExecutor, createHookExecutor } from '@mtpc/core';
// 创建钩子执行器
const executor = createHookExecutor({
beforeCreate: [validateEmail, setDefaultRole],
afterCreate: [sendWelcomeEmail, logActivity],
beforeUpdate: [validateUpdate],
afterUpdate: [logUpdate]
});
// 执行创建前钩子
const result = await executor.executeBeforeCreate(context, userData);
if (result.proceed) {
// 继续执行创建操作
const created = await createUser(result.data);
// 执行创建后钩子
await executor.executeAfterCreate(context, userData, created);
}
// 执行更新前钩子
const updateResult = await executor.executeBeforeUpdate(context, userId, updateData);
if (updateResult.proceed) {
const updated = await updateUser(userId, updateResult.data);
await executor.executeAfterUpdate(context, userId, updateData, updated);
}9.3 钩子执行顺序
// 钩子按添加顺序执行
const executor = createHookExecutor({
beforeCreate: [
async (context, data) => {
console.log('第一个钩子');
return data;
},
async (context, data) => {
console.log('第二个钩子');
return data;
},
async (context, data) => {
console.log('第三个钩子');
return data;
}
]
});
// 执行顺序:第一个 -> 第二个 -> 第三个
await executor.executeBeforeCreate(context, userData);9.4 钩子返回值处理
// before 钩子可以返回 { proceed: false } 阻止操作
const executor = createHookExecutor({
beforeCreate: [
async (context, data) => {
if (data.email === 'blocked@example.com') {
return { proceed: false, error: '该邮箱已被阻止' };
}
return { proceed: true, data };
}
]
});
const result = await executor.executeBeforeCreate(context, userData);
if (!result.proceed) {
console.log('操作被阻止:', result.error);
}9.5 钩子数据修改
// 钩子可以修改数据
const executor = createHookExecutor({
beforeCreate: [
async (context, data) => {
// 添加默认值
return {
...data,
createdAt: new Date(),
createdBy: context.subject.id
};
},
async (context, data) => {
// 验证并修改数据
if (!data.name) {
data.name = 'Anonymous';
}
return data;
}
]
});10. 多租户支持
10.1 租户上下文
import {
createTenantContext,
validateTenantContext,
isTenantActive,
createSystemTenant,
DEFAULT_TENANT,
TenantContextHolder
} from '@mtpc/core';
// 创建租户上下文
const tenant = createTenantContext('tenant-001');
console.log(tenant);
// { id: 'tenant-001', status: 'active' }
// 创建带配置的租户
const tenantWithConfig = createTenantContext('tenant-002', {
status: 'suspended',
metadata: { plan: 'enterprise', region: 'us-east' }
});
// 验证租户上下文
try {
validateTenantContext(tenant);
console.log('租户验证通过');
} catch (error) {
console.error('租户验证失败:', error.message);
}
// 检查租户是否活跃
if (isTenantActive(tenant)) {
console.log('租户处于活跃状态');
}
// 创建系统租户
const systemTenant = createSystemTenant();
console.log(systemTenant);
// { id: 'system', status: 'active', metadata: { isSystem: true } }
// 使用默认租户
const defaultTenant = DEFAULT_TENANT;
console.log(defaultTenant);
// { id: 'default', status: 'active' }10.2 租户上下文持有者
// 设置租户上下文
TenantContextHolder.set(tenant);
// 获取租户上下文
const currentTenant = TenantContextHolder.get();
console.log(currentTenant?.id);
// 安全获取租户上下文(不存在时抛出异常)
const tenant = TenantContextHolder.getOrThrow();
// 清除租户上下文
TenantContextHolder.clear();
// 在租户上下文中执行函数(同步)
const result = TenantContextHolder.run(tenant, () => {
console.log('在租户上下文中执行');
return 'result';
});
// 在租户上下文中执行函数(异步)
const asyncResult = await TenantContextHolder.runAsync(tenant, async () => {
console.log('在租户上下文中执行异步操作');
return await fetchData();
});10.3 租户管理器
import {
TenantManager,
InMemoryTenantStore,
createTenantManager
} from '@mtpc/core';
// 创建租户管理器
const manager = createTenantManager({ cacheTtl: 60000 });
// 或使用自定义存储
const customStore = new InMemoryTenantStore();
const manager = new TenantManager(customStore, { cacheTtl: 60000 });
// 创建租户
const tenant = await manager.createTenant({
id: 'tenant-001',
name: 'ACME Corp',
status: 'active',
metadata: {
plan: 'enterprise',
maxUsers: 1000
}
});
// 获取租户
const retrieved = await manager.getTenant('tenant-001');
console.log(retrieved);
// 获取租户(不存在时抛出异常)
const tenantOrThrow = await manager.getTenantOrThrow('tenant-001');
// 创建租户上下文
const context = await manager.createContext('tenant-001');
// 验证并获取租户上下文
const validContext = await manager.validateAndGetContext('tenant-001');
// 获取所有租户
const allTenants = await manager.listTenants();
// 更新租户
const updated = await manager.updateTenant('tenant-001', {
status: 'suspended'
});
// 删除租户
await manager.deleteTenant('tenant-001');
// 失效缓存
manager.invalidateCache('tenant-001');
// 清空所有缓存
manager.clearCache();10.4 租户解析器
10.4.1 请求头解析器
import { createHeaderResolver } from '@mtpc/core';
// 使用默认请求头 'x-tenant-id'
const resolver = createHeaderResolver();
const tenant = await resolver({ headers: { 'x-tenant-id': 'tenant-001' } });
// 使用自定义请求头
const customResolver = createHeaderResolver('x-company-id');
const tenant = await customResolver({ headers: { 'x-company-id': 'company-abc' } });10.4.2 子域名解析器
import { createSubdomainResolver } from '@mtpc/core';
const resolver = createSubdomainResolver('example.com');
// tenant1.example.com -> tenant1
const tenant = await resolver({ hostname: 'tenant1.example.com' });
console.log(tenant?.id); // 'tenant1'
// example.com -> null
const tenant2 = await resolver({ hostname: 'example.com' });
console.log(tenant2); // null10.4.3 路径解析器
import { createPathResolver } from '@mtpc/core';
// 使用默认前缀 '/tenant/'
const resolver = createPathResolver();
const tenant = await resolver({ path: '/tenant/tenant-001/users' });
console.log(tenant?.id); // 'tenant-001'
// 使用自定义前缀
const customResolver = createPathResolver('/org/');
const tenant = await customResolver({ path: '/org/company-abc/dashboard' });
console.log(tenant?.id); // 'company-abc'10.4.4 查询参数解析器
import { createQueryResolver } from '@mtpc/core';
// 使用默认参数名 'tenant'
const resolver = createQueryResolver();
const tenant = await resolver({ query: { tenant: 'tenant-001' } });
console.log(tenant?.id); // 'tenant-001'
// 使用自定义参数名
const customResolver = createQueryResolver('company');
const tenant = await customResolver({ query: { company: 'acme-corp' } });10.4.5 复合解析器
import { createCompositeResolver } from '@mtpc/core';
// 组合多种解析方式
const resolver = createCompositeResolver(
createSubdomainResolver('example.com'),
createHeaderResolver(),
createPathResolver('/tenant/'),
createQueryResolver('tenant')
);
// 按顺序尝试解析,找到第一个有效的租户
const tenant = await resolver({
hostname: 'api.example.com',
headers: { 'x-tenant-id': 'tenant-001' },
path: '/api/data',
query: {}
});
console.log(tenant?.id); // 'tenant-001'10.4.6 带后备的解析器
import { createResolverWithFallback, DEFAULT_TENANT } from '@mtpc/core';
const fallbackTenant = createTenantContext('default');
const resolver = createResolverWithFallback(
createHeaderResolver(),
fallbackTenant
);
// 主解析器失败时使用后备租户
const tenant = await resolver({ headers: {} });
console.log(tenant?.id); // 'default'10.4.7 带验证的解析器
import { createValidatingResolver } from '@mtpc/core';
const resolver = createValidatingResolver(
createHeaderResolver(),
async (tenant) => {
// 验证租户状态
const dbTenant = await db.tenants.findUnique({ where: { id: tenant.id } });
return dbTenant !== null && dbTenant.status === 'active';
}
);
// 只有通过验证的租户才会被返回
const tenant = await resolver({ headers: { 'x-tenant-id': 'tenant-001' } });10.5 HTTP 中间件集成
// Express 中间件示例
import express from 'express';
import { createHeaderResolver, TenantContextHolder } from '@mtpc/core';
const app = express();
const tenantResolver = createHeaderResolver();
app.use(async (req, res, next) => {
try {
const tenant = await tenantResolver(req);
if (tenant) {
TenantContextHolder.set(tenant);
}
next();
} catch (error) {
res.status(400).json({ error: 'Invalid tenant' });
}
});
// 清理中间件
app.use((req, res, next) => {
res.on('finish', () => {
TenantContextHolder.clear();
});
next();
});11. API 参考
11.1 MTPC 类
11.1.1 构造函数
createMTPC(options?: MTPCOptions): MTPC参数:
options.defaultPermissionResolver: 默认权限解析器函数options.multiTenant: 多租户配置选项
返回值: MTPC 实例
11.1.2 资源管理
// 注册单个资源
registerResource(resource: ResourceDefinition): void
// 批量注册资源
registerResources(...resources: ResourceDefinition[]): void
// 获取资源定义
getResource(name: string): ResourceDefinition | undefined11.1.3 策略管理
// 注册单个策略
registerPolicy(policy: PolicyDefinition): void
// 批量注册策略
registerPolicies(...policies: PolicyDefinition[]): void
// 评估策略
evaluatePolicies(context: MTPCContext): Promise<EvaluationResult[]>11.1.4 插件管理
// 使用插件
use(plugin: PluginDefinition): void
// 获取插件实例
getPlugin(name: string): PluginInstance | undefined
// 获取所有插件
getPlugins(): Map<string, PluginInstance>
// 检查插件是否存在
hasPlugin(name: string): boolean11.1.5 权限检查
// 创建上下文
createContext(tenant: TenantContext, subject: SubjectContext): MTPCContext
// 检查权限
checkPermission(context: MTPCContext): Promise<PermissionCheckResult>
// 检查权限(无权限时抛出异常)
requirePermission(context: MTPCContext): Promise<void>11.1.6 初始化与状态
// 初始化 MTPC
init(): Promise<void>
// 检查是否已初始化
isInitialized(): boolean
// 获取系统摘要
getSummary(): MTPCSummary
// 导出元数据
exportMetadata(): RegistryMetadata11.1.7 权限解析器
// 设置权限解析器
setPermissionResolver(resolver: PermissionResolver): void
// 获取权限解析器
getPermissionResolver(): PermissionResolver11.1.8 租户管理
// 获取租户管理器
get tenants(): TenantManager11.2 Resource 相关
11.2.1 defineResource
defineResource<T>(definition: ResourceDefinition<T>): ResourceDefinition<T>11.2.2 ResourceBuilder
class ResourceBuilder<T> {
constructor(name: string)
setSchema(schema: z.ZodType<T>): this
setFeatures(features: ResourceFeatures): this
setMetadata(metadata: ResourceMetadata): this
addPermission(permission: CustomPermission): this
addHook<K extends keyof ResourceHooks<T>>(name: K, hook: ResourceHooks<T>[K]): this
setRelations(relations: ResourceRelations): this
build(): ResourceDefinition<T>
}11.3 Policy 相关
11.3.1 PolicyBuilder
class PolicyBuilder {
constructor(id: string)
setName(name: string): this
setDescription(description: string): this
setPriority(priority: PolicyPriority): this
setEnabled(enabled: boolean): this
addRule(rule: PolicyRule): this
withCondition(condition: PolicyCondition): this
build(): PolicyDefinition
}11.4 Registry 相关
11.4.1 UnifiedRegistry
class UnifiedRegistry {
resources: ResourceRegistry
permissions: PermissionRegistry
policies: PolicyRegistry
registerResource(resource: ResourceDefinition): void
registerPolicy(policy: PolicyDefinition): void
exportMetadata(): RegistryMetadata
freeze(): void
isFrozen(): boolean
}11.4.2 ResourceRegistry
class ResourceRegistry {
register(resource: ResourceDefinition): void
get(name: string): ResourceDefinition | undefined
getAll(): ResourceDefinition[]
getByGroup(group: string): ResourceDefinition[]
has(name: string): boolean
getNames(): string[]
freeze(): void
isFrozen(): boolean
}11.4.3 PermissionRegistry
class PermissionRegistry {
register(resourceName: string, permission: PermissionDefinition): void
registerMany(resourceName: string, permissions: PermissionDefinition[]): void
get(code: string): PermissionDefinition | undefined
getAll(): PermissionDefinition[]
getByResource(resourceName: string): PermissionDefinition[]
has(code: string): boolean
getCodes(): string[]
}11.4.4 PolicyRegistry
class PolicyRegistry {
register(policy: PolicyDefinition): void
get(id: string): PolicyDefinition | undefined
getAll(): PolicyDefinition[]
getEnabledPolicies(): PolicyDefinition[]
has(id: string): boolean
}11.5 Tenant 相关
11.5.1 租户上下文函数
// 创建租户上下文
createTenantContext(id: string, options?: { status?: TenantStatus; metadata?: Record<string, unknown> }): TenantContext
// 验证租户上下文
validateTenantContext(tenant: TenantContext | null | undefined): asserts tenant is TenantContext
// 检查租户是否活跃
isTenantActive(tenant: TenantContext): boolean
// 创建系统租户
createSystemTenant(): TenantContext
// 默认租户
DEFAULT_TENANT: TenantContext11.5.2 TenantContextHolder
class TenantContextHolder {
static set(tenant: TenantContext): void
static get(): TenantContext | null
static getOrThrow(): TenantContext
static clear(): void
static run<T>(tenant: TenantContext, fn: () => T): T
static runAsync<T>(tenant: TenantContext, fn: () => Promise<T>): Promise<T>
}11.5.3 TenantManager
class TenantManager {
constructor(store: TenantStore, options?: { cacheTtl?: number })
getTenant(id: string): Promise<TenantInfo | null>
getTenantOrThrow(id: string): Promise<TenantInfo>
createContext(id: string): Promise<TenantContext>
validateAndGetContext(id: string): Promise<TenantContext>
listTenants(): Promise<TenantInfo[]>
createTenant(info: Omit<TenantInfo, 'createdAt' | 'updatedAt'>): Promise<TenantInfo>
updateTenant(id: string, info: Partial<TenantInfo>): Promise<TenantInfo>
deleteTenant(id: string): Promise<void>
invalidateCache(id: string): void
clearCache(): void
}11.5.4 租户解析器
// 请求头解析器
createHeaderResolver(headerName?: string): TenantResolver<{ headers: Record<string, string | undefined> }>
// 子域名解析器
createSubdomainResolver(baseDomain: string): TenantResolver<{ hostname: string }>
// 路径解析器
createPathResolver(prefix?: string): TenantResolver<{ path: string }>
// 查询参数解析器
createQueryResolver(paramName?: string): TenantResolver<{ query: Record<string, string | undefined> }>
// 复合解析器
createCompositeResolver<T>(...resolvers: TenantResolver<T>[]): TenantResolver<T>
// 带后备的解析器
createResolverWithFallback<T>(resolver: TenantResolver<T>, fallback: TenantContext): TenantResolver<T>
// 带验证的解析器
createValidatingResolver<T>(resolver: TenantResolver<T>, validator: (tenant: TenantContext) => Promise<boolean> | boolean): TenantResolver<T>11.6 Hooks 相关
11.6.1 GlobalHooksManager
class GlobalHooksManager {
addBeforeAny(hook: BeforeAnyHook): void
addAfterAny(hook: AfterAnyHook): void
addOnError(hook: OnErrorHook): void
executeBeforeAny(context: MTPCContext, operation: string, resourceName: string): Promise<HookResult>
executeAfterAny(context: MTPCContext, operation: string, resourceName: string, result: unknown): Promise<void>
executeOnError(context: MTPCContext, operation: string, resourceName: string, error: Error): Promise<void>
clear(): void
getHooks(): GlobalHooks
}
// 工厂函数
createGlobalHooksManager(): GlobalHooksManager11.6.2 HookExecutor
class HookExecutor<T> {
constructor(hooks: ResourceHooks<T>)
executeBeforeCreate(context: MTPCContext, data: T): Promise<HookResult<T>>
executeAfterCreate(context: MTPCContext, data: T, created: T): Promise<void>
executeBeforeRead(context: MTPCContext, id: string): Promise<HookResult<string>>
executeAfterRead(context: MTPCContext, id: string, data: T | null): Promise<T | null>
executeBeforeUpdate(context: MTPCContext, id: string, data: Partial<T>): Promise<HookResult<Partial<T>>>
executeAfterUpdate(context: MTPCContext, id: string, data: Partial<T>, updated: T): Promise<void>
executeBeforeDelete(context: MTPCContext, id: string): Promise<HookResult<string>>
executeAfterDelete(context: MTPCContext, id: string, deleted: T): Promise<void>
executeBeforeList(context: MTPCContext, options: QueryOptions): Promise<HookResult<QueryOptions>>
executeAfterList(context: MTPCContext, options: QueryOptions, results: T[]): Promise<T[]>
executeFilterQuery(context: MTPCContext, baseFilters: FilterCondition[]): Promise<HookResult<FilterCondition[]>>
}
// 工厂函数
createHookExecutor<T>(hooks: ResourceHooks<T>): HookExecutor<T>12. 常见问题
Q1: 如何扩展自定义条件类型?
A: 使用 policyEngine.addConditionHandler 方法添加自定义条件处理器:
mtpc.policyEngine.addConditionHandler('custom', async (condition, context) => {
const { field, operator, value } = condition;
const fieldValue = getFieldValue(context, field);
return customCompare(fieldValue, operator, value);
});Q2: 如何实现基于属性的访问控制(ABAC)?
A: 利用策略条件系统,通过 field 类型条件检查主体、资源或环境属性:
mtpc.registerPolicy({
id: 'abac-policy',
name: 'ABAC 策略',
rules: [{
permissions: ['document:read'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.department',
operator: 'eq',
value: 'finance'
}]
}]
});Q3: 如何处理权限变更时的缓存失效?
A: 实现权限变更事件监听,当权限发生变化时,主动清除相关缓存:
async function onPermissionsChanged(tenantId: string, subjectId: string) {
// 清除权限检查器缓存
mtpc.permissionChecker.clearSubjectCache(tenantId, subjectId);
// 如果使用外部缓存,也需要清除
await redisClient.del(`permissions:${tenantId}:${subjectId}`);
}Q4: 如何与现有权限系统集成?
A: 实现自定义 defaultPermissionResolver,从现有系统获取权限数据:
const mtpc = createMTPC({
defaultPermissionResolver: async (tenantId: string, subjectId: string) => {
// 从现有权限系统获取权限
const permissions = await existingPermissionSystem.getPermissions(tenantId, subjectId);
return new Set(permissions);
}
});Q5: 如何进行权限审计?
A: 使用钩子系统,在权限检查前后记录审计日志:
mtpc.globalHooks.addAfterAny(async (context, operation, resource, result) => {
await auditLogger.log({
userId: context.subject.id,
tenantId: context.tenant.id,
operation,
resource,
result,
timestamp: new Date()
});
});Q6: 如何实现租户级别的策略?
A: 在策略定义中指定 tenantId:
mtpc.registerPolicy({
id: 'tenant-1-admin',
name: '租户1管理员',
tenantId: 'tenant-1', // 租户级别的策略
rules: [{
permissions: ['*'],
effect: 'allow'
}],
priority: 'high',
enabled: true
});Q7: 如何实现资源级别的权限?
A: 在资源定义中添加自定义权限:
const documentResource = defineResource({
name: 'document',
features: {
create: true,
read: true,
update: true,
delete: true
},
permissions: [
{
action: 'share',
description: '分享文档'
},
{
action: 'download',
description: '下载文档'
}
]
});Q8: 如何实现动态权限?
A: 使用策略条件系统,根据运行时条件动态授予权限:
mtpc.registerPolicy({
id: 'dynamic-policy',
name: '动态权限策略',
rules: [{
permissions: ['resource:action'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.level',
operator: 'gte',
value: 5
}]
}]
});Q9: 如何实现权限继承?
A: 通过策略条件和权限解析器实现:
// 在权限解析器中实现权限继承
const mtpc = createMTPC({
defaultPermissionResolver: async (tenantId, subjectId) => {
// 获取用户权限
const userPermissions = await getUserPermissions(tenantId, subjectId);
// 获取用户角色
const roles = await getUserRoles(tenantId, subjectId);
// 获取角色权限
const rolePermissions = await getRolePermissions(tenantId, roles);
// 合并权限
return new Set([...userPermissions, ...rolePermissions]);
}
});Q10: 如何实现权限委托?
A: 使用策略条件系统,检查委托关系:
mtpc.registerPolicy({
id: 'delegation-policy',
name: '权限委托策略',
rules: [{
permissions: ['user:manage'],
effect: 'allow',
conditions: [{
type: 'field',
field: 'subject.attributes.delegatedBy',
operator: 'eq',
value: 'manager-id'
}]
}]
});13. 最佳实践
13.1 设计原则
- 遵循业务无关原则:保持权限逻辑与业务逻辑分离
- 采用 Schema 驱动:使用 Schema 定义作为单一事实源
- 优先使用编译期配置:减少运行时计算
- 遵循默认拒绝原则:确保安全
- 实现最小权限原则:只授予必要的权限
13.2 代码组织
- 集中管理资源定义:将所有资源定义放在单独的文件中
- 按功能模块组织策略:将策略按功能模块分组
- 使用插件扩展功能:保持核心代码简洁
- 为权限检查添加详细日志:便于调试和审计
13.3 性能优化
- 合理使用权限缓存:配置合适的缓存大小和 TTL
- 批量处理权限检查:使用
Promise.all并行执行 - 优化策略评估逻辑:减少复杂条件和策略数量
- 监控性能指标:定期检查权限检查性能
13.4 安全实践
- 始终验证租户上下文:确保租户有效性
- 避免硬编码权限:使用策略系统管理权限
- 定期审查权限配置:清理不必要的权限
- 实现权限审计:记录所有权限检查
13.5 可维护性
- 为资源和权限添加清晰的描述:便于理解和管理
- 使用一致的命名规范:提高代码可读性
- 编写单元测试和集成测试:确保功能正确性
- 保持文档更新:及时更新使用文档
13.6 错误处理
import {
PermissionDeniedError,
InvalidTenantError,
MissingTenantContextError,
ResourceNotFoundError,
PolicyNotFoundError
} from '@mtpc/shared/errors';
try {
await mtpc.requirePermission(context);
} catch (error) {
if (error instanceof PermissionDeniedError) {
// 权限不足
console.error('权限拒绝:', error.message);
} else if (error instanceof MissingTenantContextError) {
// 缺少租户上下文
console.error('缺少租户上下文');
} else if (error instanceof InvalidTenantError) {
// 无效的租户ID
console.error('无效的租户ID');
} else if (error instanceof ResourceNotFoundError) {
// 资源未找到
console.error('资源未找到');
} else if (error instanceof PolicyNotFoundError) {
// 策略未找到
console.error('策略未找到');
} else {
// 其他错误
console.error('未知错误:', error);
}
}13.7 性能监控
// 监控权限检查性能
const originalCheckPermission = mtpc.checkPermission.bind(mtpc);
mtpc.checkPermission = async (context) => {
const startTime = performance.now();
const result = await originalCheckPermission(context);
const endTime = performance.now();
const duration = endTime - startTime;
// 记录性能指标
console.log('权限检查性能:', {
permission: `${context.resource}:${context.action}`,
duration: `${duration.toFixed(2)}ms`,
allowed: result.allowed
});
// 如果性能超过阈值,记录详细信息
if (duration > 100) {
console.warn('权限检查性能警告:', {
...context,
duration: `${duration.toFixed(2)}ms`
});
}
return result;
};附录
A. 类型定义
A.1 MTPCOptions
interface MTPCOptions {
defaultPermissionResolver?: PermissionResolver;
multiTenant?: MultiTenantOptions;
}A.2 PermissionResolver
type PermissionResolver = (tenantId: string, subjectId: string) => Promise<Set<string>>;A.3 MTPCContext
interface MTPCContext {
tenant: TenantContext;
subject: SubjectContext;
resource: string;
action: string;
}A.4 TenantContext
interface TenantContext {
id: string;
status?: TenantStatus;
metadata?: Record<string, unknown>;
}A.5 SubjectContext
interface SubjectContext {
id: string;
type: string;
attributes?: Record<string, unknown>;
permissions?: Set<string>;
}A.6 PermissionCheckResult
interface PermissionCheckResult {
allowed: boolean;
permission: string;
reason: string;
evaluationTime: number;
}B. 性能指标
| 指标 | 目标值 | 优化建议 |
|---|---|---|
| 权限检查延迟 | < 50ms | 优化权限解析器,使用缓存 |
| 批量权限检查吞吐量 | > 1000 QPS | 使用并行执行,调整并发数 |
| 策略评估延迟 | < 10ms | 优化策略条件,减少复杂规则 |
| 缓存命中率 | > 90% | 优化缓存策略,调整过期时间 |
C. 版本历史
1.0.0
- 初始版本发布
- 核心功能实现:资源定义、策略引擎、权限检查器
- 支持多租户上下文
- 插件系统和钩子系统
- 基本性能优化
1.1.0
- 新增批量权限检查功能
- 优化策略评估算法
- 增强错误处理机制
- 添加性能监控支持
1.2.0
- 新增自定义条件类型支持
- 增强租户管理功能
- 优化权限缓存机制
- 添加更多示例和文档
文档版本: 1.0.0 最后更新: 2024-12-27 维护者: MTPC Team
继续学习: @mtpc/rbac →