feat(management): add test to validate priority preservation in auth file uploads

- Implemented `TestUploadAuthFile_PreservesPriorityAttributes` to ensure priority attributes and metadata are preserved during auth file uploads.
- Updated `UploadAuthFile` logic to utilize `SynthesizeAuthFile` for better handling of generated auth attributes and metadata.

Closes: #2924
This commit is contained in:
Luis Pater
2026-06-17 21:48:34 +08:00
parent f23fb122e7
commit acaf250fa8
2 changed files with 97 additions and 13 deletions

View File

@@ -32,6 +32,7 @@ import (
"github.com/router-for-me/CLIProxyAPI/v7/internal/misc"
"github.com/router-for-me/CLIProxyAPI/v7/internal/registry"
"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
"github.com/router-for-me/CLIProxyAPI/v7/internal/watcher/synthesizer"
sdkAuth "github.com/router-for-me/CLIProxyAPI/v7/sdk/auth"
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
"github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginapi"
@@ -1161,21 +1162,35 @@ func (h *Handler) buildAuthFromFileData(path string, data []byte) (*coreauth.Aut
if authID == "" {
authID = path
}
attr := map[string]string{
"path": path,
"source": path,
auth := (*coreauth.Auth)(nil)
if h != nil && h.cfg != nil {
sctx := &synthesizer.SynthesisContext{
Config: h.cfg,
AuthDir: h.cfg.AuthDir,
Now: time.Now(),
IDGenerator: synthesizer.NewStableIDGenerator(),
}
if generated := synthesizer.SynthesizeAuthFile(sctx, path, data); len(generated) > 0 && generated[0] != nil {
auth = generated[0].Clone()
}
}
auth := &coreauth.Auth{
ID: authID,
Provider: provider,
FileName: filepath.Base(path),
Label: label,
Status: coreauth.StatusActive,
Attributes: attr,
Metadata: metadata,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
if auth == nil {
auth = &coreauth.Auth{
ID: authID,
Provider: provider,
Label: label,
Status: coreauth.StatusActive,
Attributes: map[string]string{
"path": path,
"source": path,
},
Metadata: metadata,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
}
auth.ID = authID
auth.FileName = filepath.Base(path)
if hasLastRefresh {
auth.LastRefreshedAt = lastRefresh
}

View File

@@ -0,0 +1,69 @@
package management
import (
"bytes"
"encoding/json"
"mime/multipart"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
)
func TestUploadAuthFile_PreservesPriorityAttributes(t *testing.T) {
t.Setenv("MANAGEMENT_PASSWORD", "")
gin.SetMode(gin.TestMode)
authDir := t.TempDir()
manager := coreauth.NewManager(nil, nil, nil)
h := NewHandlerWithoutConfigFilePath(&config.Config{AuthDir: authDir}, manager)
content := `{"type":"codex","email":"midai0530@gmail.com","priority":98}`
var body bytes.Buffer
writer := multipart.NewWriter(&body)
part, err := writer.CreateFormFile("file", "codex-midai0530@gmail.com-plus.json")
if err != nil {
t.Fatalf("failed to create multipart file: %v", err)
}
if _, err = part.Write([]byte(content)); err != nil {
t.Fatalf("failed to write multipart content: %v", err)
}
if err = writer.Close(); err != nil {
t.Fatalf("failed to close multipart writer: %v", err)
}
rec := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(rec)
req := httptest.NewRequest(http.MethodPost, "/v0/management/auth-files", &body)
req.Header.Set("Content-Type", writer.FormDataContentType())
ctx.Request = req
h.UploadAuthFile(ctx)
if rec.Code != http.StatusOK {
t.Fatalf("expected upload status %d, got %d with body %s", http.StatusOK, rec.Code, rec.Body.String())
}
var payload map[string]any
if err = json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
if status, _ := payload["status"].(string); status != "ok" {
t.Fatalf("expected status ok, got %#v", payload["status"])
}
auth, ok := manager.GetByID("codex-midai0530@gmail.com-plus.json")
if !ok || auth == nil {
t.Fatalf("expected uploaded auth record to exist")
}
if got := auth.Attributes["priority"]; got != "98" {
t.Fatalf("priority attribute = %q, want %q", got, "98")
}
if got := auth.Metadata["priority"]; got != float64(98) {
t.Fatalf("priority metadata = %#v, want 98", got)
}
}