Files
Cyrene_v2/internal/config/data_dir_admin_path_test.go
AskaEth a398dc9b92
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(config,gateway,web): 路径式安全入口 ADMIN_PATH + 数据目录 platform 哨兵(裁决 1.6/16.4.7/12.4.2 + 1.5/12.4.3 核对)
- 1.6 + 16.4.7:安全入口=路径式 `/<ADMIN_PATH>`(env `ADMIN_PATH`,默认 `admin`;`xxx/admin` 亦可,
  非法值回退 `/admin`)。命中前缀 → 送注入了 `<base href="/">` + `window.__CYRENE_ADMIN_ENTRY__` 的面板入口页
  (深链直达);**形如面板入口但前缀不符 → 404**(不回落用户端聊天壳);`/api/*`、`/ws`、webhook 先放行
  ⇒ **API 不藏**。前端路由改**路径式**(`router.ts` 只读注入,无硬编兜底;移除 hash 入口)
- 1.5 / 12.4.3 核对:暴露面默认 `0.0.0.0` 与裁决一致,无需改代码(仅补注释)
- 12.4.2:`DATA_DIR` 支持 `platform` 哨兵(大小写不敏感)→ 平台标准目录;默认 `./data` 与显式空值行为不变
  (显式空值保持原兜底,避免正在运行实例突然换库)
- 复核:build/vet 绿 + config/gateway 包测试绿 + linux/darwin 交叉编译绿;新增 7 条用例,
  并用真实构建产物(`webui.Assets()`)跑通「浏览器直开 /admin 能启动面板」(`<base>` 必须在资源引用之前)
- 变异 2 条(关掉错前缀 404 / 前端默认前缀兜底)已还原
- ⚠️ 运行时序:前端已生效而后端 hatch 未生效期间**面板打不开** ⇒ 需紧接一次「build 到位 + restart」
2026-10-04 14:00:25 +08:00

73 lines
2.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package config
import (
"strings"
"testing"
"git.yeij.top/AskaEth/Cyrene_v2/internal/platform"
)
// TestLoad_DataDirPlatformSentinel 覆盖数据目录的两种取法(design/13 §2,
// 裁决 12.4.2 + 15.4.1):未配置走默认 `./data`;显式哨兵 `platform` 才走
// 平台标准数据目录;显式路径原样保留。
func TestLoad_DataDirPlatformSentinel(t *testing.T) {
t.Setenv("JWT_SECRET", strings.Repeat("s", 40))
unsetEnvForTest(t, "DATA_DIR")
cfg, err := Load("")
if err != nil {
t.Fatalf("Load() error: %v", err)
}
if cfg.DataDir != "./data" {
t.Errorf("DataDir = %q, want ./data (unset keeps the historic default)", cfg.DataDir)
}
t.Setenv("DATA_DIR", "platform")
cfg, err = Load("")
if err != nil {
t.Fatalf("Load() with sentinel error: %v", err)
}
if want := platform.DefaultDataDir(); cfg.DataDir != want {
t.Errorf("DataDir = %q, want the platform standard dir %q", cfg.DataDir, want)
}
// 显式路径(含显式 ./data)不被改写。
for _, p := range []string{"./data", "/var/lib/cyrene"} {
t.Setenv("DATA_DIR", p)
cfg, err = Load("")
if err != nil {
t.Fatalf("Load() with DATA_DIR=%q error: %v", p, err)
}
if cfg.DataDir != p {
t.Errorf("DataDir = %q, want %q verbatim", cfg.DataDir, p)
}
}
}
// TestAdminPathPrefix 覆盖安全入口前缀的归一化(裁决 1.6 / 16.4.7,
// design/07 §0.2):默认 `admin` → `/admin`,自定义 `xxx/admin` →
// `/xxx/admin`(即 `host/xxx/admin` 形态),非法值一律挂回默认。
func TestAdminPathPrefix(t *testing.T) {
want := map[string]string{
"": "/admin",
"admin": "/admin",
"/admin": "/admin",
"/admin/": "/admin",
"xxx/admin": "/xxx/admin",
"/xxx/admin/": "/xxx/admin",
" a / b ": "/a/b",
"../etc": "/admin",
"a/../b": "/admin",
"a//b": "/admin",
"a?b": "/admin",
"a#b": "/admin",
" ": "/admin",
}
for in, exp := range want {
cfg := ServerConfig{AdminPath: in}
if got := cfg.AdminPathPrefix(); got != exp {
t.Errorf("AdminPath %q → %q, want %q", in, got, exp)
}
}
}