Register lighthouse user:{id} if the namespace is free, fire user.Deleting before unscoped delete, and backfill missing handles.
Co-authored-by: Cursor <cursoragent@cursor.com>
50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
package classes
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"strings"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/backpack"
|
|
"git.golem15.com/golem15/summercms/modules/lighthouse"
|
|
)
|
|
|
|
// AuthorizeUser is the lighthouse authorizer for the user namespace
|
|
// (D-17, T-19-10). It allows only user:{id} for that user. ChannelID is
|
|
// the two-segment reader (segment 1 is the id). A second presence: prefix
|
|
// or extra segments are denied.
|
|
func AuthorizeUser() lighthouse.AuthorizerFunc {
|
|
return func(_ context.Context, userID uint, channel string) lighthouse.Result {
|
|
name := strings.TrimPrefix(channel, "presence:")
|
|
if strings.HasPrefix(name, "presence:") {
|
|
return lighthouse.Denied("invalid user channel")
|
|
}
|
|
parts := strings.Split(name, ":")
|
|
if len(parts) != 2 || parts[0] != "user" {
|
|
return lighthouse.Denied("invalid user channel")
|
|
}
|
|
if userID == 0 || lighthouse.ChannelID(name) != int64(userID) {
|
|
return lighthouse.Denied("not that user")
|
|
}
|
|
return lighthouse.Allowed(nil)
|
|
}
|
|
}
|
|
|
|
// RegisterUserAuthorizer registers the user namespace if it is free. A
|
|
// missing lighthouse service is skipped so Boot stays additive on hosts
|
|
// that never mount realtime.
|
|
func RegisterUserAuthorizer(app *backpack.App) error {
|
|
svc, err := lighthouse.From(app)
|
|
if err != nil {
|
|
slog.Default().Warn("golem15.user: lighthouse unavailable; user authorizer not registered", "err", err)
|
|
return nil
|
|
}
|
|
if svc == nil || svc.Registry() == nil {
|
|
return nil
|
|
}
|
|
if _, ok := svc.Registry().Get("user"); ok {
|
|
return nil
|
|
}
|
|
return svc.Registry().Register("user", AuthorizeUser())
|
|
}
|