summaryrefslogtreecommitdiff
path: root/internal/service/media_access.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-01 20:14:19 +0300
committerPaul Buetow <paul@buetow.org>2026-05-01 20:14:19 +0300
commit74c2e0982f336ab135d8b63d26fa49bcd58e57a9 (patch)
tree689b764fadd7d6ca35598c131d0552b3d9374e3d /internal/service/media_access.go
parent4e35889c33491be33f8d557affb1c9d822372e7a (diff)
service: split media.go (745 lines) into 5 focused files
Split the monolithic media.go into cohesive files to fix KISS/SRP violation: - media_access.go: permission verification helpers (verifyAccess, verifyModifyAccess, verifySetModifyAccess) - media_browse.go: browsing, listing, streaming, thumbnails, set cover, tags and favorites - media_write.go: upload, create, soft-delete, restore - media_share.go: share token creation, validation, revocation, streaming via token - media_notes.go: note get/upsert/delete The shared mediaService struct, NewMediaService constructor, and common helpers (supported extensions, type guessing, thumbnail generation) remain in media.go. No functional changes — all tests pass.
Diffstat (limited to 'internal/service/media_access.go')
-rw-r--r--internal/service/media_access.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/internal/service/media_access.go b/internal/service/media_access.go
new file mode 100644
index 0000000..7320c94
--- /dev/null
+++ b/internal/service/media_access.go
@@ -0,0 +1,121 @@
+package service
+
+import (
+ "context"
+ "fmt"
+
+ "codeberg.org/snonux/player/internal/model"
+)
+
+func (s *mediaService) verifyAccess(ctx context.Context, mediaID, userID int64) (*model.Media, error) {
+ media, err := s.store.GetMediaByID(ctx, mediaID)
+ if err != nil {
+ return nil, fmt.Errorf("get media: %w", err)
+ }
+ if media == nil || media.DeletedAt != nil {
+ return nil, ErrNotFound
+ }
+
+ user, err := s.store.GetUserByID(ctx, userID)
+ if err != nil {
+ return nil, fmt.Errorf("get user: %w", err)
+ }
+ if user != nil && user.IsAdmin {
+ return media, nil
+ }
+
+ set, err := s.store.GetSetByID(ctx, media.SetID)
+ if err != nil {
+ return nil, fmt.Errorf("get set: %w", err)
+ }
+ if set == nil {
+ return nil, ErrNotFound
+ }
+
+ for _, p := range set.Permissions {
+ if p.UserID == userID {
+ return media, nil
+ }
+ }
+
+ perm, err := s.store.GetPermission(ctx, media.SetID, userID)
+ if err != nil {
+ return nil, fmt.Errorf("get permission: %w", err)
+ }
+ if perm != nil {
+ return media, nil
+ }
+
+ return nil, ErrForbidden
+}
+
+// verifyModifyAccess checks that the user has access to the media and is an owner or admin.
+func (s *mediaService) verifyModifyAccess(ctx context.Context, mediaID, userID int64) (*model.Media, error) {
+ media, err := s.verifyAccess(ctx, mediaID, userID)
+ if err != nil {
+ return nil, err
+ }
+
+ user, err := s.store.GetUserByID(ctx, userID)
+ if err != nil {
+ return nil, fmt.Errorf("get user: %w", err)
+ }
+ if user != nil && user.IsAdmin {
+ return media, nil
+ }
+
+ perm, err := s.store.GetPermission(ctx, media.SetID, userID)
+ if err != nil {
+ return nil, fmt.Errorf("get permission: %w", err)
+ }
+ if perm != nil && perm.Role == model.RoleOwner {
+ return media, nil
+ }
+
+ set, err := s.store.GetSetByID(ctx, media.SetID)
+ if err != nil {
+ return nil, fmt.Errorf("get set: %w", err)
+ }
+ if set != nil {
+ for _, p := range set.Permissions {
+ if p.UserID == userID && p.Role == model.RoleOwner {
+ return media, nil
+ }
+ }
+ }
+
+ return nil, ErrForbidden
+}
+
+// verifySetModifyAccess checks that the user is an owner or admin for a set.
+func (s *mediaService) verifySetModifyAccess(ctx context.Context, setID, userID int64) error {
+ user, err := s.store.GetUserByID(ctx, userID)
+ if err != nil {
+ return fmt.Errorf("get user: %w", err)
+ }
+ if user != nil && user.IsAdmin {
+ return nil
+ }
+
+ perm, err := s.store.GetPermission(ctx, setID, userID)
+ if err != nil {
+ return fmt.Errorf("get permission: %w", err)
+ }
+ if perm != nil && perm.Role == model.RoleOwner {
+ return nil
+ }
+
+ set, err := s.store.GetSetByID(ctx, setID)
+ if err != nil {
+ return fmt.Errorf("get set: %w", err)
+ }
+ if set != nil {
+ for _, p := range set.Permissions {
+ if p.UserID == userID && p.Role == model.RoleOwner {
+ return nil
+ }
+ }
+ }
+
+ return ErrForbidden
+}