refactor: 删 trimAll + 修 isSensitive,统一用 stdlib

两处自实现 / 半成品:

1. controller/settings.go trimAll (11 行)
   - 自己写循环 trim 4 个 ASCII 字符 (' ' \t \n \r)
   - 等价于 strings.TrimSpace (后者 trim 所有 Unicode 空白)
   - strings 包已 import (其他代码用着), 没引用代价
   - 改: 7 个调用点全替, 删函数定义

2. cmd/dumpdb/main.go isSensitive (13 行)
   - 自实现 strings.Contains 循环, 没调 strings.ToLower
   - 变量名叫 lowK 但实际从未小写化
   - Bug: API_KEY / Auth_Token 这类大写 key 不会被判为敏感, 漏打码
   - 修: 用 strings.ToLower + strings.Contains, 大小写不敏感
   - 顺手加 strings import

收益:
- 行数: +15 / -27 (净删 12 行)
- 一致性: 看到 strings.TrimSpace / strings.Contains 就懂, 不必读自实现
- 安全: 大写 key 之前漏打码, 修了

e2e 验证 (verifydbsens 临时脚本, 已删):
  api_key        -> sensitive ✓
  auth_key       -> sensitive ✓
  API_KEY_UPPER  -> sensitive ✓ (修前漏)
  Auth_Token_Mixed -> sensitive ✓ (修前漏)
  default_speaker -> sensitive ✓
  default_resource_id -> not sensitive ✓
  note            -> not sensitive ✓

