Skip to content

Commit 47f62ce

Browse files
committed
update docs
1 parent bb9fa5b commit 47f62ce

File tree

12 files changed

+237
-48
lines changed

12 files changed

+237
-48
lines changed

docs/.vuepress/navbar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const myNavbar = defineNavbarConfig([
55
text: '演示',
66
items: [
77
{
8-
text: 'Arco Design Pro 版本',
8+
text: 'Arco Design 版本',
99
link: 'https://fba.xwboy.top/'
1010
}
1111
]

docs/.vuepress/sidebar.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,15 @@ export const mySidebar: SidebarMulti = {
1818
collapsed: false,
1919
prefix: 'reference/',
2020
items: [
21-
{text: '登录', link: 'login'},
22-
{text: 'OAuth 2.0', link: 'oauth2'},
21+
{text: '授权', link: 'oauth'},
2322
{text: '跨域', link: 'cors'},
24-
{text: '权限', link: 'permission'},
23+
{text: 'RBAC', link: 'RBAC'},
2524
{text: '事务', link: 'transaction'},
2625
{text: '代码生成', link: 'code-generation'},
2726
]
2827
},
2928
{
30-
text: 'MiXin',
29+
text: 'Mixin',
3130
collapsed: false,
3231
prefix: 'mixin/',
3332
items: [

docs/guide/mixin/user.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
---
2-
title: MiXin
2+
title: Mixin
33
---
44

5-
## TODO
5+
我们默认提供的所有模型都是没有操作人员信息的,在很多项目中,可能会添加每条数据的创建人、更新人,
6+
虽然我们没有实行这一特性,但是,我们提供了非常简易的集成方式
7+
8+
## 如何应用?
9+
10+
`common/model.py` 文件中,我们提供了用户 Mixin 类
11+
12+
```py
13+
class UserMixin(MappedAsDataclass):
14+
"""用户 Mixin 数据类"""
15+
16+
create_user: Mapped[int] = mapped_column(sort_order=998, comment='创建者')
17+
update_user: Mapped[int | None] = mapped_column(init=False, default=None, sort_order=998, comment='修改者')
18+
```
19+
20+
通常情况下,你会在自定义模型类中继承 `Base` 父类,要想灵活的应用操作人员信息,你只需在继承 `Base` 父类的同时,也继承
21+
`UserMixin` 类,这样就将自动添加操作人员列到模型
22+
23+
## 如何使用?
24+
25+
应用操作人员信息后,首先,你要在接口参数中,传递 `request: Request`,并作为第一个参数(在 Django,flask 等框架中,这可能很常见)
26+
27+
然后,在执行创建或更新操作时,可通过 `request.user.id` 直接获取操作人员 id,并进行数据库写入
28+
29+
我们之所以没有默认应用此功能,是因为我们不想所有接口重复调用 `request` 参数(作者强迫症)

docs/guide/reference/RBAC.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
title: 权限
3+
---
4+
5+
我们通过两个自定义依赖组件,实现了 RBAC 的轻松集成,在 Java 或其他语言中,常见的方式可能是注解,但在 fastapi 中,依赖是它的亮点,也是核心
6+
7+
## RBAC
8+
9+
RBAC 提供了两种解决方案,第一种【角色菜单】可能更加常见,它可以设置按钮级别的控制规则,另外一种是【Casbin】,它非常灵活,可以通过模型定义多种
10+
控制规则(我认为它很好,性能也很出色)
11+
12+
### 角色菜单
13+
14+
要想实现此 RBAC 调用,涉及到三处相关配置
15+
16+
::: steps
17+
1. 更新 RBAC 鉴权配置
18+
19+
`core/conf.py` 文件中找到以下配置,并更新 `PERMISSION_MODE``role-menu`
20+
21+
```py
22+
# Permission (RBAC)
23+
PERMISSION_MODE: Literal['casbin', 'role-menu'] = 'role-menu'
24+
```
25+
26+
2. 添加接口依赖
27+
28+
只有在接口中参加此依赖时,才能自动应用此鉴权
29+
30+
```py{5-6}
31+
@router.post(
32+
'',
33+
summary='xxx',
34+
dependencies=[
35+
Depends(RequestPermission('sys:api:add')),
36+
DependsRBAC,
37+
],
38+
)
39+
```
40+
41+
3. 在菜单中添加权限标识
42+
43+
我们在接口依赖中可以看到 `sys:api:add` 之类的值,这些值正是对应着菜单中的权限标识,只有它们完全一致,并且用户拥有菜单时,才有权执行操作
44+
:::
45+
46+
### Casbin
47+
48+
Casbin 在 Go web 中应用更加广泛, 我们在最初架构设计时,参考了 go-admin,gin-vue-admin... 等优秀的开源项目,同时引入了
49+
Casbin,它在众多 python web 开源项目中可能是极为罕见的,并且,它的学习成本相对较高,如果你对此感兴趣,可以通过
50+
[Casbin 官网](https://casbin.org/docs/get-started) 进行学习,另外,可参考视频教程 (
51+
[半小时彻底弄懂Casbin基础模型](https://www.bilibili.com/video/BV1qz4y167XP/?spm_id_from=333.999.0.0&vd_source=958c4d7f9243c68a0ec9dcd327bad930)、
52+
[Casbin的代码使用、api调用、自定义比较方法](https://www.bilibili.com/video/BV13r4y1M7AC/?spm_id_from=333.999.0.0&vd_source=958c4d7f9243c68a0ec9dcd327bad930)
53+
54+
55+
通过以上学习之后,我们再来看规则(不学习规则可能是天书),
56+
你可以通过此[编辑器](https://github.com/casbin/casbin-editor)进行规则验证
57+
58+
模型:
59+
60+
```
61+
[request_definition]
62+
r = sub, obj, act
63+
64+
[policy_definition]
65+
p = sub, obj, act
66+
67+
[role_definition]
68+
g = _, _
69+
70+
[policy_effect]
71+
e = some(where (p.eft == allow))
72+
73+
[matchers]
74+
m = g(r.sub, p.sub) && (keyMatch(r.obj, p.obj) || keyMatch3(r.obj, p.obj)) && (r.act == p.act || p.act == "*")
75+
```
76+
77+
p 策略:
78+
79+
- 推荐添加基于角色的访问权限, 需配合添加 g 策略才能真正拥有访问权限,适合配置全局接口访问策略<br>
80+
**格式**: 角色 role + 访问路径 path + 访问方法 method
81+
82+
- 如果添加基于用户的访问权限, 不需配合添加 g 策略就能真正拥有权限,适合配置指定用户接口访问策略<br>
83+
**格式**: 用户 uuid + 访问路径 path + 访问方法 method
84+
85+
g 策略 (**依赖 p 策略**):
86+
87+
- 如果在 p 策略中添加了基于角色的访问权限, 则还需要在 g 策略中添加基于用户组的访问权限, 才能真正拥有访问权限<br>
88+
**格式**: 用户 uuid + 角色 role
89+
90+
- 如果在 p 策略中添加了基于用户的访问权限, 则不添加相应的 g 策略能直接拥有访问权限<br>
91+
但是拥有的不是用户角色的所有权限, 而只是单一的对应的 p 策略所添加的访问权限

docs/guide/reference/code-generation.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,44 @@
22
title: 代码生成
33
---
44

5-
## TODO
5+
> [!TIP]
6+
> 当前版本仅包含后端代码生成
7+
>
8+
> 代码生成器使用 api 调用实现,包含两个模组,设计可能存在缺陷,相关问题请直接提交 issues
9+
10+
> [!WARNING]
11+
> 由于 jinja2 在渲染模版时,文本方式输出可能存在格式问题,所以 `preview` 接口可能无法直观预览代码,这是为前端进行的预设
12+
13+
## 概念
14+
15+
### 业务
16+
17+
包含代码生成的相关配置,详情查看:`generator/model/gen_business.py`
18+
19+
### 模型
20+
21+
包含代码生成所需要的模型列信息,就像正常定义模型列一样,目前支持的功能有限
22+
23+
## 使(食)用
24+
25+
1. 启动后端服务,打开 swagger 文档直接操作
26+
2. 通过第三方 api 调试工具发送接口请求
27+
3. 同时启动前后端,从页面进行操作
28+
29+
接口参数基本都有说明,请注意查看
30+
31+
### F. 纯手动模式
32+
33+
不推荐(手动创建业务接口被标记为「已弃用」)
34+
35+
1. 通过创建业务接口手动添加一项业务数据
36+
2. 通过模型创建接口手动添加模型列
37+
3. 访问 `preview`(预览),`generate`(磁盘写入),`download`(下载)接口,执行后端代码生成相应工作
38+
39+
### S. 自动模式
40+
41+
推荐
42+
43+
1. 访问 `tables` 接口,获取数据库表名列表
44+
2. 通过 `import` 接口,导入数据库已有的数据库表数据,将自动创建业务表数据和模型表数据
45+
3. 访问 `preview`(预览),`generate`(磁盘写入),`download`(下载)接口,执行后端代码生成相应工作

docs/guide/reference/login.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/guide/reference/oauth.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: 授权
3+
---
4+
5+
::: note
6+
通过 JWT 中间件实现全局自动授权
7+
:::
8+
9+
我们编写了自定义的 JWT 授权中间件,使其可以在每次请求发起时,自动调用此中间件实现自动授权,并且,通过 Redis 和 Rust 库对用户信息进行快速缓存,
10+
使其性能影响尽可能降到最低
11+
12+
## 验证码登录
13+
14+
我们提供了数字验证码方式的登录授权接口,登录成功后,JWT 将包含在接口响应信息中
15+
16+
17+
## Swagger 授权
18+
19+
这是一种快捷的授权方式,但仅出于调试目的,在服务启动后,进入 Swagger UI,可通过此调试接口进行快速登录授权(无需验证码)
20+
21+
## OAuth 2.0
22+
23+
这种授权方式通常适用于第三方平台认证登录,第三方授权成功后,将依据第三方平台信息自动创建本地用户并自动授权登录,这一切都是用户无感知的

docs/guide/reference/oauth2.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/guide/reference/permission.md

Lines changed: 0 additions & 27 deletions
This file was deleted.

docs/guide/reference/transaction.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,39 @@
22
title: 事务
33
---
44

5-
## TODO
5+
我们可以通过两种方式实现数据库事务
6+
7+
## session 生成器
8+
9+
这是官方一种比较流行的方法,通过迭代 session 控制隔离,并通过上下文异常进行回滚,最后关闭 session
10+
11+
这种方式应用于接口函数,通过依赖注入实现 session 传递,在 session 应用方面,它被认为是线程安全的
12+
13+
```py{3}
14+
@router.get('')
15+
async def get_pagination_apis(
16+
db: CurrentSession
17+
) -> ResponseModel:
18+
...
19+
```
20+
21+
## `begin()`
22+
23+
这种方式由 SQLAlchemy 官方实现,相对第一种方式来说,更加原生,在线程安全方面,由于同一个接口中,可能存在多次调用,所以没有第一种方式更加严谨,
24+
不过呢,对于此架构来说,它更加符合架构风格
25+
26+
```py{2}
27+
async def create(*, obj: CreateIns) -> None:
28+
async with async_db_session.begin() as db:
29+
await xxx_dao.create(db, obj)
30+
```
31+
32+
## 如何选择?
33+
34+
对于两种事务方法,我们更推荐第二种;
35+
36+
通常情况下,第一种方法我们更多用于分页查询接口,理论上来说,查询接口我们无需使用事务,但由于分页查询我们使用了第三方库,并且,为了尊重
37+
fastapi 官方教程,我们仍将它保留
38+
39+
而第二种,对于无需使用事务的数据库操作,我们只需将 `begin()` 方法去掉,改为 `async with async_db_session() as db:`
40+
即可,这种方式更加灵活,并且也能减少千篇一律的接口参数(纯作者强迫症),同时,它也是 sqlalchemy 2.0+ 的官方推荐使用方法

0 commit comments

Comments
 (0)