Files
summercms/modules/cabana/subject_events.go

45 lines
1.5 KiB
Go

package cabana
import (
"context"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/lagoon"
"git.golem15.com/golem15/summercms/modules/pact"
"gorm.io/gorm"
)
// backendSubjectGuard is the guard name backend subject events carry: the
// admin's own bouncer guard.
const backendSubjectGuard = "backend"
// fireSubjectChanged fires one pact.MCPSubjectChanged of the given kind for
// every administrator id through the application's event bus, so the MCP
// endpoint re-lists a linked admin's tools or ends their sessions. The event
// is a *pact.MCPSubjectChanged, the type pier listens for. Inside a
// transaction it fires only after the commit, so a rolled-back save fires
// nothing; outside one it fires at once. A missing application or bus is a
// no-op and a listener's error is logged: the save that caused the event
// never fails because of it.
func fireSubjectChanged(ctx context.Context, app *backpack.App, kind string, adminIDs ...uint) {
if app == nil || app.Events == nil {
return
}
if ctx == nil {
ctx = context.Background()
}
tx, _ := TxFromContext(ctx)
lagoon.AfterCommit(ctx, tx, func(ctx context.Context, _ *gorm.DB) {
for _, id := range adminIDs {
if id == 0 {
continue
}
event := &pact.MCPSubjectChanged{Guard: backendSubjectGuard, UserID: id, Kind: kind}
if err := app.Events.Fire(ctx, event); err != nil {
moduleLog.WarnContext(ctx, "cabana: subject changed listener failed", "kind", kind, "admin_id", id, "error", err)
}
}
})
}