build + go test ./... 全绿
未 push (待用户)
This commit is contained in:
sun
2026-09-05 11:59:06 +08:00
parent 59c0027122
commit 9353790899
2 changed files with 15 additions and 27 deletions
+8 -8
View File
@@ -11,6 +11,7 @@ import (
"database/sql" "database/sql"
"fmt" "fmt"
"os" "os"
"strings"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
@@ -116,14 +117,13 @@ func main() {
} }
func isSensitive(key string) bool { func isSensitive(key string) bool {
lowK := key // 标记 key 名包含 "key" / "token" / "speaker" 即视为敏感,值打码。
// 简单 contains (不引 strings 包保持精简) // 大小写不敏感: API_KEY / Auth_Token 等大写 key 也会被命中
markers := []string{"key", "token", "speaker"} // (避免漏打码)。
for _, m := range markers { low := strings.ToLower(key)
for i := 0; i+len(m) <= len(lowK); i++ { for _, m := range []string{"key", "token", "speaker"} {
if lowK[i:i+len(m)] == m { if strings.Contains(low, m) {
return true return true
}
} }
} }
return false return false
+7 -19
View File
@@ -121,7 +121,7 @@ func SettingsUpdateHandler(w http.ResponseWriter, r *http.Request) {
// 收集要更新的键值对 // 收集要更新的键值对
updates := make(map[string]string) updates := make(map[string]string)
if body.DefaultResourceID != nil { if body.DefaultResourceID != nil {
v := trimAll(*body.DefaultResourceID) v := strings.TrimSpace(*body.DefaultResourceID)
if v == "" { if v == "" {
middleware.SendJSONError(w, http.StatusBadRequest, "default_resource_id cannot be empty", "invalid_request_error", "missing_field") middleware.SendJSONError(w, http.StatusBadRequest, "default_resource_id cannot be empty", "invalid_request_error", "missing_field")
return return
@@ -129,7 +129,7 @@ func SettingsUpdateHandler(w http.ResponseWriter, r *http.Request) {
updates["default_resource_id"] = v updates["default_resource_id"] = v
} }
if body.DefaultSpeaker != nil { if body.DefaultSpeaker != nil {
v := trimAll(*body.DefaultSpeaker) v := strings.TrimSpace(*body.DefaultSpeaker)
if v == "" { if v == "" {
middleware.SendJSONError(w, http.StatusBadRequest, "default_speaker cannot be empty", "invalid_request_error", "missing_field") middleware.SendJSONError(w, http.StatusBadRequest, "default_speaker cannot be empty", "invalid_request_error", "missing_field")
return return
@@ -144,7 +144,7 @@ func SettingsUpdateHandler(w http.ResponseWriter, r *http.Request) {
updates["default_speaker"] = v updates["default_speaker"] = v
} }
if body.DefaultFormat != nil { if body.DefaultFormat != nil {
v := trimAll(*body.DefaultFormat) v := strings.TrimSpace(*body.DefaultFormat)
if !isValidFormat(v) { if !isValidFormat(v) {
middleware.SendJSONError(w, http.StatusBadRequest, middleware.SendJSONError(w, http.StatusBadRequest,
fmt.Sprintf("default_format %q invalid; valid: mp3/wav/opus/pcm/aac/flac", v), fmt.Sprintf("default_format %q invalid; valid: mp3/wav/opus/pcm/aac/flac", v),
@@ -163,13 +163,13 @@ func SettingsUpdateHandler(w http.ResponseWriter, r *http.Request) {
updates["sample_rate"] = strconv.Itoa(v) updates["sample_rate"] = strconv.Itoa(v)
} }
if body.Model != nil { if body.Model != nil {
updates["model"] = trimAll(*body.Model) updates["model"] = strings.TrimSpace(*body.Model)
} }
if body.ModelType != nil { if body.ModelType != nil {
updates["model_type"] = strconv.Itoa(*body.ModelType) updates["model_type"] = strconv.Itoa(*body.ModelType)
} }
if body.ExplicitLanguage != nil { if body.ExplicitLanguage != nil {
updates["explicit_language"] = trimAll(*body.ExplicitLanguage) updates["explicit_language"] = strings.TrimSpace(*body.ExplicitLanguage)
} }
if body.EnableSubtitle != nil { if body.EnableSubtitle != nil {
updates["enable_subtitle"] = boolToStr(*body.EnableSubtitle) updates["enable_subtitle"] = boolToStr(*body.EnableSubtitle)
@@ -232,7 +232,7 @@ func SettingsAPIKeyHandler(w http.ResponseWriter, r *http.Request) {
middleware.SendJSONError(w, http.StatusBadRequest, "invalid JSON body", "invalid_request_error", "bad_request") middleware.SendJSONError(w, http.StatusBadRequest, "invalid JSON body", "invalid_request_error", "bad_request")
return return
} }
key := trimAll(body.APIKey) key := strings.TrimSpace(body.APIKey)
if key == "" { if key == "" {
middleware.SendJSONError(w, http.StatusBadRequest, "api_key cannot be empty", "invalid_request_error", "missing_field") middleware.SendJSONError(w, http.StatusBadRequest, "api_key cannot be empty", "invalid_request_error", "missing_field")
return return
@@ -280,7 +280,7 @@ func SettingsAuthKeyHandler(w http.ResponseWriter, r *http.Request) {
middleware.SendJSONError(w, http.StatusBadRequest, "invalid JSON body", "invalid_request_error", "bad_request") middleware.SendJSONError(w, http.StatusBadRequest, "invalid JSON body", "invalid_request_error", "bad_request")
return return
} }
key := trimAll(body.AuthKey) key := strings.TrimSpace(body.AuthKey)
if key == "" { if key == "" {
middleware.SendJSONError(w, http.StatusBadRequest, "auth_key cannot be empty", "invalid_request_error", "missing_field") middleware.SendJSONError(w, http.StatusBadRequest, "auth_key cannot be empty", "invalid_request_error", "missing_field")
return return
@@ -409,18 +409,6 @@ func maskAPIKeyField(s string) string {
return s[:4] + "****" + s[len(s)-4:] return s[:4] + "****" + s[len(s)-4:]
} }
func trimAll(s string) string {
// 简单 trim 前后空白;不剥中间空格
out := s
for len(out) > 0 && (out[0] == ' ' || out[0] == '\t' || out[0] == '\n' || out[0] == '\r') {
out = out[1:]
}
for len(out) > 0 && (out[len(out)-1] == ' ' || out[len(out)-1] == '\t' || out[len(out)-1] == '\n' || out[len(out)-1] == '\r') {
out = out[:len(out)-1]
}
return out
}
func isValidFormat(s string) bool { func isValidFormat(s string) bool {
switch s { switch s {
case "mp3", "wav", "opus", "pcm", "aac", "flac", "": case "mp3", "wav", "opus", "pcm", "aac", "flac", "":