Files
cmautobuy/admin/handler/integration/auth_test.go
T

112 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package integration
import (
"bytes"
"database/sql"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gin-gonic/gin"
"cmautobuy/admin/config"
"cmautobuy/admin/model"
"cmautobuy/admin/repository"
_ "modernc.org/sqlite"
)
func TestRequireCatalogToken(t *testing.T) {
gin.SetMode(gin.TestMode)
const token = "0123456789abcdef0123456789abcdef"
for _, tc := range []struct {
name, header string
cfg config.CatalogIntegrationConfig
want int
}{
{"未启用", "", config.CatalogIntegrationConfig{}, http.StatusServiceUnavailable},
{"缺少", "", config.CatalogIntegrationConfig{Source: "script", Token: token}, http.StatusUnauthorized},
{"错误", "Bearer wrong", config.CatalogIntegrationConfig{Source: "script", Token: token}, http.StatusUnauthorized},
{"正确", "Bearer " + token, config.CatalogIntegrationConfig{Source: "script", Token: token}, http.StatusNoContent},
} {
t.Run(tc.name, func(t *testing.T) {
r := gin.New()
r.GET("/protected", RequireCatalogToken(tc.cfg), func(c *gin.Context) {
if integrationSource(c) != tc.cfg.Source {
t.Fatalf("source=%q", integrationSource(c))
}
c.Status(http.StatusNoContent)
})
req := httptest.NewRequest(http.MethodGet, "/protected", nil)
req.Header.Set("Authorization", tc.header)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != tc.want {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}
if strings.Contains(resp.Body.String(), token) || strings.Contains(resp.Body.String(), "wrong") {
t.Fatal("响应泄露接口凭据")
}
})
}
}
func TestCatalogBatchAPI_按批次查询摘要(t *testing.T) {
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`CREATE TABLE catalog_import_runs(source TEXT,batch_id TEXT,request_hash TEXT,status TEXT,request_count INTEGER,conflict_count INTEGER,observed_at TEXT,last_request_at TEXT,last_conflict_at TEXT,shopee_created INTEGER DEFAULT 0,shopee_updated INTEGER DEFAULT 0,sku_created INTEGER DEFAULT 0,sku_updated INTEGER DEFAULT 0,pdd_created INTEGER DEFAULT 0,pdd_updated INTEGER DEFAULT 0,association_created INTEGER DEFAULT 0,association_unchanged INTEGER DEFAULT 0,failure_count INTEGER DEFAULT 0,error_summary TEXT,response_body TEXT,created_at TEXT,finished_at TEXT,PRIMARY KEY(source,batch_id))`)
if err != nil {
t.Fatal(err)
}
run := model.CatalogImportRun{Source: "script", BatchID: "B-1", RequestHash: "abc", Status: model.CatalogImportSucceeded, LastRequestAt: model.NowISO(), CreatedAt: model.NowISO()}
if err := repository.InsertCatalogImportRun(db, run); err != nil {
t.Fatal(err)
}
const token = "0123456789abcdef0123456789abcdef"
r := gin.New()
Register(r, db, config.CatalogIntegrationConfig{Source: "script", Token: token})
req := httptest.NewRequest(http.MethodGet, "/api/v1/integrations/catalog/batches/B-1", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != 200 || !strings.Contains(resp.Body.String(), `"batch_id":"B-1"`) {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}
if strings.Contains(resp.Body.String(), "request_hash") {
t.Fatal("查询响应不应暴露请求哈希")
}
}
func TestCatalogBatchAPI_鉴权JSON与体积限制(t *testing.T) {
gin.SetMode(gin.TestMode)
const token = "0123456789abcdef0123456789abcdef"
r := gin.New()
Register(r, nil, config.CatalogIntegrationConfig{Source: "script", Token: token})
for _, tc := range []struct {
name, auth string
body []byte
want int
}{
{"无鉴权", "", []byte(`{}`), http.StatusUnauthorized},
{"坏JSON", "Bearer " + token, []byte(`{"schema_version":`), http.StatusBadRequest},
{"超限", "Bearer " + token, bytes.Repeat([]byte("x"), catalogMaxBody+1), http.StatusRequestEntityTooLarge},
} {
t.Run(tc.name, func(t *testing.T) {
req := httptest.NewRequest(http.MethodPost, "/api/v1/integrations/catalog/batches", bytes.NewReader(tc.body))
req.Header.Set("Authorization", tc.auth)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)
if resp.Code != tc.want {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}
if !strings.Contains(resp.Header().Get("Content-Type"), "application/json") {
t.Fatalf("错误响应必须是 JSON:%s", resp.Header())
}
})
}
}