Files
sm-bm-plugin/realtime_materials.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

51 lines
1.8 KiB
Go

package bm
import (
"context"
"time"
"git.golem15.com/golem15/summercms/modules/lighthouse"
"git.golem15.com/jakub/sm-bm-plugin/classes"
"git.golem15.com/jakub/sm-bm-plugin/controllers/api"
"gorm.io/gorm"
)
// registerMaterialsRealtime registers the authorizer of the materials
// namespace: channel materials:{id} carries the live revision heads-up of
// one material (D-20) and is open only to whoever may manage it.
func (p *Plugin) registerMaterialsRealtime(svc *lighthouse.Service) error {
return svc.Registry().Register(classes.MaterialsNamespace, lighthouse.AuthorizerFunc(p.authorizeMaterial))
}
// authorizeMaterial allows a subscribe to materials:{id} only when the
// material is visible to the user and they may manage it (jz.bm.access_materials
// and its author, or any such user while it has no author). It checks the
// current state on every subscribe. The deny reasons are for the logs.
func (p *Plugin) authorizeMaterial(ctx context.Context, userID uint, channel string) lighthouse.Result {
id, ok := classes.MaterialChannelID(channel)
if !ok {
return lighthouse.Denied("malformed material channel")
}
db := p.database()
if db == nil {
return lighthouse.Denied("database unavailable")
}
allowed, err := p.canWatchMaterial(ctx, db, userID, id)
if err != nil {
return lighthouse.Denied("material lookup failed")
}
if !allowed {
return lighthouse.Denied("not the material's manager")
}
return lighthouse.Allowed(nil)
}
// canWatchMaterial runs the watchMaterial seam, or api.CanWatchMaterial at
// the current time by default.
func (p *Plugin) canWatchMaterial(ctx context.Context, db *gorm.DB, userID, id uint) (bool, error) {
if p.watchMaterial != nil {
return p.watchMaterial(ctx, db, userID, id)
}
return api.CanWatchMaterial(ctx, db, time.Now(), userID, id)
}