Files
huang eaa70ac255 feat: 实现 RBAC 权限系统和数据权限控制 (004-rbac-data-permission)
主要功能:
- 实现完整的 RBAC 权限系统(账号、角色、权限的多对多关联)
- 基于 owner_id + shop_id 的自动数据权限过滤
- 使用 PostgreSQL WITH RECURSIVE 查询下级账号
- Redis 缓存优化下级账号查询性能(30分钟过期)
- 支持多租户数据隔离和层级权限管理

技术实现:
- 新增 Account、Role、Permission 模型及关联关系表
- 实现 GORM Scopes 自动应用数据权限过滤
- 添加数据库迁移脚本(000002_rbac_data_permission、000003_add_owner_id_shop_id)
- 完善错误码定义(1010-1027 为 RBAC 相关错误)
- 重构 main.go 采用函数拆分提高可读性

测试覆盖:
- 添加 Account、Role、Permission 的集成测试
- 添加数据权限过滤的单元测试和集成测试
- 添加下级账号查询和缓存的单元测试
- 添加 API 回归测试确保向后兼容

文档更新:
- 更新 README.md 添加 RBAC 功能说明
- 更新 CLAUDE.md 添加技术栈和开发原则
- 添加 docs/004-rbac-data-permission/ 功能总结和使用指南

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 16:44:06 +08:00

