做产品 PMaker
空格的键盘
显示了再报错
文档用户管理系统设置日志
删除 导出
403 你没有权限执行此操作
点了才知道不能点
看到的就是能用的
文档日志
导出
界面本身就是权限的表达

同一个账号,两种做法。左边把「不能做」留到点击之后才说,右边根本不显示。

Permission as view

What the user sees should equal what they can do. Show them things they cannot access and then block them — that is making them hit a wall every time.

What you'll run into
  • 点了才提示没权限,用户不知道该找谁开
  • 前端把按钮藏起来了,但接口没拦,改个请求就能越权
  • 加一个新角色要改十几个页面,因为权限是散在各处写死的

Three kinds of permission

First sort out which kind it is — the implementation is completely different.

类型控制什么界面上表现为
页面权限 能看到系统里的哪些页面 导航菜单里有没有这一项。没权限就不出现
操作权限 能在页面上做哪些动作 按钮显不显示:查看、新增、修改、删除、审核
数据权限 同一个页面能看到哪些数据 列表里的条数不同。销售只看自己的客户
Another model is ACL: maintain an access list per object. More precise and flexible, but every object carries its own list, so the maintenance cost is far higher — suitable for files, documents, and other cases that need per-object authorization.

Granularity can split one more layer: admin, edit, preview. Admin can assign permissions and delete data; edit can change content; preview can only view. Document products often add independent toggles for download, upload, and public sharing.

How to build RBAC

Do not bind permissions directly to users. Slip a role layer in between and both adding people and adding permissions turn into configuration.

用户 具体的人 角色 一组权限的集合 权限 页面 / 操作 / 数据 部门 用户组 用户也可以通过部门或用户组拿到角色
Another model is ACL: maintain an access list per object. More precise and flexible, but every object carries its own list, so the maintenance cost is far higher — suitable for files, documents, and other cases that need per-object authorization.

Design it in three steps: list the roles first (by org structure or by system structure), then list the permissions (pages, operations, data — three kinds), and finally draw a role-by-permission matching table. Once that table is drawn, most of the permission design is done.

How to handle it in the UI

A note for AI

CLAUDE.md · permission rules
## 权限

模型:RBAC。用户 → 角色 → 权限,不要把权限直接绑在用户上。

权限分三类,每类都要实现:
- 页面权限:无权限时导航项不渲染,直接访问 URL 也要拦
- 操作权限:无权限时按钮不渲染,不要渲染后禁用
- 数据权限:在查询条件里过滤,不要查全量再在前端筛

颗粒度:管理 / 编辑 / 预览三档。

强制要求:
- 前端的隐藏只是体验优化,每个接口都必须独立校验权限,
  不能依赖前端不发请求。
- 新增任何接口时,先说明它需要哪个权限,再写实现。
- 涉及数据权限的查询,把过滤条件写进 SQL 或 ORM 查询,
  并在代码注释里说明过滤依据。

例外情况(显示但禁用)只用于:用户知道有这个功能且能自行申请,
此时禁用态必须带一句说明,告诉他找谁开通。