mirror of
				https://github.com/volatiletech/authboss.git
				synced 2025-10-30 23:47:59 +02:00 
			
		
		
		
	Use custom struct as localization key
This commit is contained in:
		| @@ -104,16 +104,16 @@ func (a *Authboss) VerifyPassword(user AuthableUser, password string) error { | ||||
| // Localizef is a helper to translate a key using the translator | ||||
| // If the localizer is nil or returns an empty string, | ||||
| // then the original text will be returned using [fmt.Sprintf] to interpolate the args. | ||||
| func (a *Authboss) Localizef(ctx context.Context, text string, args ...any) string { | ||||
| func (a *Authboss) Localizef(ctx context.Context, key LocalizationKey, args ...any) string { | ||||
| 	if a.Config.Core.Localizer == nil { | ||||
| 		return fmt.Sprintf(text, args...) | ||||
| 		return fmt.Sprintf(key.Default, args...) | ||||
| 	} | ||||
|  | ||||
| 	if translated := a.Config.Core.Localizer.Localizef(ctx, text, args...); translated != "" { | ||||
| 	if translated := a.Config.Core.Localizer.Localizef(ctx, key, args...); translated != "" { | ||||
| 		return translated | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf(text, args...) | ||||
| 	return fmt.Sprintf(key.Default, args...) | ||||
| } | ||||
|  | ||||
| // VerifyPassword uses authboss mechanisms to check that a password is correct. | ||||
|   | ||||
							
								
								
									
										200
									
								
								localizer.go
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								localizer.go
									
									
									
									
									
								
							| @@ -7,55 +7,193 @@ import ( | ||||
| type Localizer interface { | ||||
| 	// Get the translation for the given text in the given context. | ||||
| 	// If no translation is found, an empty string should be returned. | ||||
| 	Localizef(ctx context.Context, txt string, args ...any) string | ||||
| 	Localizef(ctx context.Context, key LocalizationKey, args ...any) string | ||||
| } | ||||
|  | ||||
| // Translation constants | ||||
| const ( | ||||
| 	TxtSuccess = "success" | ||||
| type LocalizationKey struct { | ||||
| 	ID      string | ||||
| 	Default string | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	TxtSuccess = LocalizationKey{ | ||||
| 		ID:      "Success", | ||||
| 		Default: "success", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the auth module | ||||
| 	TxtInvalidCredentials = "Invalid Credentials" | ||||
| 	TxtAuthFailed         = "Please login" | ||||
| 	TxtInvalidCredentials = LocalizationKey{ | ||||
| 		ID:      "InvalidCredentials", | ||||
| 		Default: "Invalid Credentials", | ||||
| 	} | ||||
| 	TxtAuthFailed = LocalizationKey{ | ||||
| 		ID:      "AuthFailed", | ||||
| 		Default: "Please login", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the register module | ||||
| 	TxtUserAlreadyExists     = "User already exists" | ||||
| 	TxtRegisteredAndLoggedIn = "Account successfully created, you are now logged in" | ||||
| 	TxtUserAlreadyExists = LocalizationKey{ | ||||
| 		ID:      "UserAlreadyExists", | ||||
| 		Default: "User already exists", | ||||
| 	} | ||||
| 	TxtRegisteredAndLoggedIn = LocalizationKey{ | ||||
| 		ID:      "RegisteredAndLoggedIn", | ||||
| 		Default: "Account successfully created, you are now logged in", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the confirm module | ||||
| 	TxtConfirmYourAccount  = "Please verify your account, an e-mail has been sent to you." | ||||
| 	TxtAccountNotConfirmed = "Your account has not been confirmed, please check your e-mail." | ||||
| 	TxtInvalidConfirmToken = "Your confirmation token is invalid." | ||||
| 	TxtConfrimationSuccess = "You have successfully confirmed your account." | ||||
| 	TxtConfirmEmailSubject = "Confirm New Account" | ||||
| 	TxtConfirmYourAccount = LocalizationKey{ | ||||
| 		ID:      "ConfirmYourAccount", | ||||
| 		Default: "Please verify your account, an e-mail has been sent to you.", | ||||
| 	} | ||||
| 	TxtAccountNotConfirmed = LocalizationKey{ | ||||
| 		ID:      "AccountNotConfirmed", | ||||
| 		Default: "Your account has not been confirmed, please check your e-mail.", | ||||
| 	} | ||||
| 	TxtInvalidConfirmToken = LocalizationKey{ | ||||
| 		ID:      "InvalidConfirmToken", | ||||
| 		Default: "Your confirmation token is invalid.", | ||||
| 	} | ||||
| 	TxtConfrimationSuccess = LocalizationKey{ | ||||
| 		ID:      "ConfrimationSuccess", | ||||
| 		Default: "You have successfully confirmed your account.", | ||||
| 	} | ||||
| 	TxtConfirmEmailSubject = LocalizationKey{ | ||||
| 		ID:      "ConfirmEmailSubject", | ||||
| 		Default: "Confirm New Account", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the lock module | ||||
| 	TxtLocked = "Your account has been locked, please contact the administrator." | ||||
| 	TxtLocked = LocalizationKey{ | ||||
| 		ID:      "Locked", | ||||
| 		Default: "Your account has been locked, please contact the administrator.", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the logout module | ||||
| 	TxtLoggedOut = "You have been logged out" | ||||
| 	TxtLoggedOut = LocalizationKey{ | ||||
| 		ID:      "LoggedOut", | ||||
| 		Default: "You have been logged out", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the oauth2 module | ||||
| 	TxtOAuth2LoginOK    = "Logged in successfully with %s." | ||||
| 	TxtOAuth2LoginNotOK = "%s login cancelled or failed" | ||||
| 	TxtOAuth2LoginOK = LocalizationKey{ | ||||
| 		ID:      "OAuth2LoginOK", | ||||
| 		Default: "Logged in successfully with %s.", | ||||
| 	} | ||||
| 	TxtOAuth2LoginNotOK = LocalizationKey{ | ||||
| 		ID:      "OAuth2LoginNotOK", | ||||
| 		Default: "%s login cancelled or failed", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the recover module | ||||
| 	TxtRecoverInitiateSuccessFlash = "An email has been sent to you with further instructions on how to reset your password." | ||||
| 	TxtPasswordResetEmailSubject   = "Password Reset" | ||||
| 	TxtRecoverSuccessMsg           = "Successfully updated password" | ||||
| 	TxtRecoverAndLoginSuccessMsg   = "Successfully updated password and logged in" | ||||
| 	TxtRecoverInitiateSuccessFlash = LocalizationKey{ | ||||
| 		ID:      "RecoverInitiateSuccessFlash", | ||||
| 		Default: "An email has been sent to you with further instructions on how to reset your password.", | ||||
| 	} | ||||
| 	TxtPasswordResetEmailSubject = LocalizationKey{ | ||||
| 		ID:      "PasswordResetEmailSubject", | ||||
| 		Default: "Password Reset", | ||||
| 	} | ||||
| 	TxtRecoverSuccessMsg = LocalizationKey{ | ||||
| 		ID:      "RecoverSuccessMsg", | ||||
| 		Default: "Successfully updated password", | ||||
| 	} | ||||
| 	TxtRecoverAndLoginSuccessMsg = LocalizationKey{ | ||||
| 		ID:      "RecoverAndLoginSuccessMsg", | ||||
| 		Default: "Successfully updated password and logged in", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the otp module | ||||
| 	TxtTooManyOTPs = "You cannot have more than %d one time passwords" | ||||
| 	TxtTooManyOTPs = LocalizationKey{ | ||||
| 		ID:      "TooManyOTPs", | ||||
| 		Default: "You cannot have more than %d one time passwords", | ||||
| 	} | ||||
|  | ||||
| 	// Used in the 2fa module | ||||
| 	TxtEmailVerifyTriggered        = "An e-mail has been sent to confirm 2FA activation" | ||||
| 	TxtEmailVerifySubject          = "Add 2FA to Account" | ||||
| 	TxtInvalid2FAVerificationToken = "Invalid 2FA email verification token" | ||||
| 	Txt2FAAuthorizationRequired    = "You must first authorize adding 2fa by e-mail" | ||||
| 	TxtInvalid2FACode              = "2FA code was invalid" | ||||
| 	TxtRepeated2FACode             = "2FA code was previously used" | ||||
| 	TxtTOTP2FANotActive            = "TOTP 2FA is not active" | ||||
| 	TxtSMSNumberRequired           = "You must provide a phone number" | ||||
| 	TxtSMSWaitToResend             = "Please wait a few moments before resending the SMS code" | ||||
| 	TxtEmailVerifyTriggered = LocalizationKey{ | ||||
| 		ID:      "EmailVerifyTriggered", | ||||
| 		Default: "An e-mail has been sent to confirm 2FA activation", | ||||
| 	} | ||||
| 	TxtEmailVerifySubject = LocalizationKey{ | ||||
| 		ID:      "EmailVerifySubject", | ||||
| 		Default: "Add 2FA to Account", | ||||
| 	} | ||||
| 	TxtInvalid2FAVerificationToken = LocalizationKey{ | ||||
| 		ID:      "Invalid2FAVerificationToken", | ||||
| 		Default: "Invalid 2FA email verification token", | ||||
| 	} | ||||
| 	Txt2FAAuthorizationRequired = LocalizationKey{ | ||||
| 		ID:      "2FAAuthorizationRequired", | ||||
| 		Default: "You must first authorize adding 2fa by e-mail", | ||||
| 	} | ||||
| 	TxtInvalid2FACode = LocalizationKey{ | ||||
| 		ID:      "Invalid2FACode", | ||||
| 		Default: "2FA code was invalid", | ||||
| 	} | ||||
| 	TxtRepeated2FACode = LocalizationKey{ | ||||
| 		ID:      "Repeated2FACode", | ||||
| 		Default: "2FA code was previously used", | ||||
| 	} | ||||
| 	TxtTOTP2FANotActive = LocalizationKey{ | ||||
| 		ID:      "TOTP2FANotActive", | ||||
| 		Default: "TOTP 2FA is not active", | ||||
| 	} | ||||
| 	TxtSMSNumberRequired = LocalizationKey{ | ||||
| 		ID:      "SMSNumberRequired", | ||||
| 		Default: "You must provide a phone number", | ||||
| 	} | ||||
| 	TxtSMSWaitToResend = LocalizationKey{ | ||||
| 		ID:      "SMSWaitToResend", | ||||
| 		Default: "Please wait a few moments before resending the SMS code", | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| // // Translation constants | ||||
| // const ( | ||||
| // 	TxtSuccess = "success" | ||||
| // | ||||
| // 	// Used in the auth module | ||||
| // 	TxtInvalidCredentials = "Invalid Credentials" | ||||
| // 	TxtAuthFailed         = "Please login" | ||||
| // | ||||
| // 	// Used in the register module | ||||
| // 	TxtUserAlreadyExists     = "User already exists" | ||||
| // 	TxtRegisteredAndLoggedIn = "Account successfully created, you are now logged in" | ||||
| // | ||||
| // 	// Used in the confirm module | ||||
| // 	TxtConfirmYourAccount  = "Please verify your account, an e-mail has been sent to you." | ||||
| // 	TxtAccountNotConfirmed = "Your account has not been confirmed, please check your e-mail." | ||||
| // 	TxtInvalidConfirmToken = "Your confirmation token is invalid." | ||||
| // 	TxtConfrimationSuccess = "You have successfully confirmed your account." | ||||
| // 	TxtConfirmEmailSubject = "Confirm New Account" | ||||
| // | ||||
| // 	// Used in the lock module | ||||
| // 	TxtLocked = "Your account has been locked, please contact the administrator." | ||||
| // | ||||
| // 	// Used in the logout module | ||||
| // 	TxtLoggedOut = "You have been logged out" | ||||
| // | ||||
| // 	// Used in the oauth2 module | ||||
| // 	TxtOAuth2LoginOK    = "Logged in successfully with %s." | ||||
| // 	TxtOAuth2LoginNotOK = "%s login cancelled or failed" | ||||
| // | ||||
| // 	// Used in the recover module | ||||
| // 	TxtRecoverInitiateSuccessFlash = "An email has been sent to you with further instructions on how to reset your password." | ||||
| // 	TxtPasswordResetEmailSubject   = "Password Reset" | ||||
| // 	TxtRecoverSuccessMsg           = "Successfully updated password" | ||||
| // 	TxtRecoverAndLoginSuccessMsg   = "Successfully updated password and logged in" | ||||
| // | ||||
| // 	// Used in the otp module | ||||
| // 	TxtTooManyOTPs = "You cannot have more than %d one time passwords" | ||||
| // | ||||
| // 	// Used in the 2fa module | ||||
| // 	TxtEmailVerifyTriggered        = "An e-mail has been sent to confirm 2FA activation" | ||||
| // 	TxtEmailVerifySubject          = "Add 2FA to Account" | ||||
| // 	TxtInvalid2FAVerificationToken = "Invalid 2FA email verification token" | ||||
| // 	Txt2FAAuthorizationRequired    = "You must first authorize adding 2fa by e-mail" | ||||
| // 	TxtInvalid2FACode              = "2FA code was invalid" | ||||
| // 	TxtRepeated2FACode             = "2FA code was previously used" | ||||
| // 	TxtTOTP2FANotActive            = "TOTP 2FA is not active" | ||||
| // 	TxtSMSNumberRequired           = "You must provide a phone number" | ||||
| // 	TxtSMSWaitToResend             = "Please wait a few moments before resending the SMS code" | ||||
| // ) | ||||
|   | ||||
| @@ -22,18 +22,18 @@ func (l *Logout) Init(ab *authboss.Authboss) error { | ||||
| 	l.Authboss = ab | ||||
|  | ||||
| 	var logoutRouteMethod func(string, http.Handler) | ||||
| 	switch l.Authboss.Config.Modules.LogoutMethod { | ||||
| 	switch l.Config.Modules.LogoutMethod { | ||||
| 	case "GET": | ||||
| 		logoutRouteMethod = l.Authboss.Config.Core.Router.Get | ||||
| 		logoutRouteMethod = l.Config.Core.Router.Get | ||||
| 	case "POST": | ||||
| 		logoutRouteMethod = l.Authboss.Config.Core.Router.Post | ||||
| 		logoutRouteMethod = l.Config.Core.Router.Post | ||||
| 	case "DELETE": | ||||
| 		logoutRouteMethod = l.Authboss.Config.Core.Router.Delete | ||||
| 		logoutRouteMethod = l.Config.Core.Router.Delete | ||||
| 	default: | ||||
| 		return errors.Errorf("logout wants to register a logout route but was given an invalid method: %s", l.Authboss.Config.Modules.LogoutMethod) | ||||
| 		return errors.Errorf("logout wants to register a logout route but was given an invalid method: %s", l.Config.Modules.LogoutMethod) | ||||
| 	} | ||||
|  | ||||
| 	logoutRouteMethod("/logout", l.Authboss.Core.ErrorHandler.Wrap(l.Logout)) | ||||
| 	logoutRouteMethod("/logout", l.Core.ErrorHandler.Wrap(l.Logout)) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| @@ -61,7 +61,7 @@ func (l *Logout) Logout(w http.ResponseWriter, r *http.Request) error { | ||||
| 	authboss.DelKnownSession(w) | ||||
| 	authboss.DelKnownCookie(w) | ||||
|  | ||||
| 	handled, err = l.Authboss.Events.FireAfter(authboss.EventLogout, w, r) | ||||
| 	handled, err = l.Events.FireAfter(authboss.EventLogout, w, r) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if handled { | ||||
| @@ -70,8 +70,8 @@ func (l *Logout) Logout(w http.ResponseWriter, r *http.Request) error { | ||||
|  | ||||
| 	ro := authboss.RedirectOptions{ | ||||
| 		Code:         http.StatusTemporaryRedirect, | ||||
| 		RedirectPath: l.Authboss.Paths.LogoutOK, | ||||
| 		Success:      authboss.TxtLoggedOut, | ||||
| 		RedirectPath: l.Paths.LogoutOK, | ||||
| 		Success:      l.Localizef(r.Context(), authboss.TxtLoggedOut), | ||||
| 	} | ||||
| 	return l.Authboss.Core.Redirector.Redirect(w, r, ro) | ||||
| 	return l.Core.Redirector.Redirect(w, r, ro) | ||||
| } | ||||
|   | ||||
| @@ -47,25 +47,25 @@ type Recover struct { | ||||
| func (r *Recover) Init(ab *authboss.Authboss) (err error) { | ||||
| 	r.Authboss = ab | ||||
|  | ||||
| 	if err := r.Authboss.Config.Core.ViewRenderer.Load(PageRecoverStart, PageRecoverEnd); err != nil { | ||||
| 	if err := r.Config.Core.ViewRenderer.Load(PageRecoverStart, PageRecoverEnd); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := r.Authboss.Config.Core.MailRenderer.Load(EmailRecoverHTML, EmailRecoverTxt); err != nil { | ||||
| 	if err := r.Config.Core.MailRenderer.Load(EmailRecoverHTML, EmailRecoverTxt); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	r.Authboss.Config.Core.Router.Get("/recover", r.Core.ErrorHandler.Wrap(r.StartGet)) | ||||
| 	r.Authboss.Config.Core.Router.Post("/recover", r.Core.ErrorHandler.Wrap(r.StartPost)) | ||||
| 	r.Authboss.Config.Core.Router.Get("/recover/end", r.Core.ErrorHandler.Wrap(r.EndGet)) | ||||
| 	r.Authboss.Config.Core.Router.Post("/recover/end", r.Core.ErrorHandler.Wrap(r.EndPost)) | ||||
| 	r.Config.Core.Router.Get("/recover", r.Core.ErrorHandler.Wrap(r.StartGet)) | ||||
| 	r.Config.Core.Router.Post("/recover", r.Core.ErrorHandler.Wrap(r.StartPost)) | ||||
| 	r.Config.Core.Router.Get("/recover/end", r.Core.ErrorHandler.Wrap(r.EndGet)) | ||||
| 	r.Config.Core.Router.Post("/recover/end", r.Core.ErrorHandler.Wrap(r.EndPost)) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // StartGet starts the recover procedure by rendering a form for the user. | ||||
| func (r *Recover) StartGet(w http.ResponseWriter, req *http.Request) error { | ||||
| 	return r.Authboss.Config.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverStart, nil) | ||||
| 	return r.Config.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverStart, nil) | ||||
| } | ||||
|  | ||||
| // StartPost starts the recover procedure using values provided from the user | ||||
| @@ -73,7 +73,7 @@ func (r *Recover) StartGet(w http.ResponseWriter, req *http.Request) error { | ||||
| func (r *Recover) StartPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	logger := r.RequestLogger(req) | ||||
|  | ||||
| 	validatable, err := r.Authboss.Core.BodyReader.Read(PageRecoverStart, req) | ||||
| 	validatable, err := r.Core.BodyReader.Read(PageRecoverStart, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -81,33 +81,33 @@ func (r *Recover) StartPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	if errs := validatable.Validate(); errs != nil { | ||||
| 		logger.Info("recover validation failed") | ||||
| 		data := authboss.HTMLData{authboss.DataValidation: authboss.ErrorMap(errs)} | ||||
| 		return r.Authboss.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverStart, data) | ||||
| 		return r.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverStart, data) | ||||
| 	} | ||||
|  | ||||
| 	recoverVals := authboss.MustHaveRecoverStartValues(validatable) | ||||
|  | ||||
| 	user, err := r.Authboss.Storage.Server.Load(req.Context(), recoverVals.GetPID()) | ||||
| 	user, err := r.Storage.Server.Load(req.Context(), recoverVals.GetPID()) | ||||
| 	if err == authboss.ErrUserNotFound { | ||||
| 		logger.Infof("user %s was attempted to be recovered, user does not exist, faking successful response", recoverVals.GetPID()) | ||||
| 		ro := authboss.RedirectOptions{ | ||||
| 			Code:         http.StatusTemporaryRedirect, | ||||
| 			RedirectPath: r.Authboss.Config.Paths.RecoverOK, | ||||
| 			Success:      authboss.TxtRecoverInitiateSuccessFlash, | ||||
| 			RedirectPath: r.Config.Paths.RecoverOK, | ||||
| 			Success:      r.Localizef(req.Context(), authboss.TxtRecoverInitiateSuccessFlash), | ||||
| 		} | ||||
| 		return r.Authboss.Core.Redirector.Redirect(w, req, ro) | ||||
| 		return r.Core.Redirector.Redirect(w, req, ro) | ||||
| 	} | ||||
|  | ||||
| 	ru := authboss.MustBeRecoverable(user) | ||||
|  | ||||
| 	req = req.WithContext(context.WithValue(req.Context(), authboss.CTXKeyUser, user)) | ||||
| 	handled, err := r.Authboss.Events.FireBefore(authboss.EventRecoverStart, w, req) | ||||
| 	handled, err := r.Events.FireBefore(authboss.EventRecoverStart, w, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if handled { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	selector, verifier, token, err := r.Authboss.Config.Core.OneTimeTokenGenerator.GenerateToken() | ||||
| 	selector, verifier, token, err := r.Config.Core.OneTimeTokenGenerator.GenerateToken() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -118,7 +118,7 @@ func (r *Recover) StartPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	ru.PutRecoverVerifier(verifier) | ||||
| 	ru.PutRecoverExpiry(time.Now().UTC().Add(r.Config.Modules.RecoverTokenDuration)) | ||||
|  | ||||
| 	if err := r.Authboss.Storage.Server.Save(req.Context(), ru); err != nil { | ||||
| 	if err := r.Storage.Server.Save(req.Context(), ru); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @@ -128,13 +128,13 @@ func (r *Recover) StartPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 		recoveryEmailRecipients = append(recoveryEmailRecipients, ruWithSecondaries.GetSecondaryEmails()...) | ||||
| 	} | ||||
|  | ||||
| 	if r.Authboss.Modules.MailNoGoroutine { | ||||
| 	if r.Modules.MailNoGoroutine { | ||||
| 		r.SendRecoverEmail(req.Context(), recoveryEmailRecipients, token) | ||||
| 	} else { | ||||
| 		go r.SendRecoverEmail(req.Context(), recoveryEmailRecipients, token) | ||||
| 	} | ||||
|  | ||||
| 	_, err = r.Authboss.Events.FireAfter(authboss.EventRecoverStart, w, req) | ||||
| 	_, err = r.Events.FireAfter(authboss.EventRecoverStart, w, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -142,24 +142,24 @@ func (r *Recover) StartPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	logger.Infof("user %s password recovery initiated", ru.GetPID()) | ||||
| 	ro := authboss.RedirectOptions{ | ||||
| 		Code:         http.StatusTemporaryRedirect, | ||||
| 		RedirectPath: r.Authboss.Config.Paths.RecoverOK, | ||||
| 		Success:      authboss.TxtRecoverInitiateSuccessFlash, | ||||
| 		RedirectPath: r.Config.Paths.RecoverOK, | ||||
| 		Success:      r.Localizef(req.Context(), authboss.TxtRecoverInitiateSuccessFlash), | ||||
| 	} | ||||
| 	return r.Authboss.Core.Redirector.Redirect(w, req, ro) | ||||
| 	return r.Core.Redirector.Redirect(w, req, ro) | ||||
| } | ||||
|  | ||||
| // SendRecoverEmail to a specific e-mail address passing along the encodedToken | ||||
| // in an escaped URL to the templates. | ||||
| func (r *Recover) SendRecoverEmail(ctx context.Context, to []string, encodedToken string) { | ||||
| 	logger := r.Authboss.Logger(ctx) | ||||
| 	logger := r.Logger(ctx) | ||||
|  | ||||
| 	mailURL := r.mailURL(encodedToken) | ||||
|  | ||||
| 	email := authboss.Email{ | ||||
| 		To:       to, | ||||
| 		From:     r.Authboss.Config.Mail.From, | ||||
| 		FromName: r.Authboss.Config.Mail.FromName, | ||||
| 		Subject:  r.Authboss.Config.Mail.SubjectPrefix + r.Localizef(ctx, authboss.TxtPasswordResetEmailSubject), | ||||
| 		From:     r.Config.Mail.From, | ||||
| 		FromName: r.Config.Mail.FromName, | ||||
| 		Subject:  r.Config.Mail.SubjectPrefix + r.Localizef(ctx, authboss.TxtPasswordResetEmailSubject), | ||||
| 	} | ||||
|  | ||||
| 	ro := authboss.EmailResponseOptions{ | ||||
| @@ -171,7 +171,7 @@ func (r *Recover) SendRecoverEmail(ctx context.Context, to []string, encodedToke | ||||
| 	} | ||||
|  | ||||
| 	logger.Infof("sending recover e-mail to: %s", to) | ||||
| 	if err := r.Authboss.Email(ctx, email, ro); err != nil { | ||||
| 	if err := r.Email(ctx, email, ro); err != nil { | ||||
| 		logger.Errorf("failed to recover send e-mail to %s: %+v", to, err) | ||||
| 	} | ||||
| } | ||||
| @@ -179,7 +179,7 @@ func (r *Recover) SendRecoverEmail(ctx context.Context, to []string, encodedToke | ||||
| // EndGet shows a password recovery form, and it should have the token that | ||||
| // the user brought in the query parameters in it on submission. | ||||
| func (r *Recover) EndGet(w http.ResponseWriter, req *http.Request) error { | ||||
| 	validatable, err := r.Authboss.Core.BodyReader.Read(PageRecoverMiddle, req) | ||||
| 	validatable, err := r.Core.BodyReader.Read(PageRecoverMiddle, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -191,14 +191,14 @@ func (r *Recover) EndGet(w http.ResponseWriter, req *http.Request) error { | ||||
| 		DataRecoverToken: token, | ||||
| 	} | ||||
|  | ||||
| 	return r.Authboss.Config.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverEnd, data) | ||||
| 	return r.Config.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverEnd, data) | ||||
| } | ||||
|  | ||||
| // EndPost retrieves the token | ||||
| func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	logger := r.RequestLogger(req) | ||||
|  | ||||
| 	validatable, err := r.Authboss.Core.BodyReader.Read(PageRecoverEnd, req) | ||||
| 	validatable, err := r.Core.BodyReader.Read(PageRecoverEnd, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -222,7 +222,7 @@ func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 		return r.invalidToken(PageRecoverEnd, w, req) | ||||
| 	} | ||||
|  | ||||
| 	credsGenerator := r.Authboss.Core.OneTimeTokenGenerator | ||||
| 	credsGenerator := r.Core.OneTimeTokenGenerator | ||||
|  | ||||
| 	if len(rawToken) != credsGenerator.TokenSize() { | ||||
| 		logger.Infof("invalid recover token submitted, size was wrong: %d", len(rawToken)) | ||||
| @@ -232,7 +232,7 @@ func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	selectorBytes, verifierBytes := credsGenerator.ParseToken(string(rawToken)) | ||||
| 	selector := base64.StdEncoding.EncodeToString(selectorBytes[:]) | ||||
|  | ||||
| 	storer := authboss.EnsureCanRecover(r.Authboss.Config.Storage.Server) | ||||
| 	storer := authboss.EnsureCanRecover(r.Config.Storage.Server) | ||||
| 	user, err := storer.LoadByRecoverSelector(req.Context(), selector) | ||||
| 	if err == authboss.ErrUserNotFound { | ||||
| 		logger.Info("invalid recover token submitted, user not found") | ||||
| @@ -259,14 +259,14 @@ func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 	} | ||||
|  | ||||
| 	req = req.WithContext(context.WithValue(req.Context(), authboss.CTXKeyUser, user)) | ||||
| 	handled, err := r.Authboss.Events.FireBefore(authboss.EventRecoverEnd, w, req) | ||||
| 	handled, err := r.Events.FireBefore(authboss.EventRecoverEnd, w, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if handled { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	pass, err := r.Authboss.Config.Core.Hasher.GenerateHash(password) | ||||
| 	pass, err := r.Config.Core.Hasher.GenerateHash(password) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -280,13 +280,13 @@ func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = r.Authboss.Events.FireAfter(authboss.EventRecoverEnd, w, req) | ||||
| 	_, err = r.Events.FireAfter(authboss.EventRecoverEnd, w, req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	successMsg := r.Localizef(req.Context(), authboss.TxtRecoverSuccessMsg) | ||||
| 	if r.Authboss.Config.Modules.RecoverLoginAfterRecovery { | ||||
| 	if r.Config.Modules.RecoverLoginAfterRecovery { | ||||
| 		handled, err = r.Events.FireBefore(authboss.EventAuth, w, req) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @@ -304,7 +304,7 @@ func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
| 		authboss.PutSession(w, authboss.SessionKey, user.GetPID()) | ||||
| 		successMsg = r.Localizef(req.Context(), authboss.TxtRecoverAndLoginSuccessMsg) | ||||
|  | ||||
| 		handled, err = r.Authboss.Events.FireAfter(authboss.EventAuth, w, req) | ||||
| 		handled, err = r.Events.FireAfter(authboss.EventAuth, w, req) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} else if handled { | ||||
| @@ -314,16 +314,16 @@ func (r *Recover) EndPost(w http.ResponseWriter, req *http.Request) error { | ||||
|  | ||||
| 	ro := authboss.RedirectOptions{ | ||||
| 		Code:         http.StatusTemporaryRedirect, | ||||
| 		RedirectPath: r.Authboss.Config.Paths.RecoverOK, | ||||
| 		RedirectPath: r.Config.Paths.RecoverOK, | ||||
| 		Success:      successMsg, | ||||
| 	} | ||||
| 	return r.Authboss.Config.Core.Redirector.Redirect(w, req, ro) | ||||
| 	return r.Config.Core.Redirector.Redirect(w, req, ro) | ||||
| } | ||||
|  | ||||
| func (r *Recover) invalidToken(page string, w http.ResponseWriter, req *http.Request) error { | ||||
| 	errorsAll := []error{errors.New("recovery token is invalid")} | ||||
| 	data := authboss.HTMLData{authboss.DataValidation: authboss.ErrorMap(errorsAll)} | ||||
| 	return r.Authboss.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverEnd, data) | ||||
| 	return r.Core.Responder.Respond(w, req, http.StatusOK, PageRecoverEnd, data) | ||||
| } | ||||
|  | ||||
| func (r *Recover) mailURL(token string) string { | ||||
|   | ||||
| @@ -107,7 +107,7 @@ func (r *Register) Post(w http.ResponseWriter, req *http.Request) error { | ||||
| 	switch { | ||||
| 	case err == authboss.ErrUserFound: | ||||
| 		logger.Infof("user %s attempted to re-register", pid) | ||||
| 		errs = []error{errors.New(authboss.TxtUserAlreadyExists)} | ||||
| 		errs = []error{errors.New(r.Localizef(req.Context(), authboss.TxtUserAlreadyExists))} | ||||
| 		data := authboss.HTMLData{ | ||||
| 			authboss.DataValidation: authboss.ErrorMap(errs), | ||||
| 		} | ||||
| @@ -134,7 +134,7 @@ func (r *Register) Post(w http.ResponseWriter, req *http.Request) error { | ||||
| 	logger.Infof("registered and logged in user %s", pid) | ||||
| 	ro := authboss.RedirectOptions{ | ||||
| 		Code:         http.StatusTemporaryRedirect, | ||||
| 		Success:      authboss.TxtRegisteredAndLoggedIn, | ||||
| 		Success:      r.Localizef(req.Context(), authboss.TxtRegisteredAndLoggedIn), | ||||
| 		RedirectPath: r.Config.Paths.RegisterOK, | ||||
| 	} | ||||
| 	return r.Config.Core.Redirector.Redirect(w, req, ro) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user