系统设置迁入后台:站点地址 / 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
@@ -34,12 +34,20 @@ type accountView struct {
|
||||
}
|
||||
|
||||
type passwordInfo struct {
|
||||
// 站主密码由环境变量管理,不进库也不做哈希 —— 这条退路保证
|
||||
// 「解绑所有身份 + 删光 passkey」也不会把自已锁在门外。
|
||||
// 密码现在有两个可能的家:settings 表里的 bcrypt 哈希(后台改的),
|
||||
// 或环境变量 ONE_ADMIN_PASSWORD(未迁移时的兜底)。
|
||||
ManagedBy string `json:"managed_by"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// passwordSource 报告当前密码存哪。前端只作展示,不参与逻辑。
|
||||
func passwordSource(hash string) string {
|
||||
if hash != "" {
|
||||
return "settings"
|
||||
}
|
||||
return "env:ONE_ADMIN_PASSWORD"
|
||||
}
|
||||
|
||||
func (a *API) account(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
httpx.Error(w, http.StatusMethodNotAllowed, "GET required")
|
||||
@@ -54,7 +62,7 @@ func (a *API) account(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) buildAccount() (accountView, error) {
|
||||
owner, err := a.Store.EnsureOwner(a.Cfg.AdminUser)
|
||||
owner, err := a.Store.EnsureOwner(a.cfg().AdminUser)
|
||||
if err != nil {
|
||||
return accountView{}, err
|
||||
}
|
||||
@@ -72,12 +80,14 @@ func (a *API) buildAccount() (accountView, error) {
|
||||
}
|
||||
v := accountView{
|
||||
// 昵称以站主行的 name 为准;老数据里它是空的,回落到站点设置的作者名。
|
||||
Name: firstNonEmptyStr(owner.Name, st.AuthorName),
|
||||
Bio: st.AuthorBio,
|
||||
AvatarKey: st.AuthorAvatarKey,
|
||||
AvatarURL: a.avatarURL(st.AuthorAvatarKey),
|
||||
Handle: owner.Handle,
|
||||
Password: passwordInfo{ManagedBy: "env:ONE_ADMIN_PASSWORD", Username: a.Cfg.AdminUser},
|
||||
Name: firstNonEmptyStr(owner.Name, st.AuthorName),
|
||||
Bio: st.AuthorBio,
|
||||
AvatarKey: st.AuthorAvatarKey,
|
||||
AvatarURL: a.avatarURL(st.AuthorAvatarKey),
|
||||
Handle: owner.Handle,
|
||||
// 密码可迁到哪:后台「管理员账号」里改过就是 DB(bcrypt 哈希),
|
||||
// 否则回落 env。
|
||||
Password: passwordInfo{ManagedBy: passwordSource(st.AdminPasswordHash), Username: a.cfg().AdminUser},
|
||||
Identities: ids,
|
||||
Passkeys: pks,
|
||||
}
|
||||
@@ -92,15 +102,16 @@ func (a *API) buildAccount() (accountView, error) {
|
||||
}
|
||||
|
||||
// providerEnabled 判断某个第三方平台是否配了凭据。绑定入口只列已配置的,
|
||||
// 否则点了必然报错。
|
||||
// 否则点了必然报错。凭据按有效配置算(后台系统设置优先于环境变量)。
|
||||
func (a *API) providerEnabled(name string) bool {
|
||||
c := a.cfg()
|
||||
switch name {
|
||||
case "github":
|
||||
return a.Cfg.GitHubClientID != "" && a.Cfg.GitHubClientSecret != ""
|
||||
return c.GitHubClientID != "" && c.GitHubClientSecret != ""
|
||||
case "google":
|
||||
return a.Cfg.GoogleClientID != "" && a.Cfg.GoogleClientSecret != ""
|
||||
return c.GoogleClientID != "" && c.GoogleClientSecret != ""
|
||||
case "telegram":
|
||||
return a.Cfg.TelegramBot != "" && a.Cfg.TelegramToken != ""
|
||||
return c.TelegramBot != "" && c.TelegramToken != ""
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -115,7 +126,7 @@ func (a *API) avatarURL(key string) string {
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return storage.FileURL(f.Store, f.Key, a.Cfg.UploadsPublicBase)
|
||||
return storage.FileURL(f.Store, f.Key, a.cfg().UploadsPublicBase)
|
||||
}
|
||||
|
||||
type patchAccountRequest struct {
|
||||
@@ -132,7 +143,7 @@ func (a *API) patchAccount(w http.ResponseWriter, r *http.Request) {
|
||||
httpx.BadRequest(w, "invalid body")
|
||||
return
|
||||
}
|
||||
owner, err := a.Store.EnsureOwner(a.Cfg.AdminUser)
|
||||
owner, err := a.Store.EnsureOwner(a.cfg().AdminUser)
|
||||
if err != nil {
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
@@ -228,7 +239,7 @@ func (a *API) unbindIdentity(w http.ResponseWriter, r *http.Request) {
|
||||
httpx.BadRequest(w, "bad provider")
|
||||
return
|
||||
}
|
||||
owner, err := a.Store.EnsureOwner(a.Cfg.AdminUser)
|
||||
owner, err := a.Store.EnsureOwner(a.cfg().AdminUser)
|
||||
if err != nil {
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user