Files
ds2api/internal/httpapi/admin/token_runtime_http_test.go
2026-04-26 06:58:20 +08:00

110 lines
3.3 KiB
Go

package admin
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/go-chi/chi/v5"
"ds2api/internal/account"
"ds2api/internal/config"
adminshared "ds2api/internal/httpapi/admin/shared"
)
func newHTTPAdminHarness(t *testing.T, rawConfig string, ds adminshared.DeepSeekCaller) http.Handler {
t.Helper()
t.Setenv("DS2API_CONFIG_JSON", rawConfig)
store := config.LoadStore()
h := &Handler{
Store: store,
Pool: account.NewPool(store),
DS: ds,
}
r := chi.NewRouter()
RegisterRoutes(r, h)
return r
}
func adminReq(method, path string, body []byte) *http.Request {
req := httptest.NewRequest(method, path, bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer admin")
req.Header.Set("Content-Type", "application/json")
return req
}
func TestConfigImportIgnoresTokenFieldInPayload(t *testing.T) {
ds := &testingDSMock{}
router := newHTTPAdminHarness(t, `{"accounts":[]}`, ds)
payload := []byte(`{
"mode":"replace",
"config":{
"accounts":[{"email":"u@example.com","password":"pwd","token":"expired-token"}]
}
}`)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, adminReq(http.MethodPost, "/config/import", payload))
if rec.Code != http.StatusOK {
t.Fatalf("import status=%d body=%s", rec.Code, rec.Body.String())
}
readRec := httptest.NewRecorder()
router.ServeHTTP(readRec, adminReq(http.MethodGet, "/config", nil))
if readRec.Code != http.StatusOK {
t.Fatalf("get config status=%d body=%s", readRec.Code, readRec.Body.String())
}
var data map[string]any
if err := json.Unmarshal(readRec.Body.Bytes(), &data); err != nil {
t.Fatalf("decode config response: %v", err)
}
accounts, _ := data["accounts"].([]any)
if len(accounts) != 1 {
t.Fatalf("expected one account, got %d", len(accounts))
}
accountMap, _ := accounts[0].(map[string]any)
if hasToken, _ := accountMap["has_token"].(bool); hasToken {
t.Fatalf("expected imported token to be ignored, account=%#v", accountMap)
}
}
func TestAccountTestRefreshesRuntimeTokenButExportOmitsToken(t *testing.T) {
ds := &testingDSMock{}
router := newHTTPAdminHarness(t, `{
"accounts":[{"email":"batch@example.com","password":"pwd","token":"stale-token"}]
}`, ds)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, adminReq(http.MethodPost, "/accounts/test", []byte(`{"identifier":"batch@example.com"}`)))
if rec.Code != http.StatusOK {
t.Fatalf("test account status=%d body=%s", rec.Code, rec.Body.String())
}
var testResp map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &testResp); err != nil {
t.Fatalf("decode test response: %v", err)
}
if ok, _ := testResp["success"].(bool); !ok {
t.Fatalf("expected test success, got %#v", testResp)
}
if ds.loginCalls < 1 {
t.Fatalf("expected login to be called at least once, got %d", ds.loginCalls)
}
exportRec := httptest.NewRecorder()
router.ServeHTTP(exportRec, adminReq(http.MethodGet, "/config/export", nil))
if exportRec.Code != http.StatusOK {
t.Fatalf("export status=%d body=%s", exportRec.Code, exportRec.Body.String())
}
var exportResp map[string]any
if err := json.Unmarshal(exportRec.Body.Bytes(), &exportResp); err != nil {
t.Fatalf("decode export response: %v", err)
}
exportJSON, _ := exportResp["json"].(string)
if strings.Contains(exportJSON, `"token"`) {
t.Fatalf("expected export json to omit tokens, got %s", exportJSON)
}
}