Skip to content

Commit 4f3f5eb

Browse files
committed
update docs
1 parent b562020 commit 4f3f5eb

File tree

3 files changed

+185
-65
lines changed

3 files changed

+185
-65
lines changed

docs/backend/reference/conf.md

Lines changed: 79 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ openapi JSON 数据在线地址
4343

4444
## 数据库配置
4545

46-
### `DATABASE_TYPE` <Badge type="info" text="Literal['postgresql', 'mysql']" /> <Badge type="warning" text="env" />
46+
### `DATABASE_TYPE` <Badge type="info" text="Literal['mysql', 'postgresql']" /> <Badge type="warning" text="env" />
4747

4848
数据库类型,仅支持 `postgresql``mysql`,需注意第三方插件兼容性
4949

@@ -79,7 +79,7 @@ openapi JSON 数据在线地址
7979

8080
数据库字符集,仅用于 mysql
8181

82-
### `DATABASE_PK_MODE` <Badge type="info" text="str" />
82+
### `DATABASE_PK_MODE` <Badge type="info" text="Literal['autoincrement', 'snowflake']" />
8383

8484
数据库主键模式,更多详情:[切换主键](./pk.md)
8585

@@ -89,26 +89,64 @@ openapi JSON 数据在线地址
8989

9090
## Redis 配置
9191

92-
### `REDIS_TIMEOUT` <Badge type="info" text="int" /> <Badge type="warning" text="env" />
93-
94-
Socket 读写操作的超时时间和 Redis 建立 TCP 连接时的超时时间
95-
96-
### `REDIS_HOST` <Badge type="info" text="int" />
92+
### `REDIS_HOST` <Badge type="info" text="str" /> <Badge type="warning" text="env" />
9793

9894
Redis 服务器的主机地址
9995

100-
### `REDIS_PORT` <Badge type="info" text="str" />
96+
### `REDIS_PORT` <Badge type="info" text="int" /> <Badge type="warning" text="env" />
10197

10298
Redis 服务器的端口号
10399

104-
### `REDIS_PASSWORD` <Badge type="info" text="int" />
100+
### `REDIS_PASSWORD` <Badge type="info" text="str" /> <Badge type="warning" text="env" />
105101

106102
Redis 认证密码
107103

108-
### `REDIS_DATABASE` <Badge type="info" text="str" />
104+
### `REDIS_DATABASE` <Badge type="info" text="int" /> <Badge type="warning" text="env" />
109105

110106
全局默认使用的 Redis 逻辑数据库索引(0 - 15)
111107

108+
### `REDIS_TIMEOUT` <Badge type="info" text="int" />
109+
110+
Socket 读写操作的超时时间和 Redis 建立 TCP 连接时的超时时间
111+
112+
## 缓存配置
113+
114+
### `CACHE_LOCAL_ENABLED` <Badge type="info" text="bool" />
115+
116+
是否启用本地缓存
117+
118+
### `CACHE_LOCAL_MAXSIZE` <Badge type="info" text="int" />
119+
120+
本地缓存最大容量
121+
122+
### `CACHE_LOCAL_TTL` <Badge type="info" text="int" />
123+
124+
本地缓存过期时长(秒)
125+
126+
### `CACHE_REDIS_TTL` <Badge type="info" text="int" />
127+
128+
Redis 缓存过期时长(秒)
129+
130+
### `CACHE_CONFIG_REDIS_PREFIX` <Badge type="info" text="str" />
131+
132+
系统配置缓存存储到 Redis 时的前缀
133+
134+
### `CACHE_DICT_REDIS_PREFIX` <Badge type="info" text="str" />
135+
136+
字典缓存存储到 Redis 时的前缀
137+
138+
### `CACHE_PUBSUB_CHANNEL` <Badge type="info" text="str" />
139+
140+
缓存失效发布订阅频道
141+
142+
### `CACHE_PUBSUB_RECONNECT_DELAY` <Badge type="info" text="int" />
143+
144+
缓存发布订阅重连延迟(秒)
145+
146+
### `CACHE_PUBSUB_MAX_RECONNECT_ATTEMPTS` <Badge type="info" text="int" />
147+
148+
缓存发布订阅最大重连次数
149+
112150
## Snowflake(雪花算法)
113151

