d262f734f0
* mobile: wire notification registration and listener
* implement backend components for push notifications
* refactor: agentic comment cleanup
* docs: use proper module name for particle processor
* set required env variables for push notifications
* bump version
* fix: always upsert push token on mobile start
* Revert "fix: always upsert push token on mobile start"
This reverts commit 90ff18a788.
* send push notifications regardless of online status
71 lines
1.6 KiB
Go
71 lines
1.6 KiB
Go
package pusher
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
"github.com/flowy-live/llink/internal/network"
|
|
)
|
|
|
|
var ErrUnauthorized = errors.New("unauthorized")
|
|
|
|
type Authorizer struct {
|
|
networkReader network.Reader
|
|
}
|
|
|
|
func NewAuthorizer(networkReader network.Reader) *Authorizer {
|
|
return &Authorizer{networkReader: networkReader}
|
|
}
|
|
|
|
// Authorize accepts channel IDs of the form:
|
|
//
|
|
// network:{networkId}
|
|
// stream:{networkId}:{streamId}
|
|
// _presence:{humanId}
|
|
func (a *Authorizer) Authorize(ctx context.Context, channelID, humanID string) error {
|
|
parts := strings.SplitN(channelID, ":", 2)
|
|
if len(parts) < 2 {
|
|
return ErrUnauthorized
|
|
}
|
|
|
|
channelType := parts[0]
|
|
rest := parts[1]
|
|
|
|
switch channelType {
|
|
case "network":
|
|
return a.authorizeNetwork(ctx, rest, humanID)
|
|
case "stream":
|
|
return a.authorizeStream(ctx, rest, humanID)
|
|
case "_presence":
|
|
// Only the owning human may subscribe to their presence channel.
|
|
if rest != humanID {
|
|
return ErrUnauthorized
|
|
}
|
|
return nil
|
|
default:
|
|
return ErrUnauthorized
|
|
}
|
|
}
|
|
|
|
func (a *Authorizer) authorizeNetwork(ctx context.Context, networkID, humanID string) error {
|
|
isMember, err := a.networkReader.IsMember(ctx, networkID, humanID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !isMember {
|
|
return ErrUnauthorized
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// rest is "{networkId}:{streamId}"; stream-level visibility is enforced by network access.
|
|
func (a *Authorizer) authorizeStream(ctx context.Context, rest, humanID string) error {
|
|
parts := strings.SplitN(rest, ":", 2)
|
|
if len(parts) < 2 {
|
|
return ErrUnauthorized
|
|
}
|
|
networkID := parts[0]
|
|
return a.authorizeNetwork(ctx, networkID, humanID)
|
|
}
|