Create accounts automatically when authenticating from HTTP header (#2087)

* Create accounts automatically when authenticating from HTTP header

* Disable password check when header auth is enabled

* Formatting

* Password change is valid when no password (old or new) is provided

* Test suite runs with header auth disabled (mock config)
Prevents nil pointer access (panic) while testing password validating logic

* Use a constant prefix for autogenerated passwords (header auth case)

* Add tests

* Add context to log messages

Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
selfhoster1312
2023-01-25 02:18:10 +01:00
committed by GitHub
parent 9721ef8974
commit 1e24809ed6
4 changed files with 60 additions and 7 deletions
+10 -5
View File
@@ -5,6 +5,7 @@ import (
"crypto/sha256"
"errors"
"fmt"
"strings"
"sync"
"time"
@@ -206,12 +207,16 @@ func validatePasswordChange(newUser *model.User, logged *model.User) error {
if logged.IsAdmin && newUser.ID != logged.ID {
return nil
}
if newUser.NewPassword != "" && newUser.CurrentPassword == "" {
err.Errors["currentPassword"] = "ra.validation.required"
if newUser.NewPassword == "" {
if newUser.CurrentPassword == "" {
return nil
}
err.Errors["password"] = "ra.validation.required"
}
if newUser.CurrentPassword != "" {
if newUser.NewPassword == "" {
err.Errors["password"] = "ra.validation.required"
if !strings.HasPrefix(logged.Password, consts.PasswordAutogenPrefix) {
if newUser.CurrentPassword == "" {
err.Errors["currentPassword"] = "ra.validation.required"
}
if newUser.CurrentPassword != logged.Password {
err.Errors["currentPassword"] = "ra.validation.passwordDoesNotMatch"
+30
View File
@@ -6,6 +6,8 @@ import (
"github.com/beego/beego/v2/client/orm"
"github.com/deluan/rest"
"github.com/google/uuid"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/tests"
@@ -81,6 +83,34 @@ var _ = Describe("UserRepository", func() {
Expect(err).To(BeNil())
})
Context("Autogenerated password (used with Reverse Proxy Authentication)", func() {
var user model.User
BeforeEach(func() {
loggedUser.IsAdmin = false
loggedUser.Password = consts.PasswordAutogenPrefix + uuid.NewString()
})
It("does nothing if passwords are not specified", func() {
user = *loggedUser
err := validatePasswordChange(&user, loggedUser)
Expect(err).To(BeNil())
})
It("does not requires currentPassword for regular user", func() {
user = *loggedUser
user.CurrentPassword = ""
user.NewPassword = "new"
err := validatePasswordChange(&user, loggedUser)
Expect(err).ToNot(HaveOccurred())
})
It("does not requires currentPassword for admin", func() {
loggedUser.IsAdmin = true
user = *loggedUser
user.CurrentPassword = ""
user.NewPassword = "new"
err := validatePasswordChange(&user, loggedUser)
Expect(err).ToNot(HaveOccurred())
})
})
Context("Logged User is admin", func() {
BeforeEach(func() {
loggedUser.IsAdmin = true