diff options
Diffstat (limited to 'internal/handlers/handler_change_password.go')
| -rw-r--r-- | internal/handlers/handler_change_password.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/internal/handlers/handler_change_password.go b/internal/handlers/handler_change_password.go new file mode 100644 index 000000000..cbdd25ddc --- /dev/null +++ b/internal/handlers/handler_change_password.go @@ -0,0 +1,105 @@ +package handlers + +import ( + "errors" + "fmt" + "net/http" + + "github.com/authelia/authelia/v4/internal/authentication" + "github.com/authelia/authelia/v4/internal/middlewares" + "github.com/authelia/authelia/v4/internal/session" + "github.com/authelia/authelia/v4/internal/templates" +) + +func ChangePasswordPOST(ctx *middlewares.AutheliaCtx) { + var ( + userSession session.UserSession + err error + ) + + if userSession, err = ctx.GetSession(); err != nil { + ctx.Error(fmt.Errorf("error occurred retrieving session for user: %w", err), messageUnableToChangePassword) + return + } + + username := userSession.Username + + var requestBody changePasswordRequestBody + + if err = ctx.ParseBody(&requestBody); err != nil { + ctx.Error(err, messageUnableToChangePassword) + return + } + + if err = ctx.Providers.PasswordPolicy.Check(requestBody.NewPassword); err != nil { + ctx.Error(err, messagePasswordWeak) + return + } + + if err = ctx.Providers.UserProvider.ChangePassword(username, requestBody.OldPassword, requestBody.NewPassword); err != nil { + ctx.Logger.WithError(err).Debugf("Unable to change password for user '%s'", username) + + switch { + case errors.Is(err, authentication.ErrIncorrectPassword): + ctx.SetJSONError(messageIncorrectPassword) + ctx.SetStatusCode(http.StatusUnauthorized) + case errors.Is(err, authentication.ErrPasswordWeak): + ctx.SetJSONError(messagePasswordWeak) + ctx.SetStatusCode(http.StatusBadRequest) + case errors.Is(err, authentication.ErrAuthenticationFailed): + ctx.SetJSONError(messageOperationFailed) + ctx.SetStatusCode(http.StatusUnauthorized) + default: + ctx.SetJSONError(messageOperationFailed) + ctx.SetStatusCode(http.StatusInternalServerError) + } + + return + } + + ctx.Logger.Debugf("User %s has changed their password", username) + + if err = ctx.SaveSession(userSession); err != nil { + ctx.Error(fmt.Errorf("unable to update password reset state: %w", err), messageOperationFailed) + return + } + + userInfo, err := ctx.Providers.UserProvider.GetDetails(username) + if err != nil { + ctx.Logger.Error(err) + ctx.ReplyOK() + + return + } + + if len(userInfo.Emails) == 0 { + ctx.Logger.Error(fmt.Errorf("user %s has no email address configured", username)) + ctx.ReplyOK() + + return + } + + data := templates.EmailEventValues{ + Title: "Password changed successfully", + DisplayName: userInfo.DisplayName, + RemoteIP: ctx.RemoteIP().String(), + Details: map[string]any{ + "Action": "Password Change", + }, + BodyPrefix: eventEmailActionPasswordModifyPrefix, + BodyEvent: eventEmailActionPasswordChange, + BodySuffix: eventEmailActionPasswordModifySuffix, + } + + addresses := userInfo.Addresses() + + ctx.Logger.Debugf("Sending an email to user %s (%s) to inform that the password has changed.", + username, addresses[0].String()) + + if err = ctx.Providers.Notifier.Send(ctx, addresses[0], "Password changed successfully", ctx.Providers.Templates.GetEventEmailTemplate(), data); err != nil { + ctx.Logger.Error(err) + ctx.ReplyOK() + + return + } +} |