114152
### `SNOWFLAKE_DATACENTER_ID` <Badge type="info" text="int" /> <Badge type="warning" text="env" />
@@ -234,6 +272,10 @@ JWT / RBAC 路由白名单正则模式,从路由头部开始匹配,与之匹
234272

235273
## 登录配置
236274

275+
### `LOGIN_CAPTCHA_ENABLED` <Badge type="info" text="bool" />
276+
277+
是否开启登录验证码
278+
237279
### `LOGIN_CAPTCHA_REDIS_PREFIX` <Badge type="info" text="str" />
238280

239281
登录验证码存储到 Redis 时的前缀
@@ -242,10 +284,6 @@ JWT / RBAC 路由白名单正则模式,从路由头部开始匹配,与之匹
242284

243285
登录验证码过期时长(秒)
244286

245-
### `LOGIN_CAPTCHA_ENABLED` <Badge type="info" text="bool" />
246-
247-
是否开始登录验证码
248-
249287
### `LOGIN_FAILURE_PREFIX` <Badge type="info" text="str" />
250288

251289
登录失败存储到 Redis 时的前缀
@@ -280,10 +318,26 @@ JWT 中间件存储用户信息到 Redis 时的前缀
280318

281319
## 数据权限配置
282320

321+
### `DATA_PERMISSION_MODEL_EXCLUDE` <Badge type="info" text="list[str]" />
322+
323+
排除允许进行数据过滤的 SQLA 模型
324+
283325
### `DATA_PERMISSION_COLUMN_EXCLUDE` <Badge type="info" text="list[str]" />
284326

285327
排除允许进行数据过滤的 SQLA 模型列,例如 id, password 等
286328

329+
### `DATA_PERMISSION_MODEL_TEMPLATE_VARIABLES` <Badge type="info" text="list[dict[str, str]]" />
330+
331+
数据规则模型可用模板变量
332+
333+
### `DATA_PERMISSION_COLUMN_TEMPLATE_VARIABLES` <Badge type="info" text="list[dict[str, str]]" />
334+
335+
数据规则字段可用模板变量
336+
337+
### `DATA_PERMISSION_TEMPLATE_VARIABLES` <Badge type="info" text="list[dict[str, str]]" />
338+
339+
数据规则值可用模板变量
340+
287341
## Socket.IO 配置
288342

289343
### `WS_NO_AUTH_MARKER` <Badge type="info" text="str" />
@@ -426,9 +480,13 @@ JWT 中间件存储用户信息到 Redis 时的前缀
426480

427481
操作日志路径排除,在此配置内的请求地址不会记录操作日志
428482

429-
### `OPERA_LOG_ENCRYPT_KEY_INCLUDE` <Badge type="info" text="list[str]" />
483+
### `OPERA_LOG_REDACT_KEYS` <Badge type="info" text="list[str]" />
484+
485+
脱敏操作日志中的接口请求参数
430486

431-
加密操作日志中的接口请求参数
487+
### `OPERA_LOG_QUEUE_MAXSIZE` <Badge type="info" text="int" />
488+
489+
操作日志队列最大容量
432490

433491
### `OPERA_LOG_QUEUE_BATCH_CONSUME_SIZE` <Badge type="info" text="int" />
434492

@@ -464,18 +522,14 @@ pip 下载最大重试次数
464522

465523
## Grafana 配置
466524

467-
### `GRAFANA_METRICS` <Badge type="info" text="bool" />
525+
### `GRAFANA_METRICS_ENABLE` <Badge type="info" text="bool" />
468526

469527
是否启用 Grafana 套件
470528

471529
::: warning
472530
如果不需要可观测性集成,不建议启用此功能
473531
:::
474532

475-
### `GRAFANA_APP_NAME` <Badge type="info" text="str" />
476-
477-
Grafana 应用名称,通常情况下,不建议修改
478-
479533
### `GRAFANA_OTLP_GRPC_ENDPOINT` <Badge type="info" text="str" />
480534

481535
Grafana OTLP 协议 grpc 地址,用于发送遥测数据
@@ -542,19 +596,11 @@ Google 客户端 ID
542596

543597
Google 客户端密钥
544598

