diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-30 11:28:21 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-30 11:28:21 +0300 |
| commit | 100a9bb282dd4226368b4e5fac398726c7acf653 (patch) | |
| tree | 61730d7bc0d10cddd674ba24438dad2a381b88d1 /internal/service/no_rows_test.go | |
| parent | adecf1fd2e55a0605d03f36952846f6336506d37 (diff) | |
task da: enforce media access and owner/admin role permissions
Changes:
- MediaService.ListMedia now accepts userID and filters by allowed sets
for non-admins via AllowedSetIDs in repository.MediaFilter.
- Handlers pass userID into ListMedia; API returns 403 for forbidden.
- Added verifyModifyAccess and verifySetModifyAccess helpers so only
owners/admins can upload, soft-delete, restore, and regenerate
thumbnails/covers; viewers are blocked.
- GetMediaDetail, ToggleFavorite, AssignTag, RemoveTag, notes, and
shares now consistently verifyAccess before proceeding.
- Handlers handle ErrForbidden with 403 for soft-delete and restore.
- Added negative tests proving viewers cannot mutate and unauthorized
users cannot access/detail/tag/note/favorite/share inaccessible media.
Diffstat (limited to 'internal/service/no_rows_test.go')
| -rw-r--r-- | internal/service/no_rows_test.go | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/internal/service/no_rows_test.go b/internal/service/no_rows_test.go index 4d512e5..3606b63 100644 --- a/internal/service/no_rows_test.go +++ b/internal/service/no_rows_test.go @@ -22,8 +22,8 @@ func TestService_NoRows_ReturnsNil(t *testing.T) { } svc := NewMediaService(store, newMockClock(), "/tmp/media") detail, err := svc.GetMediaDetail(ctx, 99, 1) - if err != nil { - t.Fatalf("expected no error, got %v", err) + if !errors.Is(err, ErrNotFound) { + t.Fatalf("expected ErrNotFound, got %v", err) } if detail != nil { t.Fatalf("expected nil detail, got %+v", detail) @@ -32,6 +32,21 @@ func TestService_NoRows_ReturnsNil(t *testing.T) { t.Run("GetNote nil", func(t *testing.T) { store := &repository.MockStore{ + MediaRepo: repository.MockMediaRepo{ + GetMediaByIDFunc: func(ctx context.Context, id int64) (*model.Media, error) { + return &model.Media{ID: 1, SetID: 1}, nil + }, + }, + UserRepo: repository.MockUserRepo{ + GetUserByIDFunc: func(ctx context.Context, id int64) (*model.User, error) { + return &model.User{ID: id, IsAdmin: true}, nil + }, + }, + SetRepo: repository.MockSetRepo{ + GetSetByIDFunc: func(ctx context.Context, id int64) (*model.Set, error) { + return &model.Set{ID: id}, nil + }, + }, NoteRepo: repository.MockNoteRepo{ GetNoteFunc: func(ctx context.Context, mediaID, userID int64) (*model.Note, error) { return nil, nil @@ -50,6 +65,21 @@ func TestService_NoRows_ReturnsNil(t *testing.T) { t.Run("AssignTag creates missing tag", func(t *testing.T) { store := &repository.MockStore{ + MediaRepo: repository.MockMediaRepo{ + GetMediaByIDFunc: func(ctx context.Context, id int64) (*model.Media, error) { + return &model.Media{ID: 1, SetID: 1}, nil + }, + }, + UserRepo: repository.MockUserRepo{ + GetUserByIDFunc: func(ctx context.Context, id int64) (*model.User, error) { + return &model.User{ID: id, IsAdmin: true}, nil + }, + }, + SetRepo: repository.MockSetRepo{ + GetSetByIDFunc: func(ctx context.Context, id int64) (*model.Set, error) { + return &model.Set{ID: id}, nil + }, + }, TagRepo: repository.MockTagRepo{ GetTagByNameFunc: func(ctx context.Context, name string) (*model.Tag, error) { return nil, nil |
