package maoyuadmin import ( "context" "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "io" "net/http" "net/http/httptest" "net/url" "strings" "testing" "time" ) func TestClientSignsScopeAndTargetsMaoyuPrefix(t *testing.T) { const secret = "test-secret" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { t.Fatal(err) } if r.URL.RequestURI() != "/internal/admin/maoyu/tenants/default/content-reviews?status=pending" { t.Fatalf("request URI = %q", r.URL.RequestURI()) } if r.Header.Get("X-Tenant-ID") != "1" || r.Header.Get("X-Operator-ID") != "14" { t.Fatalf("unexpected scope headers") } hash := sha256.Sum256(body) canonical := strings.Join([]string{ r.Method, r.URL.RequestURI(), hex.EncodeToString(hash[:]), r.Header.Get("X-Timestamp"), r.Header.Get("X-Nonce"), "1", "14", "imManager", "req-test", }, "\n") mac := hmac.New(sha256.New, []byte(secret)) _, _ = mac.Write([]byte(canonical)) if !hmac.Equal([]byte(r.Header.Get("X-Signature")), []byte(hex.EncodeToString(mac.Sum(nil)))) { t.Fatal("signature mismatch") } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]any{ "code": 0, "data": map[string]any{"post_count": 7, "pending_audit_count": 3}, }) })) defer server.Close() client := NewClient(Config{BaseURL: server.URL, ServiceName: "im-manager", Secret: secret, Timeout: time.Second}) client.http = server.Client() var out struct { PostCount int64 `json:"postCount"` PendingAuditCount int64 `json:"pendingAuditCount"` } err := client.Get(context.Background(), Scope{TenantID: 1, TenantCode: "default", OperatorID: 14, RoleKey: "imManager", RequestID: "req-test"}, "/content-reviews", url.Values{"status": []string{"pending"}}, &out) if err != nil { t.Fatal(err) } if out.PostCount != 7 || out.PendingAuditCount != 3 { t.Fatalf("unexpected response: %+v", out) } } func TestClientReturnsBusinessMessage(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusConflict) _, _ = w.Write([]byte(`{"code":40901,"reason":"STATE_CONFLICT","message":"当前状态不允许操作"}`)) })) defer server.Close() client := NewClient(Config{BaseURL: server.URL, ServiceName: "im-manager", Secret: "secret", Timeout: time.Second}) client.http = server.Client() err := client.Post(context.Background(), Scope{TenantID: 1, TenantCode: "default", OperatorID: 14, RequestID: "req-test"}, "/content-reviews/feed_post/1/actions", map[string]any{"action": "approve"}, nil) if err == nil || err.Error() != "当前状态不允许操作" { t.Fatalf("unexpected error: %v", err) } }