545-
### `OAUTH2_LINUX_DO_CLIENT_ID` <Badge type="info" text="str" /> <Badge type="warning" text="env" />
546-
547-
Linux Do 客户端 ID
548-
549-
### `OAUTH2_LINUX_DO_CLIENT_SECRET` <Badge type="info" text="str" /> <Badge type="warning" text="env" />
550-
551-
Linux Do 客户端密钥
552-
553599
### `OAUTH2_STATE_REDIS_PREFIX` <Badge type="info" text="str" />
554600

555601
OAuth2 状态信息存储到 Redis 时的前缀
556602

557-
### `OAUTH2_STATE_EXPIRE_SECONDS` <Badge type="info" text="str" />
603+
### `OAUTH2_STATE_EXPIRE_SECONDS` <Badge type="info" text="int" />
558604

559605
OAuth2 状态信息存储到 Redis 时的过期时间(秒)
560606

@@ -566,10 +612,6 @@ GitHub 重定向地址,必须与 GitHub OAuth Apps 配置保持一致
566612

567613
Google 重定向地址,必须与 Google OAuth 2.0 客户端配置保持一致
568614

569-
### `OAUTH2_LINUX_DO_REDIRECT_URI` <Badge type="info" text="str" />
570-
571-
Linux Do 重定向地址,必须与 Linux Do Connect 配置保持一致
572-
573615
### `OAUTH2_FRONTEND_LOGIN_REDIRECT_URI` <Badge type="info" text="str" />
574616

575617
登陆成功后,重定向到前端的地址
@@ -580,11 +622,11 @@ Linux Do 重定向地址,必须与 Linux Do Connect 配置保持一致
580622

581623
## 插件:Email
582624

583-
### `EMAIL_USERNAME` <Badge type="info" text="str" />
625+
### `EMAIL_USERNAME` <Badge type="info" text="str" /> <Badge type="warning" text="env" />
584626

585627
电子邮箱发件用户
586628

587-
### `EMAIL_PASSWORD` <Badge type="info" text="str" />
629+
### `EMAIL_PASSWORD` <Badge type="info" text="str" /> <Badge type="warning" text="env" />
588630

589631
电子邮箱发件用户密码
590632

@@ -606,4 +648,4 @@ Linux Do 重定向地址,必须与 Linux Do Connect 配置保持一致
606648

607649
### `EMAIL_CAPTCHA_EXPIRE_SECONDS` <Badge type="info" text="int" />
608650

609-
电子邮件验证码缓存时长(秒)
651+
电子邮件验证码缓存时长(秒)

docs/backend/reference/data-permission.md

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,110 @@ SQL 语句拼接进行实现的,而这些固定权限,直接写死了数据
2222

2323
## 内置方案
2424

25-
有没有一种更加灵活的方案呢,答案是,当然有,目前,我们在 fba 中实现的正是超灵活方案,但相比于常见方案来讲,配置会更加复杂
25+
fba 内置了一套灵活的数据权限方案,通过数据范围(DataScope)+ 数据规则(DataRule)的组合,实现动态、可配置的数据过滤,无需业务表满足特定字段要求
2626

27-
你可以直接查看代码源文件 `backend/common/security/permission.py`
28-
,它与常规方案使用近乎相同的方式实现数据过滤,但由于其复杂性,下面,我们将通过视频进行讲解:
27+
### 架构设计
2928

