系统设置迁入后台:站点地址 / OAuth 凭据 / R2 存储 / 管理员账号,保存即生效无需重启
- 生效规则统一为「后台填了用后台的,没填回落环境变量」,老部署不改 env 照常跑 - config.Resolver:短缓存解析有效配置,存储后端按配置签名热重建;后台保存主动失效 - 秘密项(client secret / bot token / R2 密钥 / 管理员密码)接口永不回显明文, 只报「是否已配置、来自哪里」;留空保存 = 保持现值 - 管理员密码 bcrypt 入库,DB 哈希优先、显式设置的 env 密码作解锁后路; 后台改过密码后 admin/admin 开发模式立即失效 - 设置页新增「登录与存储」标签,基础信息加站点地址;秘密项带来源提示 - 监听地址 / 数据库 / 目录 / ONE_SECRET / Passkey 仍留环境变量(启动期依赖)
This commit is contained in:
1 parent
bf3ce934dd
commit
e68400b389
23 files changed
+957
-126
No files matched your search
@@ -226,6 +226,26 @@ func (s *Store) seedSettings() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSettingsMap 返回 settings 表的原始 KV。后台设置页用它判断每个
|
||||
// 配置项的来源(DB 有值 / 回落环境变量)——这个信息在解析后的
|
||||
// model.Settings 里已经丢了(空串既可能是「没配」也可能是「回落 env」)。
|
||||
func (s *Store) GetSettingsMap() (map[string]string, error) {
|
||||
rows, err := s.db.Query(s.db.Q(`SELECT key, value FROM settings`))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
m := map[string]string{}
|
||||
for rows.Next() {
|
||||
var k, v string
|
||||
if err := rows.Scan(&k, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
return m, rows.Err()
|
||||
}
|
||||
|
||||
// ---------- settings ----------
|
||||
|
||||
func (s *Store) GetSettings() (model.Settings, error) {
|
||||
@@ -272,6 +292,21 @@ func settingsFromMap(m map[string]string) model.Settings {
|
||||
st.CustomJS = m["custom_js"]
|
||||
st.SocialLinks = decodeSocialLinks(m["social_links"])
|
||||
st.AuthorAvatarKey = m["owner_avatar_key"]
|
||||
// 从环境变量迁进后台的系统设置(DB 值优先,空值由 config.Overlay 回落 env)
|
||||
st.SiteURL = strings.TrimSpace(m["site_url"])
|
||||
st.GitHubClientID = strings.TrimSpace(m["github_client_id"])
|
||||
st.GoogleClientID = strings.TrimSpace(m["google_client_id"])
|
||||
st.TelegramBot = strings.TrimSpace(m["telegram_bot"])
|
||||
st.AdminUsername = strings.TrimSpace(m["admin_username"])
|
||||
st.UploadsPublicBase = strings.TrimRight(strings.TrimSpace(m["uploads_public_base"]), "/")
|
||||
st.S3Endpoint = strings.TrimSpace(m["s3_endpoint"])
|
||||
st.R2Bucket = strings.TrimSpace(m["r2_bucket"])
|
||||
st.R2AccessKey = m["r2_access_key"]
|
||||
st.R2SecretKey = m["r2_secret_key"]
|
||||
st.GitHubClientSecret = m["github_client_secret"]
|
||||
st.GoogleClientSecret = m["google_client_secret"]
|
||||
st.TelegramToken = m["telegram_bot_token"]
|
||||
st.AdminPasswordHash = m["admin_password_hash"]
|
||||
// 开关类:'1' / 'true' 都算开,其余(含空)算关
|
||||
st.CommentsEnabled = m["comments_enabled"] == "1" || strings.EqualFold(m["comments_enabled"], "true")
|
||||
st.CommentsReview = m["comments_review"] == "1" || strings.EqualFold(m["comments_review"], "true")
|
||||
@@ -462,6 +497,17 @@ func (s *Store) UpdateSettings(st model.Settings) error {
|
||||
// 开关统一存 '1' / '0'。
|
||||
"comments_enabled": b2s(st.CommentsEnabled),
|
||||
"comments_review": b2s(st.CommentsReview),
|
||||
// 从环境变量迁进后台的系统设置(非秘密项)。秘密项不在这里写——
|
||||
// 它们经过 model.Settings 的 json:"-" 反序列化永远是空串,
|
||||
// 全量替换会把配置清掉;改秘密走 admin settings PUT 的 secrets 字段。
|
||||
"site_url": strings.TrimSpace(st.SiteURL),
|
||||
"github_client_id": strings.TrimSpace(st.GitHubClientID),
|
||||
"google_client_id": strings.TrimSpace(st.GoogleClientID),
|
||||
"telegram_bot": strings.TrimSpace(st.TelegramBot),
|
||||
"admin_username": strings.TrimSpace(st.AdminUsername),
|
||||
"uploads_public_base": strings.TrimRight(strings.TrimSpace(st.UploadsPublicBase), "/"),
|
||||
"s3_endpoint": strings.TrimSpace(st.S3Endpoint),
|
||||
"r2_bucket": strings.TrimSpace(st.R2Bucket),
|
||||
}
|
||||
for k, v := range sets {
|
||||
if s.db.Dialect == db.Postgres {
|
||||
|
||||
Reference in new issue
Block a user