Files
sm-bm-plugin/realtime.go
Jakub Zych 2a47186a7a feat: announce material revisions on materials:{id}
- every revision bump (API writes and /bmadmin saves) enqueues
  updated.jz.bm.material with {material_id, revision} in a savepoint
- the materials namespace authorizer allows a subscribe only to a
  visible material the user may manage
- api.ManagesMaterials and api.CanWatchMaterial
2026-11-09 01:12:49 +01:00

56 lines
2.0 KiB
Go

package bm
import (
"context"
"errors"
usermodels "git.golem15.com/golem15/sm-user-plugin/models"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/lighthouse"
"git.golem15.com/jakub/sm-bm-plugin/classes"
"git.golem15.com/jakub/sm-bm-plugin/controllers"
"gorm.io/gorm"
// The app always ships the Centrifugo driver; config/realtime.yaml
// keeps the null driver until rome's .env selects centrifugo.
_ "git.golem15.com/golem15/summercms/modules/lighthouse/centrifugo"
)
// errDatabaseUnavailable is the user lookup's answer before serve has
// published the database.
var errDatabaseUnavailable = errors.New("jz.bm: database unavailable")
// wireRealtime binds the app to the framework realtime service: it builds
// the service selected by realtime.driver, installs the user lookup the
// connection token reads its display name from and the notifier the
// materials admin announces revisions with, and registers the authorizer of
// the materials namespace. Channel authorizers belong to the plugins that
// own the channels: jz.bm owns materials (classes.MaterialsNamespace),
// golem15.presentations its own.
func (p *Plugin) wireRealtime(app *backpack.App) error {
svc, err := lighthouse.From(app)
if err != nil {
return err
}
p.realtime = svc
controllers.UseMaterialRevisionNotifier(&classes.MaterialRevisionNotifier{Realtime: svc})
svc.SetUserLookup(func(ctx context.Context, id uint) (lighthouse.User, bool, error) {
// Boot runs before serve publishes the database, so the handle is
// resolved per call.
gdb, ok := app.Lookup[*gorm.DB]()
if !ok || gdb == nil {
return lighthouse.User{}, false, errDatabaseUnavailable
}
var u usermodels.User
err := gdb.WithContext(ctx).Select("id", "name").Where("id = ?", id).Take(&u).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return lighthouse.User{}, false, nil
}
if err != nil {
return lighthouse.User{}, false, err
}
return lighthouse.User{ID: u.ID, Name: u.Name}, true, nil
})
return p.registerMaterialsRealtime(svc)
}