30-
@[bilibili](BV13hioY1EQU)
29+
数据权限通过以下关系链实现:
30+
31+
```
32+
用户 → 角色 → 数据范围 → 数据规则
33+
```
34+
35+
### 数据范围
36+
37+
数据范围(DataScope)是数据规则的逻辑分组,一个数据范围可以包含多条数据规则
38+
39+
### 数据规则
40+
41+
数据规则(DataRule)定义具体的过滤条件,每条规则由模型、字段、运算符、表达式和值组成
42+
43+
### 模板变量
44+
45+
为了适应动态场景,数据规则支持模板变量,在运行时自动解析为实际值
46+
47+
#### 模型模板变量
48+
49+
用于数据规则的 `model` 字段
50+
51+
| 变量 | 说明 |
52+
|-----------|--------|
53+
| `__ALL__` | 匹配所有模型 |
54+
55+
#### 字段模板变量
56+
57+
用于数据规则的 `column` 字段
58+
59+
| 变量 | 说明 |
60+
|------------------|-----------------------------|
61+
| `__dept_id__` | 部门 ID(解析为模型的 `dept_id` 字段) |
62+
| `__created_by__` | 创建者(解析为模型的 `created_by` 字段) |
63+
64+
#### 值模板变量
65+
66+
用于数据规则的 `value` 字段
67+
68+
| 变量 | 说明 |
69+
|--------------|-------------|
70+
| `${user_id}` | 当前登录用户 ID |
71+
| `${dept_id}` | 当前登录用户部门 ID |
72+
| `${now}` | 当前时间 |
73+
74+
### 使用
75+
76+
#### 接口依赖注入
77+
78+
通过 `DataPermissionFilter` 类在接口中注入数据权限过滤条件,传入需要进行数据过滤的模型类
79+
80+
```python
81+
from backend.common.security.permission import DataPermissionFilter
82+
83+
@router.get('')
84+
async def get_dept_tree(
85+
db: CurrentSession,
86+
data_filter: Annotated[ColumnElement[bool], Depends(DataPermissionFilter(Dept))], # [!code highlight]
87+
) -> ResponseSchemaModel[list[GetDeptTree]]:
88+
dept = await dept_service.get_tree(db=db, data_filter=data_filter, ...)
89+
return response_base.success(data=dept)
90+
```
91+
92+
#### CRUD 数据过滤
93+
94+
在 CRUD 层中,将 `data_filter` 作为查询过滤条件传入
95+
96+
```python
97+
async def get_all(
98+
self,
99+
db: AsyncSession,
100+
data_filter: ColumnElement[bool], # [!code highlight]
101+
...
102+
) -> Sequence[Dept]:
103+
return await self.select_models_order(db, 'sort', 'asc', data_filter, **filters)
104+
```
105+
106+
### 过滤流程
107+
108+
```
109+
用户请求 API
110+
111+
FastAPI 解析 Depends(DataPermissionFilter)
112+
113+
filter_data_permission() 执行
114+
├── 超级管理员 → 无过滤,查看所有数据
115+
├── 角色 is_filter_scopes=False → 无过滤
116+
├── 无数据规则 → 无过滤
117+
└── 存在数据规则 → 构建 SQLAlchemy 条件
118+
├── 解析模型模板变量(__ALL__ 等)
119+
├── 解析字段模板变量(__dept_id__ 等)
120+
├── 解析值模板变量(${user_id} 等)
121+
├── 根据表达式构建条件(==, !=, >, in 等)
122+
└── 根据运算符组合条件(AND / OR)
123+
124+
返回 ColumnElement[bool] 过滤条件
125+
126+
CRUD 层使用过滤条件查询数据库
127+
```
128+
129+
### 视频讲解
130+
131+
@[bilibili](BV13hioY1EQU)

docs/backend/reference/timezone.md

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,4 @@ sqlalchemy 和所有 python mysql 驱动默认都不处理 mysql 时区信息,
4848
更具体的:[sqlalchemy/1985](https://github.com/sqlalchemy/sqlalchemy/issues/1985)
4949
:::
5050

51-
为此,我们使用了第 2 种解决方案,并创建了自定义 TimeZone 类型
52-
53-
```python
54-
class TimeZone(TypeDecorator[datetime]):
55-
"""PostgreSQL、MySQL 兼容性时区感知类型"""
56-
57-
impl = DateTime(timezone=True)
58-
cache_ok = True
59-
60-
@property
61-
def python_type(self) -> type[datetime]:
62-
return datetime
63-
64-
def process_bind_param(self, value: datetime | None, dialect) -> datetime | None: # noqa: ANN001
65-
if value is not None and value.utcoffset() != timezone.now().utcoffset():
66-
# TODO 处理夏令时偏移
67-
value = timezone.from_datetime(value)
68-
return value
69-
70-
def process_result_value(self, value: datetime | None, dialect) -> datetime | None: # noqa: ANN001
71-
if value is not None and value.tzinfo is None:
72-
value = value.replace(tzinfo=timezone.tz_info)
73-
return value
74-
```
51+
为此,我们使用了第 2 种解决方案,并创建了自定义 TimeZone 类型,更多详情请查看:`backend/common/model.py`

0 commit comments

Comments
 (0)