FileCodeBox Go 重写版 v2.5.6(安全审计修复版)
Go 1.27.1 (Gin+GORM) + Vue 3 文件快传服务: - 安全审计全部修复(docs/security-audit-2026-09-05.md): bcrypt 密码哈希与自动升级、presign 直传服务端大小/内容校验、 全局请求体上限、依赖升级(govulncheck 0 命中)、janitor 后台清理、 管理端审计动作落库、/admin CORS 收紧、通知内容白名单净化、 会话默认 7 天、限流缓存故障降级、robots.txt 端点等 - 前端:取件链接复制修复(不再重复拼接提取码)、markdown 净化器加固 - Redis 支持库号(FCB_REDIS_DB / redis://…/db URL) - 文档:docs/api/* 与 openapi.yaml 同步最新行为(robots.txt、 提码 5 位起、chunk 32MiB 上限、admin 审计动作等) 验证:gofmt/go vet/go test 全绿;二进制端到端冒烟通过
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
// schema 同步测试:保证 config.KVSchema() 的默认值/键集合与 defaults() 完全一致,
|
||||
// 与 settings 包 re-export 的键名常量同源。新增键时任何一处漏改都会在此失败。
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestKVSchemaDefaultsMatchDefaults KVSchema 的 Default 必须 === defaults() 中同名键。
|
||||
func TestKVSchemaDefaultsMatchDefaults(t *testing.T) {
|
||||
def := defaults()
|
||||
for _, e := range KVSchema() {
|
||||
want, ok := def[e.Key]
|
||||
if !ok {
|
||||
t.Fatalf("schema 键 %q 缺少 defaults() 默认值", e.Key)
|
||||
}
|
||||
// 类型规范化比较(JSON 序列化可比较 []string / int / float)
|
||||
a, _ := json.Marshal(e.Default)
|
||||
b, _ := json.Marshal(want)
|
||||
if string(a) != string(b) {
|
||||
t.Fatalf("键 %q 默认值不一致: schema=%s defaults=%s", e.Key, a, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestKVSchemaNoDuplicates 键名不得重复。
|
||||
func TestKVSchemaNoDuplicates(t *testing.T) {
|
||||
seen := map[string]bool{}
|
||||
for _, e := range KVSchema() {
|
||||
if seen[e.Key] {
|
||||
t.Fatalf("schema 键 %q 重复定义", e.Key)
|
||||
}
|
||||
seen[e.Key] = true
|
||||
}
|
||||
}
|
||||
|
||||
// TestV2NewKeysPresent v2 新增键必须在 schema 与 defaults 中同时存在。
|
||||
func TestV2NewKeysPresent(t *testing.T) {
|
||||
def := defaults()
|
||||
newKeys := []string{
|
||||
KeyBackgroundURL, KeyFooterText, KeyFooterBeian,
|
||||
KeyNotifyEnabled, KeyMaxSaveCount, KeyMaxFileSize,
|
||||
}
|
||||
for _, k := range newKeys {
|
||||
if _, ok := def[k]; !ok {
|
||||
t.Fatalf("v2 新键 %q 缺少默认值", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestV2AccessorDefaults v2 便捷访问器默认语义。
|
||||
func TestV2AccessorDefaults(t *testing.T) {
|
||||
t.Setenv("FCB_DB_DRIVER", "sqlite")
|
||||
t.Setenv("FCB_DB_DSN", "")
|
||||
c, err := New()
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
}
|
||||
// 背景图:background_url 与 background 均空 → 空
|
||||
if c.BackgroundURL() != "" {
|
||||
t.Fatalf("背景图默认应为空: %q", c.BackgroundURL())
|
||||
}
|
||||
// legacy background 键兜底
|
||||
c.ApplyKV(map[string]any{KeyBackground: "/legacy/bg.jpg"})
|
||||
if c.BackgroundURL() != "/legacy/bg.jpg" {
|
||||
t.Fatalf("legacy background 应回落生效: %q", c.BackgroundURL())
|
||||
}
|
||||
// max_file_size > 0 时优先于 uploadSize
|
||||
c.ApplyKV(map[string]any{KeyMaxFileSize: int64(1024), KeyUploadSize: int64(2048)})
|
||||
if c.MaxFileSize() != 1024 {
|
||||
t.Fatalf("max_file_size 应优先: %d", c.MaxFileSize())
|
||||
}
|
||||
// max_file_size = 0 回落 uploadSize
|
||||
c.ApplyKV(map[string]any{KeyMaxFileSize: int64(0)})
|
||||
if c.MaxFileSize() != 2048 {
|
||||
t.Fatalf("max_file_size=0 应回落 uploadSize: %d", c.MaxFileSize())
|
||||
}
|
||||
// 通知默认开启
|
||||
if !c.NotifyEnabled() {
|
||||
t.Fatal("notify_enabled 默认应开启")
|
||||
}
|
||||
// 保存次数上限默认不限制
|
||||
if c.MaxSaveCount() != 0 {
|
||||
t.Fatalf("max_save_count 默认应 0: %d", c.MaxSaveCount())
|
||||
}
|
||||
// 页脚默认空
|
||||
if c.FooterText() != "" || c.FooterBeian() != "" {
|
||||
t.Fatal("页脚默认应为空")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user