589 lines
15 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: Role Management API
description: RBAC 角色管理接口 - 支持角色的创建、查询、更新、删除和权限分配
version: 1.0.0
servers:
- url: http://localhost:8080/api/v1
description: Development server
tags:
- name: roles
description: 角色管理
- name: role-permissions
description: 角色-权限关联
paths:
/roles:
post:
summary: 创建角色
description: 创建新角色
tags:
- roles
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateRoleRequest'
responses:
'200':
description: 创建成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
$ref: '#/components/schemas/RoleResponse'
'400':
description: 请求参数错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
get:
summary: 查询角色列表
description: 分页查询角色列表
tags:
- roles
parameters:
- name: page
in: query
description: 页码(从 1 开始)
schema:
type: integer
default: 1
minimum: 1
- name: page_size
in: query
description: 每页大小
schema:
type: integer
default: 20
minimum: 1
maximum: 100
- name: role_type
in: query
description: 角色类型过滤1=超级, 2=代理, 3=企业)
schema:
type: integer
enum: [1, 2, 3]
- name: status
in: query
description: 状态过滤0=禁用, 1=启用)
schema:
type: integer
enum: [0, 1]
responses:
'200':
description: 查询成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
$ref: '#/components/schemas/ListRolesResponse'
'400':
description: 请求参数错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
/roles/{id}:
get:
summary: 查询角色详情
description: 根据 ID 查询角色详情
tags:
- roles
parameters:
- name: id
in: path
required: true
description: 角色 ID
schema:
type: integer
responses:
'200':
description: 查询成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
$ref: '#/components/schemas/RoleResponse'
'404':
description: 角色不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
put:
summary: 更新角色
description: 更新角色信息
tags:
- roles
parameters:
- name: id
in: path
required: true
description: 角色 ID
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateRoleRequest'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
$ref: '#/components/schemas/RoleResponse'
'400':
description: 请求参数错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'404':
description: 角色不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
delete:
summary: 删除角色
description: 软删除角色,设置 deleted_at 字段
tags:
- roles
parameters:
- name: id
in: path
required: true
description: 角色 ID
schema:
type: integer
responses:
'200':
description: 删除成功
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'404':
description: 角色不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
/roles/{id}/permissions:
post:
summary: 为角色分配权限
description: 批量为角色分配权限,已存在的关联会被忽略
tags:
- role-permissions
parameters:
- name: id
in: path
required: true
description: 角色 ID
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AssignPermsToRoleRequest'
responses:
'200':
description: 分配成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RolePermissionResponse'
'400':
description: 请求参数错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'404':
description: 角色或权限不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
get:
summary: 查询角色的所有权限
description: 查询指定角色已分配的所有权限
tags:
- role-permissions
parameters:
- name: id
in: path
required: true
description: 角色 ID
schema:
type: integer
responses:
'200':
description: 查询成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiResponse'
- type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PermissionResponse'
'404':
description: 角色不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
/roles/{role_id}/permissions/{perm_id}:
delete:
summary: 移除角色的权限
description: 软删除角色-权限关联
tags:
- role-permissions
parameters:
- name: role_id
in: path
required: true
description: 角色 ID
schema:
type: integer
- name: perm_id
in: path
required: true
description: 权限 ID
schema:
type: integer
responses:
'200':
description: 移除成功
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'404':
description: 角色或权限不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: 服务器错误
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
components:
schemas:
ApiResponse:
type: object
required:
- code
- message
- timestamp
properties:
code:
type: integer
description: 错误码0 表示成功1xxx 表示客户端错误2xxx 表示服务端错误)
example: 0
message:
type: string
description: 响应消息
example: success
data:
type: object
description: 响应数据
timestamp:
type: string
format: date-time
description: 响应时间戳ISO 8601 格式)
example: "2025-11-18T15:30:00Z"
CreateRoleRequest:
type: object
required:
- role_name
- role_type
properties:
role_name:
type: string
maxLength: 50
description: 角色名称
example: 平台管理员
role_desc:
type: string
maxLength: 255
description: 角色描述
example: 平台系统管理员角色
role_type:
type: integer
enum: [1, 2, 3]
description: 角色类型1=超级, 2=代理, 3=企业)
example: 1
status:
type: integer
enum: [0, 1]
default: 1
description: 状态0=禁用, 1=启用)
example: 1
UpdateRoleRequest:
type: object
properties:
role_name:
type: string
maxLength: 50
description: 角色名称(可选更新)
example: 平台超级管理员
role_desc:
type: string
maxLength: 255
description: 角色描述(可选更新)
example: 平台系统超级管理员角色
status:
type: integer
enum: [0, 1]
description: 状态(可选更新)
example: 0
RoleResponse:
type: object
properties:
id:
type: integer
description: 角色 ID
example: 1
role_name:
type: string
description: 角色名称
example: 平台管理员
role_desc:
type: string
description: 角色描述
example: 平台系统管理员角色
role_type:
type: integer
description: 角色类型1=超级, 2=代理, 3=企业)
example: 1
status:
type: integer
description: 状态0=禁用, 1=启用)
example: 1
creator:
type: integer
description: 创建人 ID
example: 1
updater:
type: integer
description: 更新人 ID
example: 1
created_at:
type: string
format: date-time
description: 创建时间
example: "2025-11-18T10:00:00Z"
updated_at:
type: string
format: date-time
description: 更新时间
example: "2025-11-18T10:00:00Z"
ListRolesResponse:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/RoleResponse'
total:
type: integer
description: 总记录数
example: 50
page:
type: integer
description: 当前页码
example: 1
page_size:
type: integer
description: 每页大小
example: 20
AssignPermsToRoleRequest:
type: object
required:
- perm_ids
properties:
perm_ids:
type: array
items:
type: integer
minItems: 1
description: 权限 ID 列表
example: [1, 2, 3, 4, 5]
RolePermissionResponse:
type: object
properties:
id:
type: integer
description: 关联 ID
example: 1
role_id:
type: integer
description: 角色 ID
example: 1
perm_id:
type: integer
description: 权限 ID
example: 1
status:
type: integer
description: 状态0=禁用, 1=启用)
example: 1
creator:
type: integer
description: 创建人 ID
example: 1
created_at:
type: string
format: date-time
description: 创建时间
example: "2025-11-18T10:00:00Z"
PermissionResponse:
type: object
properties:
id:
type: integer
description: 权限 ID
example: 1
perm_name:
type: string
description: 权限名称
example: 用户管理
perm_code:
type: string
description: 权限编码
example: user:create
perm_type:
type: integer
description: 权限类型1=菜单, 2=按钮)
example: 1
url:
type: string
description: URL 路径
example: /admin/users
parent_id:
type: integer
nullable: true
description: 上级权限 ID
example: null
sort:
type: integer
description: 排序序号
example: 1
status:
type: integer
description: 状态0=禁用, 1=启用)
example: 1
created_at:
type: string
format: date-time
description: 创建时间
example: "2025-11-18T10:00:00Z"
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- BearerAuth: []