Allow password changes when you don't have one yet

This commit is contained in:
Ben Visness 2023-05-04 23:21:22 -05:00
parent 9b441333a7
commit 2ba2fa4d7d
2 changed files with 37 additions and 25 deletions

View File

@ -81,18 +81,20 @@
</div> </div>
<div class="tab" data-name="Password" data-slug="password"> <div class="tab" data-name="Password" data-slug="password">
<div class="edit-form-row"> {{ if .HasPassword }}
<div class="pt-input-ns">Old password:</div> <div class="edit-form-row">
<div> <div class="pt-input-ns">Old password:</div>
<input id="id_old_password" name="old_password" type="password" /> <div>
<input id="id_old_password" name="old_password" type="password" />
</div>
</div> </div>
</div> {{ end }}
<div class="edit-form-row"> <div class="edit-form-row">
<div class="pt-input-ns">New password:</div> <div class="pt-input-ns">New password:</div>
<div> <div>
<input name="new_password" type="password" /> <input name="new_password" type="password" />
<div class="c--dim f7 mw6"> <div class="c--dim f7 mw6">
Your password must be 8 or more characters, and must differ from your username and current password. Your password must be 8 or more characters, and must differ from your username{{ if .HasPassword }} and current password{{ end }}.
Other than that, <a href="http://krebsonsecurity.com/password-dos-and-donts/" class="external" target="_blank">please follow best practices</a>. Other than that, <a href="http://krebsonsecurity.com/password-dos-and-donts/" class="external" target="_blank">please follow best practices</a>.
</div> </div>
</div> </div>

View File

@ -213,10 +213,11 @@ func UserSettings(c *RequestContext) ResponseData {
AvatarMaxFileSize int AvatarMaxFileSize int
DefaultAvatarUrl string DefaultAvatarUrl string
User templates.User User templates.User
Email string // these fields are handled specially on templates.User Email string // these fields are handled specially on templates.User
ShowEmail bool ShowEmail bool
LinksText string LinksText string
HasPassword bool
SubmitUrl string SubmitUrl string
ContactUrl string ContactUrl string
@ -292,6 +293,7 @@ func UserSettings(c *RequestContext) ResponseData {
Email: c.CurrentUser.Email, Email: c.CurrentUser.Email,
ShowEmail: c.CurrentUser.ShowEmail, ShowEmail: c.CurrentUser.ShowEmail,
LinksText: linksText, LinksText: linksText,
HasPassword: c.CurrentUser.Password != "",
SubmitUrl: hmnurl.BuildUserSettings(""), SubmitUrl: hmnurl.BuildUserSettings(""),
ContactUrl: hmnurl.BuildContactPage(), ContactUrl: hmnurl.BuildContactPage(),
@ -424,7 +426,13 @@ func UserSettingsSave(c *RequestContext) ResponseData {
// Update password // Update password
oldPassword := form.Get("old_password") oldPassword := form.Get("old_password")
newPassword := form.Get("new_password") newPassword := form.Get("new_password")
if oldPassword != "" && newPassword != "" { var doChangePassword bool
if c.CurrentUser.Password == "" {
doChangePassword = newPassword != ""
} else {
doChangePassword = oldPassword != "" && newPassword != ""
}
if doChangePassword {
errorRes := updatePassword(c, tx, oldPassword, newPassword) errorRes := updatePassword(c, tx, oldPassword, newPassword)
if errorRes != nil { if errorRes != nil {
return *errorRes return *errorRes
@ -558,25 +566,27 @@ func UserProfileAdminNuke(c *RequestContext) ResponseData {
} }
func updatePassword(c *RequestContext, tx pgx.Tx, old, new string) *ResponseData { func updatePassword(c *RequestContext, tx pgx.Tx, old, new string) *ResponseData {
oldHashedPassword, err := auth.ParsePasswordString(c.CurrentUser.Password) if c.CurrentUser.Password != "" {
if err != nil { oldHashedPassword, err := auth.ParsePasswordString(c.CurrentUser.Password)
c.Logger.Warn().Err(err).Msg("failed to parse user's password string") if err != nil {
return nil c.Logger.Warn().Err(err).Msg("failed to parse user's password string")
} return nil
}
ok, err := auth.CheckPassword(old, oldHashedPassword) ok, err := auth.CheckPassword(old, oldHashedPassword)
if err != nil { if err != nil {
res := c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to check user's password")) res := c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to check user's password"))
return &res return &res
} }
if !ok { if !ok {
res := c.RejectRequest("The old password you provided was not correct.") res := c.RejectRequest("The old password you provided was not correct.")
return &res return &res
}
} }
newHashedPassword := auth.HashPassword(new) newHashedPassword := auth.HashPassword(new)
err = auth.UpdatePassword(c, tx, c.CurrentUser.Username, newHashedPassword) err := auth.UpdatePassword(c, tx, c.CurrentUser.Username, newHashedPassword)
if err != nil { if err != nil {
res := c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to update password")) res := c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to update password"))
return &res return &res