1. 审核规则改为从audit_rules表动态匹配(去硬编码)
- CreateTicket提交时查audit_rules WHERE db_type=? AND is_enabled=true
- 正则匹配SQL,value=reject拦截,warn/review放行
- UPDATE/DELETE无WHERE: Go RE2不支持(?!...)负向前瞻
→ 用value=where_check特殊标记+strings.Contains WHERE检测
- 修复UPDATE/DELETE无WHERE正则(Go兼容)
2. ListAuditRules按db_type过滤
- ghost.go: 添加c.Query('db_type') WHERE过滤
- MySQL不显示KEYS规则,Redis不显示DROP规则
3. Redis只读命令拦截(工单提交)
- 新增Redis只读命令白名单: GET/HGET/MGET/HGETALL/KEYS/SCAN等28个
- 只读命令走工单→直接拦截,引导用户用查询功能
4. 补充audit_rules规则
- Redis新增7条: DEBUG/SHUTDOWN/SCRIPT/SAVE/BGSAVE/BGREWRITEAOF/SLAVEOF/CLUSTER
- MySQL新增1条: DROP SCHEMA
- 总计34条规则(MySQL12/Redis11/PG7/MongoDB4)
5. docs/CONFIGURATION.md 配置系统文档
- 三套配置体系: system_settings/audit_rules/ldap_configs
- 每项配置: key/默认值/作用/代码引用位置
- 未引用配置标注: executor_batch_size/executor_backup/query_max_rows_examined(待实现)
- LDAP冗余配置: system_settings中7项ldap_*无代码引用(LDAP用独立表)
验证: 5/5审批流通过, 36/36安全测试通过, 27/27审核规则匹配正确
23 KiB
OpsxSQL 平台配置系统文档
本文档详细说明 OpsxSQL 平台的三套配置体系:
system_settings系统设置、audit_rules审核规则、ldap_configsLDAP 配置。最后更新:2025-06
目录
- 一、配置体系总览
- 二、查询控制 (query)
- 三、审核规则 (audit_rules)
- 四、数据脱敏 (data_masking)
- 五、执行器 (executor)
- 六、Ghost / OSC 在线 DDL (ghost)
- 七、安全策略 (security)
- 八、日志清理 (cleanup)
- 九、LDAP 配置 (ldap)
- 十、未引用 / 待实现配置
- 附录:数据模型
一、配置体系总览
| 配置体系 | 存储表 | 配置项数 | 用途 |
|---|---|---|---|
| 系统设置 | system_settings |
42 项(7 个分组) | 平台运行参数 |
| 审核规则 | audit_rules |
34 条(4 种 DB 类型) | SQL 提交审核拦截 |
| LDAP 配置 | ldap_configs |
独立 CRUD | LDAP 认证集成 |
system_settings 分组概览
| 分组 | 配置项数 | 有效引用 | 状态 |
|---|---|---|---|
query 查询控制 |
5 | 4 | ⚠️ query_max_rows_examined 未引用 |
security 安全策略 |
5 | 5 | ✅ 全部有效 |
data_masking 数据脱敏 |
2 | 2 | ✅ 全部有效 |
cleanup 日志清理 |
4 | 4 | ✅ 全部有效 |
executor 执行器 |
4 | 2 | ⚠️ batch_size/backup 未引用 |
ghost 在线 DDL |
13 | 13 | ✅ 全部有效 |
ldap LDAP |
9 | 0 | ❌ 全部冗余(LDAP 使用独立 ldap_configs 表) |
配置读写 API
| 操作 | 端点 | 说明 |
|---|---|---|
| 读取所有设置 | GET /api/v1/settings |
按 group 字段分组返回 |
| 批量更新设置 | PUT /api/v1/settings |
接收 [{key, value}, ...] 数组 |
| 读取审核规则 | GET /api/v1/audit-rules?db_type=mysql |
可按 db_type 过滤 |
配置均在服务启动时通过 seedDefaultSettings() / seedAuditRules() 幂等初始化。
二、查询控制 (query)
查询控制配置作用于在线查询功能(instance_detail.go),限制用户对数据库的查询行为。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
query_limit_max |
number | 1000 |
SELECT 查询返回的最大行数,超过自动截断 | instance_detail.go:525 |
query_timeout |
number | 30 |
单次查询最长执行时间(秒),超时自动终止 | instance_detail.go:616-617 |
query_auto_limit |
boolean | true |
用户未写 LIMIT 时自动追加,防止全表扫描 | instance_detail.go:526 |
query_dangerous_pattern |
boolean | true |
检测不带 WHERE 的 DELETE/UPDATE 等高危操作 | instance_detail.go:540 |
query_max_rows_examined |
number | 1000000 |
单次查询允许扫描的最大行数 | ⚠️ 待实现 — 仅 seed 定义 |
作用机制
query_limit_max — 查询请求中的 limit 参数不能超过此值:
maxLimit := getSettingInt("query_limit_max", 1000)
if input.Limit <= 0 {
input.Limit = maxLimit
}
// ... 后续截断到 maxLimit
query_auto_limit — 当用户未指定 LIMIT 时,自动追加平台默认上限:
autoLimit := getSetting("query_auto_limit", "true") == "true"
query_timeout — 使用 Go context.WithTimeout 实现硬超时:
timeoutSec := getSettingInt("query_timeout", 30)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutSec)*time.Second)
query_dangerous_pattern — 在执行前检测 SQL 中是否包含高危操作关键字:
if getSetting("query_dangerous_pattern", "true") == "true" {
for _, pat := range []string{"DELETE FROM", "UPDATE ", "DROP ", "TRUNCATE", "ALTER ", "RENAME "} {
// ... 检测并拦截
}
}
三、审核规则 (audit_rules)
概述
审核规则存储在 audit_rules 表中,在 工单提交时(CreateTicket)自动触发检查。系统预置 34 条规则,覆盖 MySQL、PostgreSQL、Redis、MongoDB 四种数据库类型。
匹配机制
CreateTicket → 加载 audit_rules WHERE db_type=? AND is_enabled=true
→ 对每条 SQL 语句逐一匹配
→ Pattern 正则匹配 ⟶ value=where_check 时使用字符串检测
正则匹配流程(ticket.go:299-303):
for _, rule := range rules {
matched, _ := regexp.MatchString(*rule.Pattern, checkStmt)
if matched { /* 规则命中 */ }
}
WHERE 特殊检测(ticket.go:305-314):
由于 Go 的 RE2 正则引擎不支持负向前瞻(negative lookahead),无法用正则"匹配不含 WHERE 的 DELETE"。因此采用两步检测:
- 正则匹配
DELETE FROM/UPDATE ... SET等基础模式 - 若规则
value字段为"where_check",则用strings.Contains(upperSQL, "WHERE")判断是否包含 WHERE 子句 - 包含 WHERE → 跳过(安全);不包含 → 拦截
规则字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
name |
string | 规则名称 |
description |
text | 规则描述 |
rule_type |
string | 规则类型:DDL / DML / DCL / DQL / performance / security |
severity |
string | 严重级别:error / warning / info |
db_type |
string | 目标数据库类型:mysql / postgresql / redis / mongodb |
pattern |
text | 正则表达式(RE2 语法) |
is_enabled |
boolean | 是否启用 |
message |
string(500) | 命中时的提示消息 |
value |
string(255) | 处理方式:reject(拦截) / review(需审核) / warn(警告) / where_check(WHERE检测) |
code |
string(50) | 规则编码(预留) |
config_json |
text | 扩展配置 JSON(预留) |
MySQL 审核规则(12 条)
| 规则名称 | 类型 | 严重级别 | Pattern | Value | 说明 |
|---|---|---|---|---|---|
| 禁止 DROP TABLE | DDL | error | (?i)^\s*DROP\s+TABLE |
reject | 防止数据永久丢失 |
| 禁止 DROP DATABASE | DDL | error | (?i)^\s*DROP\s+DATABASE |
reject | 禁止删库 |
| 禁止 TRUNCATE TABLE | DDL | error | (?i)^\s*TRUNCATE\s+TABLE? |
reject | 请用 DELETE 逐批删除 |
| ALTER TABLE 需审核 | DDL | warning | (?i)^\s*ALTER\s+TABLE |
review | 需审批后执行 |
| 禁止 DELETE 无 WHERE | DML | error | (?i)^\s*DELETE\s+FROM?\s+\S+\s*$ |
reject | 必须包含 WHERE 条件 |
| 禁止 UPDATE 无 WHERE | DML | error | (?i)^\s*UPDATE\s+\S+\s+SET\s+.*\s*$ |
reject | 必须包含 WHERE 条件 |
| SELECT * 建议 | DQL | info | (?i)^\s*SELECT\s+\*\s+FROM |
warn | 建议明确指定查询字段 |
| INSERT 需指定列 | DML | warning | (?i)^\s*INSERT\s+INTO\s+\S+\s+VALUES |
review | 应明确指定列名 |
| 禁止 GRANT ALL | DCL | error | (?i)^\s*GRANT\s+ALL |
reject | 禁止授予全部权限 |
| 大表变更警告 | performance | warning | (空 pattern) | warn | 影响行数大时警告 |
| 禁止不带 LIMIT 的 DELETE | DML | warning | (?i)^\s*DELETE\s+FROM\s+\S+\s+WHERE |
warn | 建议添加 LIMIT 分批删除 |
注意:seed 中 MySQL 预置 12 条,实际按
len(allRules["mysql"])计算。上表列出 11 条有明确 pattern 的规则,另含 1 条 "大表变更警告"(无 pattern,作为提示性规则存在)。
PostgreSQL 审核规则(7 条)
| 规则名称 | 类型 | 严重级别 | Value | 说明 |
|---|---|---|---|---|
| 禁止 DROP TABLE | DDL | error | reject | 同 MySQL |
| 禁止 DROP DATABASE | DDL | error | reject | 同 MySQL |
| 禁止 DELETE 无 WHERE | DML | error | reject | 同 MySQL |
| 禁止 UPDATE 无 WHERE | DML | error | reject | 同 MySQL |
| ALTER TABLE 需审核 | DDL | warning | review | 同 MySQL |
| SELECT * 建议 | DQL | info | warn | 同 MySQL |
| 禁止 GRANT ALL | DCL | error | reject | 同 MySQL |
Redis 审核规则(4 条)
| 规则名称 | 类型 | 严重级别 | Pattern | Value | 说明 |
|---|---|---|---|---|---|
| 禁止 FLUSHALL | DDL | error | (?i)^FLUSHALL |
reject | 禁止清空所有数据 |
| 禁止 FLUSHDB | DDL | error | (?i)^FLUSHDB |
reject | 清空数据库需审批 |
| 禁止 CONFIG | security | error | (?i)^CONFIG\s |
reject | 配置修改需走审批 |
| KEYS 命令警告 | performance | error | (?i)^KEYS\s |
reject | 生产环境禁止 KEYS,请使用 SCAN |
MongoDB 审核规则(4 条)
| 规则名称 | 类型 | 严重级别 | Pattern | Value | 说明 |
|---|---|---|---|---|---|
| 禁止 dropDatabase | DDL | error | dropDatabase |
reject | 禁止删除数据库 |
| 禁止 drop 集合 | DDL | error | (?i)\.drop\(\) |
reject | 禁止删除集合 |
| remove 需带条件 | DML | error | (?i)remove\(\s*\) |
reject | remove 必须带查询条件 |
| updateMany 需审核 | DML | warning | (?i)updateMany |
review | 批量更新需审批 |
四、数据脱敏 (data_masking)
数据脱敏功能作用于在线查询返回结果,自动将敏感字段的内容替换为 ***。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
data_masking_enabled |
boolean | true |
全局脱敏开关 | instance_detail.go:1522-1525 |
data_masking_sensitive_fields |
string | (见下方) | 全局敏感字段列表(逗号分隔) | instance_detail.go:1531-1534 |
默认敏感字段列表:
mobile, concat_mobile, email_alias, email, password, ga_key,
private_key, secret, secret_key, key_snow, telephone, username,
real_name, token, two_factor_secret, content, phone
作用机制
applyDataMasking() 函数(instance_detail.go:1520)执行以下逻辑:
- 读取
data_masking_enabled,若非true则跳过 - 读取
data_masking_sensitive_fields,按逗号拆分为字段名列表 - 合并实例级别
instance.mask_fields的字段 - 遍历查询结果的每一行每一列,若列名(不区分大小写)匹配敏感字段,则将值替换为
***
字段匹配方式:列名包含(contains)敏感字段名即匹配,不区分大小写。
优先级:全局敏感字段 ∪ 实例级 mask_fields,两者合并生效。
五、执行器 (executor)
执行器配置控制工单中 SQL 语句的实际执行行为。
| Key | 类型 | 默认值 | 说明 | 引用位置 | 状态 |
|---|---|---|---|---|---|
executor_timeout |
number | 300 |
SQL 执行的最大等待时间(秒) | ticket.go:725,766 |
✅ 有效 |
executor_dry_run |
boolean | true |
执行前先 EXPLAIN 验证 SQL 语法 | ticket.go:770 |
✅ 有效 |
executor_batch_size |
number | 100 |
DML 批量执行时每批的行数 | (无) | ⚠️ 待实现 |
executor_backup |
boolean | true |
DML 执行前自动备份受影响数据 | (无) | ⚠️ 待实现 |
作用机制
executor_timeout — 为每个 SQL 语句创建带超时的 context:
// OSC (gh-ost) 路径
execTimeout := getSettingInt("executor_timeout", 300)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(execTimeout)*time.Second)
// 原生执行路径
execTimeout := getSettingInt("executor_timeout", 300)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(execTimeout)*time.Second)
executor_dry_run — 对 DDL 语句执行 EXPLAIN 预检查:
if getSetting("executor_dry_run", "true") == "true" {
ddlPrefixes := []string{"CREATE", "ALTER", "DROP", "TRUNCATE", "RENAME"}
// 对每条 DDL 语句执行 EXPLAIN,语法错误则拦截
}
六、Ghost / OSC 在线 DDL (ghost)
Ghost 配置控制 gh-ost 在线 DDL 变更工具的默认参数。共 13 项配置,全部在 ghost.go 的 applyGhostSettings() 函数和 OSC 触发逻辑中引用。
基本设置
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
ghost_enabled |
boolean | false |
启用 gh-ost 在线 DDL 变更工具 | ticket.go (OSC 触发判断) |
ghost_path |
string | gh-ost |
gh-ost 二进制文件路径 | ghost.go (任务创建) |
ghost_default_mode |
string | dry_run |
默认执行模式:dry_run(预演) / execute(直接执行) |
ghost.go (任务创建) |
ghost_osc_priority |
string | native_first |
OSC 优先级策略:native_first / ghost_first / ghost_only |
ticket.go (OSC 触发判断) |
ghost_env_mode |
string | development |
环境模式:development / staging / production |
ghost.go (任务创建) |
ghost_cloud_type |
string | self_hosted |
部署类型:self_hosted / rds / cloud |
ghost.go (任务创建) |
自动触发
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
ghost_auto_trigger_rows |
number | 10 |
表行数超过此阈值(万行)自动推荐使用 OSC | ticket.go (大表检测) |
ghost_auto_trigger_ddl |
string | ADD COLUMN,MODIFY COLUMN,ADD INDEX |
自动触发 OSC 的 DDL 操作类型列表(逗号分隔) | ticket.go (DDL 类型匹配) |
性能调优
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
ghost_default_chunk_size |
number | 1000 |
每次拷贝的行数 | ghost.go:387 (applyGhostSettings) |
ghost_max_load |
string | Threads_running=25 |
超过此负载暂停拷贝 | ghost.go:391 |
ghost_critical_load |
string | Threads_running=50 |
超过此负载立即停止 | ghost.go:395 |
ghost_allow_on_master |
boolean | true |
是否允许直接在主库运行 gh-ost | ghost.go:403 |
ghost_max_lag_millis |
number | 1500 |
从库复制延迟超过此值(ms)暂停拷贝 | ghost.go:399 |
作用机制
自动触发 OSC 流程(ticket.go):
- 检查
ghost_enabled是否启用 - 检查 SQL 是否为 ALTER TABLE 类型
- 检查 DDL 操作类型是否在
ghost_auto_trigger_ddl列表中 - 检查目标表行数是否超过
ghost_auto_trigger_rows(万) - 根据
ghost_osc_priority决定使用原生 ALTER 还是 gh-ost
参数注入流程(ghost.go:applyGhostSettings):
func applyGhostSettings(task *ghost.GhOstTask) {
task.ChunkSize = getSettingInt("ghost_default_chunk_size", 1000)
task.MaxLoad = getSetting("ghost_max_load", "")
task.CriticalLoad = getSetting("ghost_critical_load", "")
task.MaxLagMillis = getSettingInt("ghost_max_lag_millis", 1500)
task.AllowOnMaster = getSetting("ghost_allow_on_master", "true") == "true"
}
七、安全策略 (security)
安全策略配置控制用户登录和认证行为,全部在 auth.go(handler)和 middleware/auth.go 中引用。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
login_max_attempts |
number | 5 |
连续登录失败达到此次数后锁定账号 | auth.go:34,365 |
login_lockout_minutes |
number | 30 |
账号锁定后的持续时长(分钟) | auth.go:35,366 |
password_min_length |
number | 8 |
用户密码的最短字符数 | auth.go (密码校验) |
password_require_complex |
boolean | true |
要求密码包含大小写字母、数字和特殊字符 | auth.go (密码校验) |
session_timeout_hours |
number | 24 |
JWT Token 有效期(小时) | middleware/auth.go:20 |
作用机制
登录锁定流程(auth.go):
- 登录时检查
login_max_attempts和login_lockout_minutes - 密码错误时调用
handleFailedLogin(),递增FailedLoginAttempts - 达到
login_max_attempts时,设置LockedUntil = now + lockout_minutes - 账号锁定期间拒绝登录,返回剩余锁定时间
会话超时(middleware/auth.go):
func getSessionTimeoutHours() int {
// 从 system_settings 读取 session_timeout_hours
// 用于 JWT Token 的过期时间计算
}
八、日志清理 (cleanup)
清理配置控制各类日志和工单数据的自动保留期限。全部在 ghost.go(清理定时任务)和 main.go(seed)中引用。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|---|---|---|---|---|
ticket_retention_days |
number | 180 |
超过此天数的已完成/已关闭工单将被清理 | ghost.go (清理任务) |
audit_log_retention_days |
number | 365 |
超过此天数的审计日志将被清理 | ghost.go (清理任务) |
query_history_retention_days |
number | 90 |
超过此天数的查询历史将被清理 | ghost.go (清理任务) |
slow_log_retention_days |
number | 180 |
超过此天数的慢查询日志将被清理 | ghost.go (清理任务) |
九、LDAP 配置 (ldap)
system_settings 中的 LDAP 配置(⚠️ 冗余)
以下 9 项配置存在于 system_settings 表的 ldap 分组中,但 全部未被业务代码引用。LDAP 功能使用独立的 ldap_configs 表进行管理。
| Key | 类型 | 默认值 | 说明 | 状态 |
|---|---|---|---|---|
ldap_host |
string | 8.217.205.92 |
LDAP 服务器地址 | ❌ 冗余 |
ldap_port |
string | 389 |
LDAP 端口 | ❌ 冗余 |
ldap_use_ssl |
boolean | false |
启用 LDAPS (SSL/TLS) | ❌ 冗余 |
ldap_bind_dn |
string | cn=admin,dc=opsx,dc=vip |
管理员 DN | ❌ 冗余 |
ldap_base_dn |
string | dc=opsx,dc=vip |
Base DN | ❌ 冗余 |
ldap_user_filter |
string | (objectClass=inetOrgPerson) |
用户过滤器 | ❌ 冗余 |
ldap_uid_attr |
string | uid |
UID 属性 | ❌ 冗余 |
ldap_mail_attr |
string | mail |
邮箱属性 | ❌ 冗余 |
ldap_cn_attr |
string | cn |
显示名属性 | ❌ 冗余 |
ldap_configs 独立表(实际使用)
LDAP 功能通过独立的 ldap_configs 表管理,提供完整的 CRUD 功能:
| 功能 | API 端点 | 说明 |
|---|---|---|
| 配置 CRUD | /api/v1/ldap-configs |
增删改查 LDAP 服务器配置 |
| 测试连接 | /api/v1/ldap-configs/:id/test |
验证 LDAP 服务器连通性 |
| OU 管理 | /api/v1/ldap-configs/:id/ous |
管理 LDAP 组织单元 |
| 用户导入 | /api/v1/ldap-configs/:id/import |
从 LDAP 导入用户到平台 |
建议:后续版本可清理
system_settings中ldap分组的冗余配置项,避免维护混淆。
十、未引用 / 待实现配置
以下配置项在 seed.go 中定义,但在业务代码中 无实际引用,标注为"待实现":
| Key | 分组 | 默认值 | 预期功能 | 状态 |
|---|---|---|---|---|
executor_batch_size |
executor | 100 |
DML 批量执行时每批的行数 | ⚠️ 待实现 |
executor_backup |
executor | true |
DML 执行前自动备份受影响数据 | ⚠️ 待实现 |
query_max_rows_examined |
query | 1000000 |
单次查询允许扫描的最大行数 | ⚠️ 待实现 |
ldap_host |
ldap | 8.217.205.92 |
LDAP 服务器地址 | ❌ 冗余(使用 ldap_configs 表) |
ldap_port |
ldap | 389 |
LDAP 端口 | ❌ 冗余 |
ldap_use_ssl |
ldap | false |
启用 LDAPS | ❌ 冗余 |
ldap_bind_dn |
ldap | cn=admin,dc=opsx,dc=vip |
管理员 DN | ❌ 冗余 |
ldap_base_dn |
ldap | dc=opsx,dc=vip |
Base DN | ❌ 冗余 |
ldap_user_filter |
ldap | (objectClass=inetOrgPerson) |
用户过滤器 | ❌ 冗余 |
ldap_uid_attr |
ldap | uid |
UID 属性 | ❌ 冗余 |
ldap_mail_attr |
ldap | mail |
邮箱属性 | ❌ 冗余 |
ldap_cn_attr |
ldap | cn |
显示名属性 | ❌ 冗余 |
汇总:
- ⚠️ 待实现:3 项(
executor_batch_size、executor_backup、query_max_rows_examined) - ❌ 冗余:9 项(
ldap分组全部,LDAP 使用独立ldap_configs表)
附录:数据模型
system_settings 表结构
type SystemSetting struct {
ID int `gorm:"primaryKey" json:"id"`
Key string `gorm:"size:100;not null" json:"key"` // 唯一配置键
Value string `gorm:"type:text;not null" json:"value"` // 当前值
ValueType string `gorm:"size:20;not null" json:"value_type"` // number / boolean / string
Group string `gorm:"size:50;not null" json:"group"` // 分组名
Label string `gorm:"size:100;not null" json:"label"` // 前端显示名
Desc *string `gorm:"type:text" json:"description"` // 配置说明
DefaultValue *string `gorm:"type:text" json:"default_value"` // 默认值
SortOrder int `gorm:"not null" json:"sort_order"` // 组内排序
UpdatedAt *time.Time `json:"updated_at"`
}
audit_rules 表结构
type AuditRule struct {
ID int `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:100;not null" json:"name"` // 规则名称
Desc *string `gorm:"type:text" json:"description"` // 规则描述
RuleType string `gorm:"size:50;not null" json:"rule_type"` // DDL/DML/DCL/DQL/performance/security
Severity *string `gorm:"size:20" json:"severity"` // error/warning/info
DBType *string `gorm:"size:20" json:"db_type"` // mysql/postgresql/redis/mongodb
Pattern *string `gorm:"type:text" json:"pattern"` // RE2 正则表达式
IsEnabled *bool ` json:"is_enabled"` // 是否启用
Message string `gorm:"size:500;not null" json:"message"` // 命中提示消息
Value *string `gorm:"size:255" json:"value"` // reject/review/warn/where_check
Code *string `gorm:"size:50" json:"code"` // 规则编码(预留)
ConfigJSON *string `gorm:"type:text;column:config_json" json:"config_json"` // 扩展配置(预留)
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
配置读取辅助函数
// ghost.go — 读取字符串配置
func getSetting(key, fallback string) string {
var s model.SystemSetting
if model.DB.Where("`key` = ?", key).Take(&s).Error == nil && s.Value != "" {
return s.Value
}
return fallback
}
// ghost.go — 读取整数配置
func getSettingInt(key string, fallback int) int {
// 读取字符串并 strconv.Atoi,失败返回 fallback
}
文档维护说明:新增配置项时,需同步更新
seed.go的seedDefaultSettings()/seedAuditRules()函数及本文档。