Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
4.2 kB · 127 lines
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128package moderation
import ( "context" "fmt" "time"
"stream.place/streamplace/pkg/placestream")
type delegationGetter interface { GetModerationDelegations(ctx context.Context, streamerDID, moderatorDID string) ([]placestream.ModerationDefs_PermissionView, error)}
// Permission scope constantsconst ( PermissionBan = "ban" PermissionHide = "hide" PermissionLivestreamManage = "livestream.manage" PermissionMessagePin = "message.pin" PermissionVodCommentHide = "vod.comment.hide")
// ActionPermissions maps moderation actions to required permissionsvar ActionPermissions = map[string]string{ "createBlock": PermissionBan, "deleteBlock": PermissionBan, "createGate": PermissionHide, "deleteGate": PermissionHide, "createVodGate": PermissionVodCommentHide, "deleteVodGate": PermissionVodCommentHide, "updateLivestream": PermissionLivestreamManage, // A streamer's recordings and video records: what the app's Livestreams // tab does, for a moderator the streamer trusts with their channel. "finalizeLivestream": PermissionLivestreamManage, "listVideos": PermissionLivestreamManage, "publishVideo": PermissionLivestreamManage, "updateVideo": PermissionLivestreamManage, "deleteVideo": PermissionLivestreamManage, "createPin": PermissionMessagePin, "deletePin": PermissionMessagePin,}
// PermissionChecker validates moderation permissionstype PermissionChecker struct { model delegationGetter}
// NewPermissionChecker creates a new permission checkerfunc NewPermissionChecker(m delegationGetter) *PermissionChecker { return &PermissionChecker{model: m}}
// CheckPermission validates that a moderator has permission to perform an action// Returns an error if the moderator lacks the required permissionfunc (pc *PermissionChecker) CheckPermission(ctx context.Context, moderatorDID, streamerDID, action string) error { // Get required permission for this action (validate action first) requiredPermission, ok := ActionPermissions[action] if !ok { return fmt.Errorf("unknown action: %s", action) }
// Streamers always have permission for their own content if moderatorDID == streamerDID { return nil }
// Check if moderator has the required permission hasPermission, err := pc.HasPermission(ctx, moderatorDID, streamerDID, requiredPermission) if err != nil { return fmt.Errorf("failed to check permissions: %w", err) }
if !hasPermission { return fmt.Errorf("moderator %s does not have permission '%s' for streamer %s", moderatorDID, requiredPermission, streamerDID) }
return nil}
// HasPermission checks if a moderator has a specific permission for a streamer.// It merges permissions from ALL delegation records for the moderator.func (pc *PermissionChecker) HasPermission(ctx context.Context, moderatorDID, streamerDID, permission string) (bool, error) { // Streamers always have all permissions for their own content if moderatorDID == streamerDID { return true, nil }
// Look up ALL delegation records for this moderator delegations, err := pc.model.GetModerationDelegations(ctx, streamerDID, moderatorDID) if err != nil { return false, fmt.Errorf("failed to get moderation delegations: %w", err) }
if len(delegations) == 0 { return false, nil }
// Check all delegation records and merge their permissions for _, delegationView := range delegations { // Extract the actual permission record from the view permRecord, ok := delegationView.Record.Val.(*placestream.ModerationPermission) if !ok { return false, fmt.Errorf("failed to cast record to ModerationPermission") }
// Skip expired delegations if permRecord.ExpirationTime != nil { expirationTime, err := time.Parse(time.RFC3339, *permRecord.ExpirationTime) if err != nil { return false, fmt.Errorf("failed to parse expiration time: %w", err) } if time.Now().After(expirationTime) { continue } }
// Check if this delegation has the required permission for _, p := range permRecord.Permissions { if p == permission { return true, nil } } }
return false, nil}