Invalidate UI on approval queue changes

This commit is contained in:
Joe Julian
2026-04-11 09:53:23 -07:00
parent 2ef571c241
commit 852c115b2a
3 changed files with 50 additions and 0 deletions
+18
View File
@@ -50,6 +50,7 @@ type Broker struct {
timeout time.Duration
now func() time.Time
nextID func() string
notify func()
}
type pendingRequest struct {
@@ -108,6 +109,15 @@ func (b *Broker) Pending() []Request {
return requests
}
func (b *Broker) SetChangeNotifier(notify func()) {
if b == nil {
return
}
b.mu.Lock()
defer b.mu.Unlock()
b.notify = notify
}
func (b *Broker) Request(ctx context.Context, token apitokens.Token, op apitokens.Operation, resource apitokens.Resource) (Result, error) {
if b == nil {
return Result{}, ErrRequestTimedOut
@@ -128,12 +138,20 @@ func (b *Broker) Request(ctx context.Context, token apitokens.Token, op apitoken
b.mu.Lock()
b.pending[pending.request.ID] = pending
notify := b.notify
b.mu.Unlock()
if notify != nil {
notify()
}
defer func() {
b.mu.Lock()
delete(b.pending, pending.request.ID)
notify := b.notify
b.mu.Unlock()
if notify != nil {
notify()
}
}()
timer := time.NewTimer(b.timeout)
+31
View File
@@ -3,6 +3,7 @@ package apiapproval
import (
"context"
"errors"
"slices"
"testing"
"time"
@@ -120,6 +121,36 @@ func TestBrokerTimesOutPendingRequests(t *testing.T) {
}
}
func TestBrokerNotifiesWhenPendingRequestsChange(t *testing.T) {
t.Parallel()
broker := NewBroker(time.Minute)
changes := make(chan int, 4)
broker.SetChangeNotifier(func() {
changes <- len(broker.Pending())
})
errCh := make(chan error, 1)
go func() {
_, err := broker.Request(context.Background(), apitokens.Token{ID: "token-1", Name: "CLI"}, apitokens.OperationListGroups, apitokens.Resource{Kind: apitokens.ResourceGroup, Path: []string{"Root"}})
errCh <- err
}()
waitForPending(t, broker, 1)
if _, _, err := broker.Resolve(broker.Pending()[0].ID, OutcomeAllowOnce); err != nil {
t.Fatalf("Resolve(allow once) error = %v", err)
}
if err := <-errCh; err != nil {
t.Fatalf("Request() error = %v, want nil", err)
}
got := []int{<-changes, <-changes}
slices.Sort(got)
if !slices.Equal(got, []int{0, 1}) {
t.Fatalf("change notifications = %v, want [0 1]", got)
}
}
func waitForPending(t *testing.T, broker *Broker, want int) {
t.Helper()
+1
View File
@@ -76,6 +76,7 @@ func run(w *app.Window, mode string, paths statePaths, grpcAddr string) error {
ui.state.AuditLog = ui.auditLog
ui.grpcAddress = host.Address()
ui.state.Approvals = &uiApprovalManager{server: host.Server()}
host.Server().ApprovalBroker().SetChangeNotifier(ui.invalidate)
defer func() { _ = host.Stop() }()
}
for {