CLI: Improve length check in "photoprism passwd" command #3482
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
054a0764c5
commit
87b6d72477
6 changed files with 26 additions and 19 deletions
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
"github.com/photoprism/photoprism/pkg/clean"
|
"github.com/photoprism/photoprism/pkg/clean"
|
||||||
"github.com/photoprism/photoprism/pkg/rnd"
|
"github.com/photoprism/photoprism/pkg/rnd"
|
||||||
|
"github.com/photoprism/photoprism/pkg/txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PasswdCommand configures the command name, flags, and action.
|
// PasswdCommand configures the command name, flags, and action.
|
||||||
|
@ -67,12 +68,14 @@ func passwdAction(ctx *cli.Context) error {
|
||||||
return fmt.Errorf("user %s has been deleted", clean.LogQuote(id))
|
return fmt.Errorf("user %s has been deleted", clean.LogQuote(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("please enter a new password for %s (minimum %d characters)\n", clean.Log(m.Username()), entity.PasswordLength)
|
log.Infof("please enter a new password for %s (%d-%d characters)\n", clean.Log(m.Username()), entity.PasswordLength, txt.ClipPassword)
|
||||||
|
|
||||||
newPassword := getPassword("New Password: ")
|
newPassword := getPassword("New Password: ")
|
||||||
|
|
||||||
if len(newPassword) < 6 {
|
if len([]rune(newPassword)) < entity.PasswordLength {
|
||||||
return errors.New("new password is too short, please try again")
|
return fmt.Errorf("password must have at least %d characters", entity.PasswordLength)
|
||||||
|
} else if len(newPassword) > txt.ClipPassword {
|
||||||
|
return fmt.Errorf("password must have less than %d characters", txt.ClipPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
retypePassword := getPassword("Retype Password: ")
|
retypePassword := getPassword("Retype Password: ")
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
"github.com/photoprism/photoprism/internal/form"
|
"github.com/photoprism/photoprism/internal/form"
|
||||||
"github.com/photoprism/photoprism/pkg/clean"
|
"github.com/photoprism/photoprism/pkg/clean"
|
||||||
|
"github.com/photoprism/photoprism/pkg/txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UsersAddCommand configures the command name, flags, and action.
|
// UsersAddCommand configures the command name, flags, and action.
|
||||||
|
@ -90,10 +91,12 @@ func usersAddAction(ctx *cli.Context) error {
|
||||||
frm.UserEmail = clean.Email(res)
|
frm.UserEmail = clean.Email(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
if interactive && len(ctx.String("password")) < entity.PasswordLength {
|
if interactive && len([]rune(ctx.String("password"))) < entity.PasswordLength {
|
||||||
validate := func(input string) error {
|
validate := func(input string) error {
|
||||||
if len(input) < entity.PasswordLength {
|
if len([]rune(input)) < entity.PasswordLength {
|
||||||
return fmt.Errorf("password must have at least %d characters", entity.PasswordLength)
|
return fmt.Errorf("password must have at least %d characters", entity.PasswordLength)
|
||||||
|
} else if len(input) > txt.ClipPassword {
|
||||||
|
return fmt.Errorf("password must have less than %d characters", txt.ClipPassword)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ const (
|
||||||
// UsernameLength specifies the minimum length of the username in characters.
|
// UsernameLength specifies the minimum length of the username in characters.
|
||||||
var UsernameLength = 1
|
var UsernameLength = 1
|
||||||
|
|
||||||
// PasswordLength specifies the minimum length of the password in characters.
|
// PasswordLength specifies the minimum length of a password in characters (runes, not bytes).
|
||||||
var PasswordLength = 4
|
var PasswordLength = 4
|
||||||
|
|
||||||
// UsersPath is the relative path for user assets.
|
// UsersPath is the relative path for user assets.
|
||||||
|
@ -768,8 +768,10 @@ func (m *User) SetPassword(password string) error {
|
||||||
return fmt.Errorf("only registered users can change their password")
|
return fmt.Errorf("only registered users can change their password")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(password) < PasswordLength {
|
if len([]rune(password)) < PasswordLength {
|
||||||
return fmt.Errorf("password must have at least %d characters", PasswordLength)
|
return fmt.Errorf("password must have at least %d characters", PasswordLength)
|
||||||
|
} else if len(password) > txt.ClipPassword {
|
||||||
|
return fmt.Errorf("password must have less than %d characters", txt.ClipPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
pw := NewPassword(m.UserUID, password, false)
|
pw := NewPassword(m.UserUID, password, false)
|
||||||
|
|
|
@ -7,14 +7,17 @@ import (
|
||||||
|
|
||||||
"github.com/photoprism/photoprism/internal/form"
|
"github.com/photoprism/photoprism/internal/form"
|
||||||
"github.com/photoprism/photoprism/pkg/clean"
|
"github.com/photoprism/photoprism/pkg/clean"
|
||||||
|
"github.com/photoprism/photoprism/pkg/txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddUser creates a new user record and sets the password in a single transaction.
|
// AddUser creates a new user record and sets the password in a single transaction.
|
||||||
func AddUser(frm form.User) error {
|
func AddUser(frm form.User) error {
|
||||||
user := NewUser().SetFormValues(frm)
|
user := NewUser().SetFormValues(frm)
|
||||||
|
|
||||||
if len(frm.Password) < PasswordLength {
|
if len([]rune(frm.Password)) < PasswordLength {
|
||||||
return fmt.Errorf("password must have at least %d characters", PasswordLength)
|
return fmt.Errorf("password must have at least %d characters", PasswordLength)
|
||||||
|
} else if len(frm.Password) > txt.ClipPassword {
|
||||||
|
return fmt.Errorf("password must have less than %d characters", txt.ClipPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := user.Validate(); err != nil {
|
if err := user.Validate(); err != nil {
|
||||||
|
|
|
@ -46,12 +46,14 @@ func NewPassword(uid, pw string, allowHash bool) Password {
|
||||||
|
|
||||||
// SetPassword sets a new password stored as hash.
|
// SetPassword sets a new password stored as hash.
|
||||||
func (m *Password) SetPassword(pw string, allowHash bool) error {
|
func (m *Password) SetPassword(pw string, allowHash bool) error {
|
||||||
|
// Remove leading and trailing white space.
|
||||||
pw = clean.Password(pw)
|
pw = clean.Password(pw)
|
||||||
|
|
||||||
if l := len(pw); l > txt.ClipPassword {
|
// Check if password is too short or too long.
|
||||||
return fmt.Errorf("password is too long")
|
if len([]rune(pw)) < 1 {
|
||||||
} else if l < 1 {
|
|
||||||
return fmt.Errorf("password is too short")
|
return fmt.Errorf("password is too short")
|
||||||
|
} else if len(pw) > txt.ClipPassword {
|
||||||
|
return fmt.Errorf("password must have less than %d characters", txt.ClipPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if string already is a bcrypt hash.
|
// Check if string already is a bcrypt hash.
|
||||||
|
|
|
@ -109,13 +109,7 @@ func Attr(s string) string {
|
||||||
return list.ParseAttr(s).String()
|
return list.ParseAttr(s).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password returns the sanitized password string with trimmed whitespace.
|
// Password returns the password string with all leading and trailing white space removed.
|
||||||
func Password(s string) string {
|
func Password(s string) string {
|
||||||
s = strings.TrimSpace(s)
|
return strings.TrimSpace(s)
|
||||||
|
|
||||||
if s == "" || reject(s, txt.ClipPassword) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue