mirror of
https://github.com/navidrome/navidrome.git
synced 2025-12-23 23:18:05 -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"
|
||||||
"github.com/navidrome/navidrome/model/request"
|
"github.com/navidrome/navidrome/model/request"
|
||||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||||
|
"github.com/navidrome/navidrome/utils/req"
|
||||||
"github.com/navidrome/navidrome/utils/slice"
|
"github.com/navidrome/navidrome/utils/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +36,13 @@ func (api *Router) GetUser(r *http.Request) (*responses.Subsonic, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, newError(responses.ErrorGeneric, "Internal error")
|
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()
|
response := newResponse()
|
||||||
user := buildUserResponse(loggedUser)
|
user := buildUserResponse(loggedUser)
|
||||||
response.User = &user
|
response.User = &user
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package subsonic
|
package subsonic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"errors"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
|
||||||
"github.com/navidrome/navidrome/conf"
|
"github.com/navidrome/navidrome/conf"
|
||||||
@@ -43,8 +43,8 @@ var _ = Describe("Users", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create request with user in context
|
// Create request with user in context
|
||||||
req := httptest.NewRequest("GET", "/rest/getUser", nil)
|
req := httptest.NewRequest("GET", "/rest/getUser?username=testuser", nil)
|
||||||
ctx := request.WithUser(context.Background(), testUser)
|
ctx := request.WithUser(GinkgoT().Context(), testUser)
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
userResponse, err1 := router.GetUser(req)
|
userResponse, err1 := router.GetUser(req)
|
||||||
@@ -116,4 +116,60 @@ var _ = Describe("Users", func() {
|
|||||||
Expect(response.Folder).To(ContainElements(int32(1), int32(2), int32(5)))
|
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