package console import "testing" // 保存服务时的必填校验:启用中的服务不许留空凭据——之前 stt_azure 三个字段全空也存下去了, // 客户端拿到一串空字符串才暴露。停用/区域分叉两条豁免不能误伤。 func TestCheckSvcRequiredFields(t *testing.T) { enc := func(key, val string) SvcField { return SvcField{Key: key, Encrypted: true, DefValue: val} } plain := func(key, val string) SvcField { return SvcField{Key: key, DefValue: val} } t.Run("启用+凭据为空 → 拦下", func(t *testing.T) { m := &ThirdSvcConfig{Id: "stt_azure", Enable: true, Categories: "1", Fields: []SvcField{enc("subscription_key", ""), plain("region", "")}} if msg := checkSvcRequiredFieldsWith(m, nil); msg == "" { t.Fatal("凭据为空必须拦下") } }) t.Run("停用的服务放行", func(t *testing.T) { m := &ThirdSvcConfig{Id: "stt_azure", Categories: "1", Fields: []SvcField{enc("subscription_key", "")}} if msg := checkSvcRequiredFieldsWith(m, nil); msg != "" { t.Fatalf("停用的服务是草稿态,应放行:%s", msg) } }) t.Run("非加密字段留空不拦", func(t *testing.T) { m := &ThirdSvcConfig{Id: "llm_qwen", Enable: true, Categories: "5", Fields: []SvcField{enc("api_key", "sk-x"), plain("base_url", "")}} if msg := checkSvcRequiredFieldsWith(m, nil); msg != "" { t.Fatalf("base_url 这类可选字段不该拦:%s", msg) } }) t.Run("MCP 缺 url → 拦下", func(t *testing.T) { m := &ThirdSvcConfig{Id: "mcp_x", Enable: true, Categories: "10", Fields: []SvcField{plain("url", "")}} if msg := checkSvcRequiredFieldsWith(m, nil); msg == "" { t.Fatal("MCP 没有 url 客户端连不上,必须拦下") } }) t.Run("凭据齐全放行", func(t *testing.T) { m := &ThirdSvcConfig{Id: "tts_azure", Enable: true, Categories: "2", Fields: []SvcField{enc("subscription_key", "cipher"), plain("region", "southeastasia")}} if msg := checkSvcRequiredFieldsWith(m, nil); msg != "" { t.Fatalf("配齐了不该拦:%s", msg) } }) } // 列表接口给前端的「缺凭据」清单:只认「基础行与所有区域分叉都没值」,别把按区域配的服务误标。 func TestSvcCredMissing(t *testing.T) { items := []*ThirdSvcConfig{ {Id: "a", Fields: []SvcField{{Key: "k1", Encrypted: true, DefValue: ""}, {Key: "k2", Encrypted: true, DefValue: "cipher"}}}, {Id: "b", Fields: []SvcField{{Key: "k", Encrypted: true, DefValue: "cipher"}}}, {Id: "c", Fields: []SvcField{{Key: "plain", DefValue: ""}}}, } got := svcCredMissingWith(items, nil) // 没有任何区域覆盖 if len(got["a"]) != 1 || got["a"][0] != "k1" { t.Fatalf("a 应只缺 k1:%v", got["a"]) } if _, ok := got["b"]; ok { t.Fatalf("b 凭据齐全不该出现:%v", got) } if _, ok := got["c"]; ok { t.Fatalf("c 只有非加密字段,不算缺凭据:%v", got) } }