mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-05 08:55:28 +08:00
110 lines
3.3 KiB
Go
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)
|
|
}
|
|
}
|