func ResetPasswdPost(ctx *context.Context) {
	u, twofa := commonResetPassword(ctx)
	if ctx.Written() {
		return
	}

	if u == nil {
		// Flash error has been set
		ctx.HTML(http.StatusOK, tplResetPassword)
		return
	}

	// Validate password length.
	passwd := ctx.Query("password")
	if len(passwd) < setting.MinPasswordLength {
		ctx.Data["IsResetForm"] = true
		ctx.Data["Err_Password"] = true
		ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplResetPassword, nil)
		return
	} else if !password.IsComplexEnough(passwd) {
		ctx.Data["IsResetForm"] = true
		ctx.Data["Err_Password"] = true
		ctx.RenderWithErr(password.BuildComplexityError(ctx), tplResetPassword, nil)
		return
	} else if pwned, err := password.IsPwned(ctx, passwd); pwned || err != nil {
		errMsg := ctx.Tr("auth.password_pwned")
		if err != nil {
			log.Error(err.Error())
			errMsg = ctx.Tr("auth.password_pwned_err")
		}
		ctx.Data["IsResetForm"] = true
		ctx.Data["Err_Password"] = true
		ctx.RenderWithErr(errMsg, tplResetPassword, nil)
		return
	}

	// Handle two-factor
	regenerateScratchToken := false
	if twofa != nil {
		if ctx.QueryBool("scratch_code") {
			if !twofa.VerifyScratchToken(ctx.Query("token")) {
				ctx.Data["IsResetForm"] = true
				ctx.Data["Err_Token"] = true
				ctx.RenderWithErr(ctx.Tr("auth.twofa_scratch_token_incorrect"), tplResetPassword, nil)
				return
			}
			regenerateScratchToken = true
		} else {
			passcode := ctx.Query("passcode")
			ok, err := twofa.ValidateTOTP(passcode)
			if err != nil {
				ctx.Error(http.StatusInternalServerError, "ValidateTOTP", err.Error())
				return
			}
			if !ok || twofa.LastUsedPasscode == passcode {
				ctx.Data["IsResetForm"] = true
				ctx.Data["Err_Passcode"] = true
				ctx.RenderWithErr(ctx.Tr("auth.twofa_passcode_incorrect"), tplResetPassword, nil)
				return
			}

			twofa.LastUsedPasscode = passcode
			if err = models.UpdateTwoFactor(twofa); err != nil {
				ctx.ServerError("ResetPasswdPost: UpdateTwoFactor", err)
				return
			}
		}
	}
	var err error
	if u.Rands, err = models.GetUserSalt(); err != nil {
		ctx.ServerError("UpdateUser", err)
		return
	}
	if err = u.SetPassword(passwd); err != nil {
		ctx.ServerError("UpdateUser", err)
		return
	}
	u.MustChangePassword = false
	if err := models.UpdateUserCols(u, "must_change_password", "passwd", "passwd_hash_algo", "rands", "salt"); err != nil {
		ctx.ServerError("UpdateUser", err)
		return
	}

	log.Trace("User password reset: %s", u.Name)
	ctx.Data["IsResetFailed"] = true
	remember := len(ctx.Query("remember")) != 0

	if regenerateScratchToken {
		// Invalidate the scratch token.
		_, err = twofa.GenerateScratchToken()
		if err != nil {
			ctx.ServerError("UserSignIn", err)
			return
		}
		if err = models.UpdateTwoFactor(twofa); err != nil {
			ctx.ServerError("UserSignIn", err)
			return
		}

		handleSignInFull(ctx, u, remember, false)
		ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
		ctx.Redirect(setting.AppSubURL + "/user/settings/security")
		return
	}

	handleSignInFull(ctx, u, remember, true)
}
// ResetPasswdPost response from account recovery request
ResetPasswdPost response from account recovery request
// ResetPasswdPost response from account recovery request
func ResetPasswdPost(ctx *context.Context) {
	u, twofa := commonResetPassword(ctx)
	if ctx.Written() {
		return
	}
	if u == nil {
		ctx.HTML(http.StatusOK, tplResetPassword)
		return
	}
	passwd := ctx.Query("password")
	if len(passwd) < setting.MinPasswordLength {
		ctx.Data["IsResetForm"] = true
		ctx.Data["Err_Password"] = true
		ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplResetPassword, nil)
		return
	} else if !password.IsComplexEnough(passwd) {
		ctx.Data["IsResetForm"] = true
		ctx.Data["Err_Password"] = true
		ctx.RenderWithErr(password.BuildComplexityError(ctx), tplResetPassword, nil)
		return
	} else if pwned, err := password.IsPwned(ctx, passwd); pwned || err != nil {
		errMsg := ctx.Tr("auth.password_pwned")
		if err != nil {
			log.Error(err.Error())
			errMsg = ctx.Tr("auth.password_pwned_err")
		}
		ctx.Data["IsResetForm"] = true
		ctx.Data["Err_Password"] = true
		ctx.RenderWithErr(errMsg, tplResetPassword, nil)
		return
	}
	regenerateScratchToken := false
	if twofa != nil {
		if ctx.QueryBool("scratch_code") {
			if !twofa.VerifyScratchToken(ctx.Query("token")) {
				ctx.Data["IsResetForm"] = true
				ctx.Data["Err_Token"] = true
				ctx.RenderWithErr(ctx.Tr("auth.twofa_scratch_token_incorrect"), tplResetPassword, nil)
				return
			}
			regenerateScratchToken = true
		} else {
			passcode := ctx.Query("passcode")
			ok, err := twofa.ValidateTOTP(passcode)
			if err != nil {
				ctx.Error(http.StatusInternalServerError, "ValidateTOTP", err.Error())
				return
			}
			if !ok || twofa.LastUsedPasscode == passcode {
				ctx.Data["IsResetForm"] = true
				ctx.Data["Err_Passcode"] = true
				ctx.RenderWithErr(ctx.Tr("auth.twofa_passcode_incorrect"), tplResetPassword, nil)
				return
			}
			twofa.LastUsedPasscode = passcode
			if err = models.UpdateTwoFactor(twofa); err != nil {
				ctx.ServerError("ResetPasswdPost: UpdateTwoFactor", err)
				return
			}
		}
	}
	var err error
	if u.Rands, err = models.GetUserSalt(); err != nil {
		ctx.ServerError("UpdateUser", err)
		return
	}
	if err = u.SetPassword(passwd); err != nil {
		ctx.ServerError("UpdateUser", err)
		return
	}
	u.MustChangePassword = false
	if err := models.UpdateUserCols(u, "must_change_password", "passwd", "passwd_hash_algo", "rands", "salt"); err != nil {
		ctx.ServerError("UpdateUser", err)
		return
	}
	log.Trace("User password reset: %s", u.Name)
	ctx.Data["IsResetFailed"] = true
	remember := len(ctx.Query("remember")) != 0
	if regenerateScratchToken {
		_, err = twofa.GenerateScratchToken()
		if err != nil {
			ctx.ServerError("UserSignIn", err)
			return
		}
		if err = models.UpdateTwoFactor(twofa); err != nil {
			ctx.ServerError("UserSignIn", err)
			return
		}
		handleSignInFull(ctx, u, remember, false)
		ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
		ctx.Redirect(setting.AppSubURL + "/user/settings/security")
		return
	}
	handleSignInFull(ctx, u, remember, true)
}
func ResetPasswdPost ( ctx * context . Context ) { u , twofa := commonResetPassword ( ctx ) if ctx . Written ( ) { return } if u == nil { ctx . HTML ( http . StatusOK , tplResetPassword ) return } passwd := ctx . Query ( " " ) if len ( passwd ) < setting . MinPasswordLength { ctx . Data [ " " ] = true ctx . Data [ " " ] = true ctx . RenderWithErr ( ctx . Tr ( " " , setting . MinPasswordLength ) , tplResetPassword , nil ) return } else if ! password . IsComplexEnough ( passwd ) { ctx . Data [ " " ] = true ctx . Data [ " " ] = true ctx . RenderWithErr ( password . BuildComplexityError ( ctx ) , tplResetPassword , nil ) return } else if pwned , err := password . IsPwned ( ctx , passwd ) ; pwned || err != nil { errMsg := ctx . Tr ( " " ) if err != nil { log . Error ( err . Error ( ) ) errMsg = ctx . Tr ( " " ) } ctx . Data [ " " ] = true ctx . Data [ " " ] = true ctx . RenderWithErr ( errMsg , tplResetPassword , nil ) return } regenerateScratchToken := false if twofa != nil { if ctx . QueryBool ( " " ) { if ! twofa . VerifyScratchToken ( ctx . Query ( " " ) ) { ctx . Data [ " " ] = true ctx . Data [ " " ] = true ctx . RenderWithErr ( ctx . Tr ( " " ) , tplResetPassword , nil ) return } regenerateScratchToken = true } else { passcode := ctx . Query ( " " ) ok , err := twofa . ValidateTOTP ( passcode ) if err != nil { ctx . Error ( http . StatusInternalServerError , " " , err . Error ( ) ) return } if ! ok || twofa . LastUsedPasscode == passcode { ctx . Data [ " " ] = true ctx . Data [ " " ] = true ctx . RenderWithErr ( ctx . Tr ( " " ) , tplResetPassword , nil ) return } twofa . LastUsedPasscode = passcode if err = models . UpdateTwoFactor ( twofa ) ; err != nil { ctx . ServerError ( " " , err ) return } } } var err error if u . Rands , err = models . GetUserSalt ( ) ; err != nil { ctx . ServerError ( " " , err ) return } if err = u . SetPassword ( passwd ) ; err != nil { ctx . ServerError ( " " , err ) return } u . MustChangePassword = false if err := models . UpdateUserCols ( u , " " , " " , " " , " " , " " ) ; err != nil { ctx . ServerError ( " " , err ) return } log . Trace ( " " , u . Name ) ctx . Data [ " " ] = true remember := len ( ctx . Query ( " " ) ) != 0 if regenerateScratchToken { _ , err = twofa . GenerateScratchToken ( ) if err != nil { ctx . ServerError ( " " , err ) return } if err = models . UpdateTwoFactor ( twofa ) ; err != nil { ctx . ServerError ( " " , err ) return } handleSignInFull ( ctx , u , remember , false ) ctx . Flash . Info ( ctx . Tr ( " " ) ) ctx . Redirect ( setting . AppSubURL + " " ) return } handleSignInFull ( ctx , u , remember , true ) }
ResetPasswdPost response from account recovery request
ResetPasswdPost response from account recovery request
// Flash error has been set // Validate password length. // Handle two-factor // Invalidate the scratch token.