feat: 统一管理台主题与 Key 展示
This commit is contained in:
@@ -186,6 +186,27 @@ func TestCreateKeyCopiesDefaultRuleSnapshot(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateKeyRejectsShortSecret(t *testing.T) {
|
||||
app := NewApp()
|
||||
if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\n"))); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
response := managementCallBody(t, app, http.MethodPost, managementBase+routeKeys, []byte(`{"name":"short","secret":"12345"}`))
|
||||
if response.StatusCode != http.StatusBadRequest || !strings.Contains(string(response.Body), "6-256") {
|
||||
t.Fatalf("short Key response=%d body=%s", response.StatusCode, response.Body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagedSecretValidation(t *testing.T) {
|
||||
for secret, want := range map[string]bool{
|
||||
"12345": false, "000000": true, "alice-000000": true, "with space": false, strings.Repeat("x", 257): false,
|
||||
} {
|
||||
if got := validManagedSecret(secret); got != want {
|
||||
t.Fatalf("validManagedSecret(%q)=%v, want %v", secret, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBillingAdmissionConcurrencyAndUsageSettlement(t *testing.T) {
|
||||
app := NewApp()
|
||||
if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil {
|
||||
|
||||
@@ -65,6 +65,12 @@ func TestLifecycleConfigYAMLUsesBase64WireEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigRejectsShortBootstrapKey(t *testing.T) {
|
||||
if _, err := decodeConfig([]byte("bootstrap_key: 12345\n")); err == nil {
|
||||
t.Fatal("short bootstrap_key unexpectedly accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsageRecordWireFieldsMatchTargetContract(t *testing.T) {
|
||||
raw, err := json.Marshal(UsageRecord{})
|
||||
if err != nil {
|
||||
|
||||
@@ -33,8 +33,11 @@ func decodeConfig(raw []byte) (Config, error) {
|
||||
if strings.TrimSpace(cfg.DatabasePath) == "" {
|
||||
return Config{}, fmt.Errorf("database_path 不能为空")
|
||||
}
|
||||
if strings.TrimSpace(cfg.BootstrapName) == "" || strings.TrimSpace(cfg.BootstrapKey) == "" {
|
||||
return Config{}, fmt.Errorf("bootstrap_name 和 bootstrap_key 不能为空")
|
||||
if strings.TrimSpace(cfg.BootstrapName) == "" {
|
||||
return Config{}, fmt.Errorf("bootstrap_name 不能为空")
|
||||
}
|
||||
if !validManagedSecret(cfg.BootstrapKey) {
|
||||
return Config{}, fmt.Errorf("bootstrap_key 必须为 6-256 个不含空白或控制字符的字符")
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func (a *App) createManagedKey(body []byte) ManagementResponse {
|
||||
}
|
||||
}
|
||||
if !validManagedSecret(secret) {
|
||||
return managementError(http.StatusBadRequest, "invalid_key", "Key 必须为 1-256 个不含空白或控制字符的字符")
|
||||
return managementError(http.StatusBadRequest, "invalid_key", "Key 必须为 6-256 个不含空白或控制字符的字符")
|
||||
}
|
||||
keyID, err := generatedToken("key_")
|
||||
if err != nil {
|
||||
@@ -465,7 +465,7 @@ func generatedToken(prefix string) (string, error) {
|
||||
}
|
||||
|
||||
func validManagedSecret(secret string) bool {
|
||||
if secret == "" || len(secret) > 256 {
|
||||
if len(secret) < 6 || len(secret) > 256 {
|
||||
return false
|
||||
}
|
||||
for _, value := range secret {
|
||||
|
||||
@@ -454,11 +454,16 @@ func TestUsageResourceServesTablePage(t *testing.T) {
|
||||
if strings.Contains(page, "<script src=") || strings.Contains(page, "<link rel=\"stylesheet\" href=") {
|
||||
t.Fatal("UI unexpectedly depends on external assets")
|
||||
}
|
||||
for _, removed := range []string{"下游 Keys", "最近用量记录", "显示 102 条", "最多展示", "1–100 /", "一个 Key 对应一个用户", "查看请求结果、实际上游", "维护模型基础价格"} {
|
||||
for _, removed := range []string{"下游 Keys", "最近用量记录", "显示 102 条", "最多展示", "1–100 /", "一个 Key 对应一个用户", "查看请求结果、实际上游", "维护模型基础价格", "点击“管理”修改访问、路由与额度", "由 CPA 调度", `copy.textContent = "复制"`} {
|
||||
if strings.Contains(page, removed) {
|
||||
t.Fatalf("UI still contains removed description %q", removed)
|
||||
}
|
||||
}
|
||||
for _, feature := range []string{`minlength="6"`, `maskedSecret(key.secret)`, `className = "credential-copy"`, `return "自由选择"`} {
|
||||
if !strings.Contains(page, feature) {
|
||||
t.Fatalf("UI does not contain compact Key display feature %q", feature)
|
||||
}
|
||||
}
|
||||
if strings.Index(page, `id="page-buttons"`) > strings.Index(page, `id="headers"`) {
|
||||
t.Fatal("UI pagination controls are not above the usage table")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user