- pier: TestSessionReserve (A-WR-03), TestLockScope (A-WR-07), TestScopeWidening (A-WR-04), TestStatelessFanOut (A-WR-05, A-WR-06), TestPersonalTokenBinding (A-WR-09), TestDispatchHardening (A-WR-01, A-WR-02, A-WR-08, A-IN-04, A-IN-05, A-IN-08), TestCatalogPathFields (A-WR-02, A-IN-07), TestPromptWriteCeiling (C-IN-01), TestTokenScopedRevoke (B-WR-04, C-IN-02), TestResolveClientAddress (B-IN-04); test seam WrapStore - pact TestFrontendTokenScopes, towel TestClientIP, cabana TestTokenScopeNameParity - cabana TestAccountContributionURL (B-WR-03), TestAccountContributionsIsolation (B-WR-06, B-IN-03), TestRecordActionPromptLocalized (B-IN-02), and the Postgres TestAccountTokenRevokeEvent (B-WR-04) and TestResolveBackendTokenRemote (B-IN-04) - vitest: hotkeysEditing.test.ts (B-WR-01, B-WR-02) and the extended AccountContributions.test.ts (B-WR-03, B-WR-06, B-IN-01) - check-phase19.7.sh requires every name (GO_TESTS, GO_TAGGED_TESTS, DOCKER_TESTS, ADMIN_FILES) and scans the new files (PHASE_TEST_FILES)
62 lines
2.0 KiB
Go
62 lines
2.0 KiB
Go
package cabana_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
"sync"
|
|
"testing"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/cabana"
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
)
|
|
|
|
// TestAccountTokenRevokeEvent pins plan 07's token-specific revocation
|
|
// (B-WR-04): revoking one g15_ token from My account fires exactly one
|
|
// revoked subject event for the admin, after the commit, whose TokenID is
|
|
// the revoked row's id, and no event for the admin as a whole (their other
|
|
// tokens and OAuth sessions stay). Postgres only: under -short nothing runs.
|
|
func TestAccountTokenRevokeEvent(t *testing.T) {
|
|
if testing.Short() {
|
|
return
|
|
}
|
|
t.Run("one revoked event with the token id", func(t *testing.T) {
|
|
env := newScreensEnv(t)
|
|
var mu sync.Mutex
|
|
var got []pact.MCPSubjectChanged
|
|
env.app.Events.Listen("test.revoke", func(_ context.Context, ev *pact.MCPSubjectChanged) error {
|
|
mu.Lock()
|
|
got = append(got, *ev)
|
|
mu.Unlock()
|
|
return nil
|
|
})
|
|
admin, jwt := env.admin(t, env.unique("revoke"), true, "")
|
|
ids := make([]uint, 2)
|
|
for i := range ids {
|
|
out := env.expect(t, http.StatusCreated, http.MethodPost, "/account/tokens", jwt, map[string]any{
|
|
"name": env.unique("agent"), "expires": "90d", "scopes": []string{"*"},
|
|
})
|
|
raw, _ := json.Marshal(out["data"])
|
|
var created cabana.AdminAPITokenCreated
|
|
if err := json.Unmarshal(raw, &created); err != nil || created.ID == 0 {
|
|
t.Fatalf("created token = %s (%v)", raw, err)
|
|
}
|
|
ids[i] = created.ID
|
|
}
|
|
mu.Lock()
|
|
got = nil
|
|
mu.Unlock()
|
|
env.expect(t, http.StatusOK, http.MethodDelete, "/account/tokens/"+strconv.FormatUint(uint64(ids[0]), 10), jwt, map[string]any{})
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
if len(got) != 1 {
|
|
t.Fatalf("revoking one token fired %d events, want 1: %+v", len(got), got)
|
|
}
|
|
ev := got[0]
|
|
if ev.Kind != pact.MCPSubjectRevoked || ev.Guard != "backend" || ev.UserID != admin.ID || ev.TokenID != ids[0] || ev.ClientID != "" {
|
|
t.Fatalf("event = %+v, want revoked backend %d with token %d", ev, admin.ID, ids[0])
|
|
}
|
|
})
|
|
}
|