feat: 支持动态角色权限分配
This commit is contained in:
@@ -17,12 +17,12 @@
|
||||
## 项目能力
|
||||
|
||||
- 门店管理:查询、新增、修改、软删除门店。
|
||||
- 角色管理:管理员可查看角色;超级管理员可新增、修改、删除自定义角色,服务端内置角色不可变更。
|
||||
- 角色管理:拥有 `role:manage` 的账号可新增、修改、删除自定义角色,服务端内置角色不可变更。
|
||||
- 员工管理:分页查询、新增、修改、启用/停用、软删除员工。
|
||||
- 员工角色:一个员工可以绑定多个角色。
|
||||
- 登录账号:超级管理员和员工都可以登录。
|
||||
- 后台权限:超级管理员拥有所有权限;管理员可管理门店和员工、只读角色;店长只看当前门店员工。
|
||||
- 固定权限:菜单和动作权限由服务端写死,前端只按接口返回结果展示。
|
||||
- 后台权限:超级管理员拥有所有权限;角色权限由 `role_permissions` 动态分配。
|
||||
- 动态权限:菜单和按钮动作由 `/api/permissions/me` 返回,前端可通过权限管理页分配角色权限。
|
||||
- JWT 鉴权:登录后签发 token,除健康检查和登录外,接口都需要 Bearer token。
|
||||
- 数据校验:使用 zod 校验路径参数、查询参数和请求体。
|
||||
- 数据库迁移:使用 `migrations/*.sql` 管理建表和初始化数据。
|
||||
@@ -40,12 +40,15 @@
|
||||
├── .gitignore # Git 忽略规则,排除本地配置、依赖和编译产物
|
||||
├── AGENTS.md # Codex/Agent 入口指令,当前指向 RTK.md
|
||||
├── RTK.md # 项目协作规则和开发约定
|
||||
├── docs/
|
||||
│ └── API.md # 前端对接接口文档
|
||||
├── migrations/ # 数据库迁移 SQL
|
||||
│ ├── 001_initial_schema.sql # 创建基础表结构
|
||||
│ ├── 002_seed_demo_data.sql # 初始化演示门店和角色
|
||||
│ ├── 003_create_super_admins.sql # 创建超级管理员表和默认账号
|
||||
│ ├── 004_add_employee_login_fields.sql # 给员工补充登录字段
|
||||
│ └── 005_refine_employee_login_and_role_policy.sql # 调整员工默认密码、手机号唯一和系统角色
|
||||
│ ├── 005_refine_employee_login_and_role_policy.sql # 调整员工默认密码、手机号唯一和系统角色
|
||||
│ └── 006_create_role_permissions.sql # 创建角色权限关系表并初始化默认权限
|
||||
├── src/
|
||||
│ ├── app.ts # 创建 Fastify 应用、注册路由、统一错误处理
|
||||
│ ├── server.ts # 启动 HTTP 服务和优雅停机
|
||||
@@ -58,7 +61,7 @@
|
||||
│ │ ├── auth/ # 登录、当前用户和 JWT 鉴权模块
|
||||
│ │ ├── catalog/ # 门店和角色模块
|
||||
│ │ ├── employees/ # 员工 CRUD 模块
|
||||
│ │ └── permissions/ # 服务端固定菜单和动作权限策略
|
||||
│ │ └── permissions/ # 权限点定义、角色权限分配和菜单动作策略
|
||||
│ └── shared/ # 通用响应结构和业务错误
|
||||
├── docker-compose.yml # 本地 MySQL
|
||||
├── package.json
|
||||
@@ -77,6 +80,7 @@
|
||||
| `.gitignore` | 忽略本地环境变量、依赖目录、编译产物和系统文件,避免把无关文件推到仓库。 |
|
||||
| `AGENTS.md` | Agent 工具读取的入口文件,当前通过 `@RTK.md` 引入项目规则。 |
|
||||
| `RTK.md` | 本项目的协作规则,例如使用中文说明、保持分层、改目录时同步 README。 |
|
||||
| `docs/API.md` | 面向前端对接的完整接口文档,包含认证、权限、字段约束、示例请求响应和错误码。 |
|
||||
| `migrations/` | 数据库迁移目录。所有建表、改表、初始化基础数据的 SQL 都放在这里。 |
|
||||
| `src/app.ts` | 创建 Fastify 应用,注册路由,处理健康检查和全局错误。 |
|
||||
| `src/server.ts` | 真正启动 HTTP 服务,监听端口,并处理优雅停机。 |
|
||||
@@ -86,7 +90,7 @@
|
||||
| `src/modules/auth/` | 登录鉴权模块,负责后台登录、员工端登录、密码校验、JWT 签发、当前用户查询和权限 guard。 |
|
||||
| `src/modules/catalog/` | 门店和角色模块,负责基础资料接口。 |
|
||||
| `src/modules/employees/` | 员工模块,负责员工分页、详情、新增、修改、状态变更和软删除。 |
|
||||
| `src/modules/permissions/` | 服务端固定权限策略,返回前端菜单、动作权限和权限策略说明。 |
|
||||
| `src/modules/permissions/` | 权限模块,维护权限点定义、角色权限分配、当前用户菜单动作权限和权限策略说明。 |
|
||||
| `src/shared/` | 跨模块复用的响应结构和业务错误类型。 |
|
||||
| `docker-compose.yml` | 本地开发用 MySQL 容器配置。 |
|
||||
| `package.json` | 项目信息、依赖和常用脚本;脚本会读取现有 `.env.development`。 |
|
||||
@@ -160,6 +164,7 @@ pnpm db:migrate
|
||||
- `roles`:角色表
|
||||
- `employees`:员工表
|
||||
- `employee_roles`:员工角色关系表
|
||||
- `role_permissions`:角色权限关系表
|
||||
- `super_admins`:超级管理员表
|
||||
- `schema_migrations`:迁移记录表
|
||||
|
||||
@@ -217,6 +222,10 @@ pnpm db:migrate
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## 接口文档
|
||||
|
||||
完整前端对接文档见 [docs/API.md](./docs/API.md),包含认证、权限、字段约束、全部接口、示例请求响应和常见错误码。
|
||||
|
||||
## 接口响应格式
|
||||
|
||||
成功响应:
|
||||
@@ -304,7 +313,7 @@ curl -X POST http://localhost:3500/api/auth/employee/login \
|
||||
```
|
||||
|
||||
响应里的 `data.token` 就是后续接口要使用的 JWT。
|
||||
响应里的 `data.user.permissions` 是服务端计算出的固定权限点;菜单和按钮动作以 `/api/permissions/me` 返回结果为准。
|
||||
响应里的 `data.user.permissions` 是服务端按角色动态计算出的权限点;菜单和按钮动作以 `/api/permissions/me` 返回结果为准。
|
||||
|
||||
为了方便测试,可以先把 token 保存成 shell 变量:
|
||||
|
||||
@@ -332,23 +341,39 @@ curl http://localhost:3500/api/permissions/me \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
查看服务端固定权限策略:
|
||||
查看角色权限策略:
|
||||
|
||||
```bash
|
||||
curl http://localhost:3500/api/permissions/policies \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
查看可分配权限点定义:
|
||||
|
||||
```bash
|
||||
curl http://localhost:3500/api/permissions/definitions \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
给角色分配权限:
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:3500/api/permissions/roles/5 \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"permissions":["store:view","store:manage","permission:view","permission:manage"]}'
|
||||
```
|
||||
|
||||
如果员工账号没有后台菜单权限,可以通过员工端登录并访问 `/api/auth/me`,但访问门店、角色、员工等后台管理接口会返回 `403 FORBIDDEN`。
|
||||
|
||||
### 后台菜单权限
|
||||
|
||||
| 菜单 | 超级管理员 | 管理员 `admin` | 店长 `store_manager` | 其他员工 |
|
||||
| 菜单 | 超级管理员 | 默认管理员 `admin` | 默认店长 `store_manager` | 其他角色 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 门店管理 | 查看、新增、修改、删除 | 查看、新增、修改、删除 | 不可见 | 不可见 |
|
||||
| 角色管理 | 查看、新增、修改、删除自定义角色 | 仅查看 | 不可见 | 不可见 |
|
||||
| 角色管理 | 查看、新增、修改、删除自定义角色 | 查看、新增、修改、删除自定义角色 | 不可见 | 按角色权限决定 |
|
||||
| 员工管理 | 查看全部、新增、修改、删除 | 查看全部、新增、修改、删除 | 仅查看当前门店员工 | 不可见 |
|
||||
| 权限管理 | 查看 | 查看 | 不可见 | 不可见 |
|
||||
| 权限管理 | 查看、分配 | 查看、分配 | 不可见 | 按角色权限决定 |
|
||||
|
||||
## 门店接口示例
|
||||
|
||||
@@ -402,8 +427,8 @@ curl -X DELETE http://localhost:3500/api/stores/1 \
|
||||
|
||||
## 角色接口示例
|
||||
|
||||
角色管理页面只有超级管理员和管理员可见。管理员只能看;超级管理员可以新增、修改、删除自定义角色。服务端内置角色不可修改或删除。
|
||||
自定义角色默认不绑定后台菜单权限;后台菜单权限仍由服务端固定策略控制。
|
||||
角色管理页面由 `role:view` 控制可见性,由 `role:manage` 控制新增、修改、删除。服务端内置角色不可修改或删除。
|
||||
自定义角色默认不绑定后台菜单权限;可以在权限管理页面给角色分配权限后,再把角色绑定给员工。
|
||||
|
||||
查询角色:
|
||||
|
||||
@@ -511,6 +536,7 @@ curl -X DELETE http://localhost:3500/api/employees/1 \
|
||||
- [003_create_super_admins.sql](./migrations/003_create_super_admins.sql):创建超级管理员表,并初始化本地登录账号。
|
||||
- [004_add_employee_login_fields.sql](./migrations/004_add_employee_login_fields.sql):给员工补充登录密码哈希和最后登录时间。
|
||||
- [005_refine_employee_login_and_role_policy.sql](./migrations/005_refine_employee_login_and_role_policy.sql):员工默认密码改为 `pw111111`,手机号改为全局唯一,并标记服务端内置角色。
|
||||
- [006_create_role_permissions.sql](./migrations/006_create_role_permissions.sql):创建角色权限关系表,并初始化 `admin` 和 `store_manager` 的默认权限。
|
||||
|
||||
执行 `pnpm db:migrate` 时,脚本会:
|
||||
|
||||
@@ -533,10 +559,12 @@ migrations/003_add_employee_email.sql
|
||||
- `employees.active_phone` 是生成列,用来实现“未删除员工手机号全局唯一”。
|
||||
- `employees.password_hash` 让员工也能登录,默认本地密码是 `pw111111`。
|
||||
- `employee_roles` 是多对多关系表。
|
||||
- `role_permissions` 保存角色和权限点的多对多关系,权限分配保存后会在接口鉴权时实时生效。
|
||||
- `super_admins` 保存超级管理员账号,密码使用 PBKDF2 哈希,禁止存明文。
|
||||
- 菜单和动作权限由 `src/modules/permissions/` 固定,前端根据 `/api/permissions/me` 渲染。
|
||||
- `admin` 角色可查看角色、管理门店和员工;`store_manager` 只能查看当前门店员工。
|
||||
- JWT 鉴权在 `src/modules/auth/` 中实现,`permissionGuard` 按固定权限点保护接口。
|
||||
- 权限点定义由 `src/modules/permissions/` 固定,角色拥有的权限点由 `role_permissions` 动态决定。
|
||||
- 前端根据 `/api/permissions/me` 渲染菜单和按钮,根据 `/api/permissions/definitions` 渲染可分配权限点。
|
||||
- `admin` 角色默认可管理门店、角色、员工和权限;`store_manager` 默认只能查看当前门店员工。
|
||||
- JWT 鉴权在 `src/modules/auth/` 中实现,`permissionGuard` 按当前角色权限点保护接口。
|
||||
- `repository` 使用参数化查询,避免 SQL 注入。
|
||||
- `service` 使用事务保证员工信息和角色绑定同时成功或同时失败。
|
||||
- `app.ts` 统一注册 JWT、业务路由和错误处理,并处理 zod 校验错误、业务错误和数据库唯一索引冲突。
|
||||
|
||||
Reference in New Issue
Block a user