安全

权限模型

基于 CASL 的声明式权限控制

权限模型

项目使用 CASL 实现声明式的权限控制。核心概念:

  • Role(角色):USERVIPADMIN
  • Action(操作):createreadupdatedeletemanage(manage 表示所有操作)
  • Subject(对象):UserProjectSubscriptionSettingsall

各角色的默认权限:

角色ProjectUser(自身)SubscriptionSettings
USER读、创建、更新读、更新-
VIP读、创建、更新、删除读、更新读、更新
ADMIN全部(manage all)全部全部全部

权限定义在 packages/permissions/src/abilities.ts。在代码中检查权限:

import { can, cannot, Action, Subject } from "@01mvp/permissions";
import type { AppUser } from "@01mvp/permissions";

const user: AppUser = { id: "user-123", role: Role.USER };

// 检查用户能否创建项目
if (can(user, Action.CREATE, Subject.PROJECT)) {
  // 允许操作
}

// 检查用户能否更新其他用户的信息(带具体数据)
if (cannot(user, Action.UPDATE, Subject.USER, { id: "other-user-id" })) {
  // 拒绝操作
}

packages/permissions/src/utils.ts 还提供了辅助函数:

import { createAppUser, getAvailableActions, mapDatabaseRoleToAppRole } from "@01mvp/permissions";

// 从数据库用户记录创建 AppUser(自动映射 role 字符串到枚举)
const appUser = createAppUser({ id: "1", role: "vip" });

// 获取用户在某个对象上所有可执行的操作
const actions = getAvailableActions(appUser, Subject.PROJECT);
// => ["read", "create", "update", "delete"]

mapDatabaseRoleToAppRole 会自动把 "admin" 映射为 ADMIN"vip" 映射为 VIP,其他值(包括 "user""normal")映射为 USER

定义新的权限规则

packages/permissions/src/abilities.tsdefineAbilitiesFor 函数中添加规则:

// 示例:给 VIP 用户增加查看订阅详情的权限
can(Action.READ, Subject.SUBSCRIPTION);

如果需要新增 Subject(对象类型),在 packages/permissions/src/types.tsSubject 枚举中添加即可。