- 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
51 lines
1.8 KiB
Go
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)
|
|
}
|