mirror of
https://github.com/navidrome/navidrome.git
synced 2025-06-12 21:32:17 +03:00
fix(transcoding): restrict transcoding operations to admin users (#4096)
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
6ac3acaaf8
commit
e5438552c6
@ -65,6 +65,11 @@ func loggedUser(ctx context.Context) *model.User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isAdmin(ctx context.Context) bool {
|
||||||
|
user := loggedUser(ctx)
|
||||||
|
return user.IsAdmin
|
||||||
|
}
|
||||||
|
|
||||||
func (r *sqlRepository) registerModel(instance any, filters map[string]filterFunc) {
|
func (r *sqlRepository) registerModel(instance any, filters map[string]filterFunc) {
|
||||||
if r.tableName == "" {
|
if r.tableName == "" {
|
||||||
r.tableName = strings.TrimPrefix(reflect.TypeOf(instance).String(), "*model.")
|
r.tableName = strings.TrimPrefix(reflect.TypeOf(instance).String(), "*model.")
|
||||||
|
@ -41,6 +41,9 @@ func (r *transcodingRepository) FindByFormat(format string) (*model.Transcoding,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *transcodingRepository) Put(t *model.Transcoding) error {
|
func (r *transcodingRepository) Put(t *model.Transcoding) error {
|
||||||
|
if !isAdmin(r.ctx) {
|
||||||
|
return rest.ErrPermissionDenied
|
||||||
|
}
|
||||||
_, err := r.put(t.ID, t)
|
_, err := r.put(t.ID, t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -69,6 +72,9 @@ func (r *transcodingRepository) NewInstance() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *transcodingRepository) Save(entity interface{}) (string, error) {
|
func (r *transcodingRepository) Save(entity interface{}) (string, error) {
|
||||||
|
if !isAdmin(r.ctx) {
|
||||||
|
return "", rest.ErrPermissionDenied
|
||||||
|
}
|
||||||
t := entity.(*model.Transcoding)
|
t := entity.(*model.Transcoding)
|
||||||
id, err := r.put(t.ID, t)
|
id, err := r.put(t.ID, t)
|
||||||
if errors.Is(err, model.ErrNotFound) {
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
@ -78,6 +84,9 @@ func (r *transcodingRepository) Save(entity interface{}) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *transcodingRepository) Update(id string, entity interface{}, cols ...string) error {
|
func (r *transcodingRepository) Update(id string, entity interface{}, cols ...string) error {
|
||||||
|
if !isAdmin(r.ctx) {
|
||||||
|
return rest.ErrPermissionDenied
|
||||||
|
}
|
||||||
t := entity.(*model.Transcoding)
|
t := entity.(*model.Transcoding)
|
||||||
t.ID = id
|
t.ID = id
|
||||||
_, err := r.put(id, t)
|
_, err := r.put(id, t)
|
||||||
@ -88,6 +97,9 @@ func (r *transcodingRepository) Update(id string, entity interface{}, cols ...st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *transcodingRepository) Delete(id string) error {
|
func (r *transcodingRepository) Delete(id string) error {
|
||||||
|
if !isAdmin(r.ctx) {
|
||||||
|
return rest.ErrPermissionDenied
|
||||||
|
}
|
||||||
err := r.delete(Eq{"id": id})
|
err := r.delete(Eq{"id": id})
|
||||||
if errors.Is(err, model.ErrNotFound) {
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
return rest.ErrNotFound
|
return rest.ErrNotFound
|
||||||
|
96
persistence/transcoding_repository_test.go
Normal file
96
persistence/transcoding_repository_test.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package persistence
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/deluan/rest"
|
||||||
|
"github.com/navidrome/navidrome/log"
|
||||||
|
"github.com/navidrome/navidrome/model"
|
||||||
|
"github.com/navidrome/navidrome/model/request"
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("TranscodingRepository", func() {
|
||||||
|
var repo model.TranscodingRepository
|
||||||
|
var adminRepo model.TranscodingRepository
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
ctx := log.NewContext(GinkgoT().Context())
|
||||||
|
ctx = request.WithUser(ctx, regularUser)
|
||||||
|
repo = NewTranscodingRepository(ctx, GetDBXBuilder())
|
||||||
|
|
||||||
|
adminCtx := log.NewContext(GinkgoT().Context())
|
||||||
|
adminCtx = request.WithUser(adminCtx, adminUser)
|
||||||
|
adminRepo = NewTranscodingRepository(adminCtx, GetDBXBuilder())
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
// Clean up any transcoding created during the tests
|
||||||
|
tc, err := adminRepo.FindByFormat("test_format")
|
||||||
|
if err == nil {
|
||||||
|
err = adminRepo.(*transcodingRepository).Delete(tc.ID)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Admin User", func() {
|
||||||
|
It("creates a new transcoding", func() {
|
||||||
|
base, err := adminRepo.CountAll()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = adminRepo.Put(&model.Transcoding{ID: "new", Name: "new", TargetFormat: "test_format", DefaultBitRate: 320, Command: "ffmpeg"})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
count, err := adminRepo.CountAll()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(count).To(Equal(base + 1))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("updates an existing transcoding", func() {
|
||||||
|
tr := &model.Transcoding{ID: "upd", Name: "old", TargetFormat: "test_format", DefaultBitRate: 100, Command: "ffmpeg"}
|
||||||
|
Expect(adminRepo.Put(tr)).To(Succeed())
|
||||||
|
tr.Name = "updated"
|
||||||
|
err := adminRepo.Put(tr)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
res, err := adminRepo.FindByFormat("test_format")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(res.Name).To(Equal("updated"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("deletes a transcoding", func() {
|
||||||
|
err := adminRepo.Put(&model.Transcoding{ID: "to-delete", Name: "temp", TargetFormat: "test_format", DefaultBitRate: 256, Command: "ffmpeg"})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
err = adminRepo.(*transcodingRepository).Delete("to-delete")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
_, err = adminRepo.Get("to-delete")
|
||||||
|
Expect(err).To(MatchError(model.ErrNotFound))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Regular User", func() {
|
||||||
|
It("fails to create", func() {
|
||||||
|
err := repo.Put(&model.Transcoding{ID: "bad", Name: "bad", TargetFormat: "test_format", DefaultBitRate: 64, Command: "ffmpeg"})
|
||||||
|
Expect(err).To(Equal(rest.ErrPermissionDenied))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("fails to update", func() {
|
||||||
|
tr := &model.Transcoding{ID: "updreg", Name: "old", TargetFormat: "test_format", DefaultBitRate: 64, Command: "ffmpeg"}
|
||||||
|
Expect(adminRepo.Put(tr)).To(Succeed())
|
||||||
|
|
||||||
|
tr.Name = "bad"
|
||||||
|
err := repo.Put(tr)
|
||||||
|
Expect(err).To(Equal(rest.ErrPermissionDenied))
|
||||||
|
|
||||||
|
//_ = adminRepo.(*transcodingRepository).Delete("updreg")
|
||||||
|
})
|
||||||
|
|
||||||
|
It("fails to delete", func() {
|
||||||
|
tr := &model.Transcoding{ID: "delreg", Name: "temp", TargetFormat: "test_format", DefaultBitRate: 64, Command: "ffmpeg"}
|
||||||
|
Expect(adminRepo.Put(tr)).To(Succeed())
|
||||||
|
|
||||||
|
err := repo.(*transcodingRepository).Delete("delreg")
|
||||||
|
Expect(err).To(Equal(rest.ErrPermissionDenied))
|
||||||
|
|
||||||
|
//_ = adminRepo.(*transcodingRepository).Delete("delreg")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user