mirror of
https://github.com/navidrome/navidrome.git
synced 2025-12-23 15:08:04 -05:00
fix(subsonic): add username parameter validation for GetUser endpoint
Fixes #4794 Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/model/request"
|
||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
"github.com/navidrome/navidrome/utils/req"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
)
|
||||
|
||||
@@ -35,7 +36,13 @@ func (api *Router) GetUser(r *http.Request) (*responses.Subsonic, error) {
|
||||
if !ok {
|
||||
return nil, newError(responses.ErrorGeneric, "Internal error")
|
||||
}
|
||||
|
||||
username, err := req.Params(r).String("username")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if username != loggedUser.UserName {
|
||||
return nil, newError(responses.ErrorAuthorizationFail)
|
||||
}
|
||||
response := newResponse()
|
||||
user := buildUserResponse(loggedUser)
|
||||
response.User = &user
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package subsonic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http/httptest"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
@@ -43,8 +43,8 @@ var _ = Describe("Users", func() {
|
||||
}
|
||||
|
||||
// Create request with user in context
|
||||
req := httptest.NewRequest("GET", "/rest/getUser", nil)
|
||||
ctx := request.WithUser(context.Background(), testUser)
|
||||
req := httptest.NewRequest("GET", "/rest/getUser?username=testuser", nil)
|
||||
ctx := request.WithUser(GinkgoT().Context(), testUser)
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
userResponse, err1 := router.GetUser(req)
|
||||
@@ -116,4 +116,60 @@ var _ = Describe("Users", func() {
|
||||
Expect(response.Folder).To(ContainElements(int32(1), int32(2), int32(5)))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("GetUser authorization", func() {
|
||||
It("should allow user to request their own information", func() {
|
||||
req := httptest.NewRequest("GET", "/rest/getUser?username=testuser", nil)
|
||||
ctx := request.WithUser(GinkgoT().Context(), testUser)
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
response, err := router.GetUser(req)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(response).ToNot(BeNil())
|
||||
Expect(response.User).ToNot(BeNil())
|
||||
Expect(response.User.Username).To(Equal("testuser"))
|
||||
})
|
||||
|
||||
It("should deny user from requesting another user's information", func() {
|
||||
req := httptest.NewRequest("GET", "/rest/getUser?username=anotheruser", nil)
|
||||
ctx := request.WithUser(GinkgoT().Context(), testUser)
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
response, err := router.GetUser(req)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(response).To(BeNil())
|
||||
|
||||
var subErr subError
|
||||
ok := errors.As(err, &subErr)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(subErr.code).To(Equal(responses.ErrorAuthorizationFail))
|
||||
})
|
||||
|
||||
It("should return error when username parameter is missing", func() {
|
||||
req := httptest.NewRequest("GET", "/rest/getUser", nil)
|
||||
ctx := request.WithUser(GinkgoT().Context(), testUser)
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
response, err := router.GetUser(req)
|
||||
|
||||
Expect(err).To(MatchError("missing parameter: 'username'"))
|
||||
Expect(response).To(BeNil())
|
||||
})
|
||||
|
||||
It("should return error when user context is missing", func() {
|
||||
req := httptest.NewRequest("GET", "/rest/getUser?username=testuser", nil)
|
||||
|
||||
response, err := router.GetUser(req)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(response).To(BeNil())
|
||||
|
||||
var subErr subError
|
||||
ok := errors.As(err, &subErr)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(subErr.code).To(Equal(responses.ErrorGeneric))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user