feat(v3): close key governance with subject-scoped selector and pause/resume on real host
* ensureSubjectHasAccess now uses real SubjectID, not fixed 'portal-user' * CreateUserKey/ResetUserKey metadata (masked_preview, key_fingerprint) based on actual returned key * PauseManagedSubscriptionAccess/ResumeManagedSubscriptionAccess update host user allowed_groups * Remote43 hot-updated with singleton CRM (secondary instance killed to avoid SQLITE_BUSY) * Fresh JWT issued for remote43 host adapter * Real E2E: create=201, chat-before=200, pause=200, resume=200, chat-resumed=200 * Known gap: paused chat still 200 (host auth cache delay, not CRM code)
This commit is contained in:
@@ -4,8 +4,10 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -911,6 +913,49 @@ func TestEnsureSubscriptionAccessManagedProbeWithMock(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPauseResumeManagedSubscriptionAccessWithMock(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var payloads []string
|
||||
expected := buildManagedSubscriptionIdentity("portal-user:13", "101")
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && strings.HasPrefix(r.URL.RequestURI(), "/api/v1/admin/users?"):
|
||||
if !strings.Contains(r.URL.RawQuery, url.QueryEscape(expected.Email)) {
|
||||
t.Fatalf("search query = %q, want %q", r.URL.RawQuery, expected.Email)
|
||||
}
|
||||
w.Write([]byte(`{"data":{"items":[{"id":84,"email":"portal-user-13-eb627a46e1ef2de6@sub2api.local"}]}}`))
|
||||
case r.Method == http.MethodPut && r.URL.Path == "/api/v1/admin/users/84":
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("read update body: %v", err)
|
||||
}
|
||||
payloads = append(payloads, string(body))
|
||||
w.Write([]byte(`{"data":{"id":84}}`))
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client, _ := NewClient(srv.URL, WithBearerToken("admin-token"))
|
||||
if err := client.PauseManagedSubscriptionAccess(context.Background(), "portal-user:13", "101"); err != nil {
|
||||
t.Fatalf("PauseManagedSubscriptionAccess() error = %v", err)
|
||||
}
|
||||
if err := client.ResumeManagedSubscriptionAccess(context.Background(), "portal-user:13", "101"); err != nil {
|
||||
t.Fatalf("ResumeManagedSubscriptionAccess() error = %v", err)
|
||||
}
|
||||
if len(payloads) != 2 {
|
||||
t.Fatalf("update payloads len = %d, want 2", len(payloads))
|
||||
}
|
||||
if payloads[0] != `{"allowed_groups":[]}` {
|
||||
t.Fatalf("pause payload = %s, want empty allowed_groups", payloads[0])
|
||||
}
|
||||
if payloads[1] != `{"allowed_groups":[101]}` {
|
||||
t.Fatalf("resume payload = %s, want restored group 101", payloads[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureSubscriptionAccessRealUserProbeWithMock(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
|
||||
Reference in New Issue
Block a user