231 lines
5.6 KiB
Go
231 lines
5.6 KiB
Go
package admin
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type dataResponse struct {
|
|
Code int `json:"code"`
|
|
Data dataPayload `json:"data"`
|
|
}
|
|
|
|
type dataPayload struct {
|
|
Type string `json:"type"`
|
|
Version int `json:"version"`
|
|
Proxies []dataProxy `json:"proxies"`
|
|
Accounts []dataAccount `json:"accounts"`
|
|
}
|
|
|
|
type dataProxy struct {
|
|
ProxyKey string `json:"proxy_key"`
|
|
Name string `json:"name"`
|
|
Protocol string `json:"protocol"`
|
|
Host string `json:"host"`
|
|
Port int `json:"port"`
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type dataAccount struct {
|
|
Name string `json:"name"`
|
|
Platform string `json:"platform"`
|
|
Type string `json:"type"`
|
|
Credentials map[string]any `json:"credentials"`
|
|
Extra map[string]any `json:"extra"`
|
|
ProxyKey *string `json:"proxy_key"`
|
|
Concurrency int `json:"concurrency"`
|
|
Priority int `json:"priority"`
|
|
}
|
|
|
|
func setupAccountDataRouter() (*gin.Engine, *stubAdminService) {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.New()
|
|
adminSvc := newStubAdminService()
|
|
|
|
h := NewAccountHandler(
|
|
adminSvc,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
nil,
|
|
)
|
|
|
|
router.GET("/api/v1/admin/accounts/data", h.ExportData)
|
|
router.POST("/api/v1/admin/accounts/data", h.ImportData)
|
|
return router, adminSvc
|
|
}
|
|
|
|
func TestExportDataIncludesSecrets(t *testing.T) {
|
|
router, adminSvc := setupAccountDataRouter()
|
|
|
|
proxyID := int64(11)
|
|
adminSvc.proxies = []service.Proxy{
|
|
{
|
|
ID: proxyID,
|
|
Name: "proxy",
|
|
Protocol: "http",
|
|
Host: "127.0.0.1",
|
|
Port: 8080,
|
|
Username: "user",
|
|
Password: "pass",
|
|
Status: service.StatusActive,
|
|
},
|
|
{
|
|
ID: 12,
|
|
Name: "orphan",
|
|
Protocol: "https",
|
|
Host: "10.0.0.1",
|
|
Port: 443,
|
|
Username: "o",
|
|
Password: "p",
|
|
Status: service.StatusActive,
|
|
},
|
|
}
|
|
adminSvc.accounts = []service.Account{
|
|
{
|
|
ID: 21,
|
|
Name: "account",
|
|
Platform: service.PlatformOpenAI,
|
|
Type: service.AccountTypeOAuth,
|
|
Credentials: map[string]any{"token": "secret"},
|
|
Extra: map[string]any{"note": "x"},
|
|
ProxyID: &proxyID,
|
|
Concurrency: 3,
|
|
Priority: 50,
|
|
Status: service.StatusDisabled,
|
|
},
|
|
}
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/accounts/data", nil)
|
|
router.ServeHTTP(rec, req)
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
var resp dataResponse
|
|
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
|
require.Equal(t, 0, resp.Code)
|
|
require.Equal(t, dataType, resp.Data.Type)
|
|
require.Len(t, resp.Data.Proxies, 2)
|
|
require.Equal(t, "pass", resp.Data.Proxies[0].Password)
|
|
require.Len(t, resp.Data.Accounts, 1)
|
|
require.Equal(t, "secret", resp.Data.Accounts[0].Credentials["token"])
|
|
}
|
|
|
|
func TestExportDataWithoutProxies(t *testing.T) {
|
|
router, adminSvc := setupAccountDataRouter()
|
|
|
|
proxyID := int64(11)
|
|
adminSvc.proxies = []service.Proxy{
|
|
{
|
|
ID: proxyID,
|
|
Name: "proxy",
|
|
Protocol: "http",
|
|
Host: "127.0.0.1",
|
|
Port: 8080,
|
|
Username: "user",
|
|
Password: "pass",
|
|
Status: service.StatusActive,
|
|
},
|
|
}
|
|
adminSvc.accounts = []service.Account{
|
|
{
|
|
ID: 21,
|
|
Name: "account",
|
|
Platform: service.PlatformOpenAI,
|
|
Type: service.AccountTypeOAuth,
|
|
Credentials: map[string]any{"token": "secret"},
|
|
ProxyID: &proxyID,
|
|
Concurrency: 3,
|
|
Priority: 50,
|
|
Status: service.StatusDisabled,
|
|
},
|
|
}
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/accounts/data?include_proxies=false", nil)
|
|
router.ServeHTTP(rec, req)
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
var resp dataResponse
|
|
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
|
|
require.Equal(t, 0, resp.Code)
|
|
require.Len(t, resp.Data.Proxies, 0)
|
|
require.Len(t, resp.Data.Accounts, 1)
|
|
require.Nil(t, resp.Data.Accounts[0].ProxyKey)
|
|
}
|
|
|
|
func TestImportDataReusesProxyAndSkipsDefaultGroup(t *testing.T) {
|
|
router, adminSvc := setupAccountDataRouter()
|
|
|
|
adminSvc.proxies = []service.Proxy{
|
|
{
|
|
ID: 1,
|
|
Name: "proxy",
|
|
Protocol: "socks5",
|
|
Host: "1.2.3.4",
|
|
Port: 1080,
|
|
Username: "u",
|
|
Password: "p",
|
|
Status: service.StatusActive,
|
|
},
|
|
}
|
|
|
|
dataPayload := map[string]any{
|
|
"data": map[string]any{
|
|
"type": dataType,
|
|
"version": dataVersion,
|
|
"proxies": []map[string]any{
|
|
{
|
|
"proxy_key": "socks5|1.2.3.4|1080|u|p",
|
|
"name": "proxy",
|
|
"protocol": "socks5",
|
|
"host": "1.2.3.4",
|
|
"port": 1080,
|
|
"username": "u",
|
|
"password": "p",
|
|
"status": "active",
|
|
},
|
|
},
|
|
"accounts": []map[string]any{
|
|
{
|
|
"name": "acc",
|
|
"platform": service.PlatformOpenAI,
|
|
"type": service.AccountTypeOAuth,
|
|
"credentials": map[string]any{"token": "x"},
|
|
"proxy_key": "socks5|1.2.3.4|1080|u|p",
|
|
"concurrency": 3,
|
|
"priority": 50,
|
|
},
|
|
},
|
|
},
|
|
"skip_default_group_bind": true,
|
|
}
|
|
|
|
body, _ := json.Marshal(dataPayload)
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/admin/accounts/data", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
router.ServeHTTP(rec, req)
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
require.Len(t, adminSvc.createdProxies, 0)
|
|
require.Len(t, adminSvc.createdAccounts, 1)
|
|
require.True(t, adminSvc.createdAccounts[0].SkipDefaultGroupBind)
|
|
}
|