1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-03-05 15:15:45 +02:00

Add translation strings for otp and 2fa modules

This commit is contained in:
Stephen Afam-Osemene 2023-11-30 01:12:07 +00:00
parent 8f93fb0752
commit a0994c3732
8 changed files with 55 additions and 44 deletions

View File

@ -10,6 +10,8 @@ type Localizer interface {
// Translation constants
const (
TxtSuccess = "success"
// Used in the auth module
TxtInvalidCredentials = "Invalid Credentials"
TxtAuthFailed = "Please login"
@ -40,4 +42,18 @@ const (
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"
)

View File

@ -118,7 +118,7 @@ func (o *OTP) LoginPost(w http.ResponseWriter, r *http.Request) error {
pidUser, err := o.Authboss.Storage.Server.Load(r.Context(), pid)
if err == authboss.ErrUserNotFound {
logger.Infof("failed to load user requested by pid: %s", pid)
data := authboss.HTMLData{authboss.DataErr: "Invalid Credentials"}
data := authboss.HTMLData{authboss.DataErr: o.Localize(r.Context(), authboss.TxtInvalidCredentials)}
return o.Authboss.Core.Responder.Respond(w, r, http.StatusOK, PageLogin, data)
} else if err != nil {
return err
@ -153,7 +153,7 @@ func (o *OTP) LoginPost(w http.ResponseWriter, r *http.Request) error {
}
logger.Infof("user %s failed to log in with otp", pid)
data := authboss.HTMLData{authboss.DataErr: "Invalid Credentials"}
data := authboss.HTMLData{authboss.DataErr: o.Localize(r.Context(), authboss.TxtInvalidCredentials)}
return o.Authboss.Core.Responder.Respond(w, r, http.StatusOK, PageLogin, data)
}
@ -218,7 +218,7 @@ func (o *OTP) AddPost(w http.ResponseWriter, r *http.Request) error {
currentOTPs := splitOTPs(otpUser.GetOTPs())
if len(currentOTPs) >= maxOTPs {
data := authboss.HTMLData{authboss.DataValidation: fmt.Sprintf("you cannot have more than %d one time passwords", maxOTPs)}
data := authboss.HTMLData{authboss.DataValidation: o.Localize(r.Context(), authboss.TxtTooManyOTPs, maxOTPs)}
return o.Core.Responder.Respond(w, r, http.StatusOK, PageAdd, data)
}

View File

@ -263,7 +263,9 @@ func (s *SMS) PostSetup(w http.ResponseWriter, r *http.Request) error {
number := smsVals.GetPhoneNumber()
if len(number) == 0 {
data := authboss.HTMLData{
authboss.DataValidation: map[string][]string{FormValuePhoneNumber: {"must provide a phone number"}},
authboss.DataValidation: map[string][]string{FormValuePhoneNumber: {
s.Localize(r.Context(), authboss.TxtSMSNumberRequired),
}},
}
return s.Core.Responder.Respond(w, r, http.StatusOK, PageSMSSetup, data)
}
@ -355,7 +357,7 @@ func (s *SMSValidator) sendCode(w http.ResponseWriter, r *http.Request, user Use
var data authboss.HTMLData
err := s.SendCodeToUser(w, r, user.GetPID(), phoneNumber)
if err == errSMSRateLimit {
data = authboss.HTMLData{authboss.DataErr: "please wait a few moments before resending SMS code"}
data = authboss.HTMLData{authboss.DataErr: s.Localize(r.Context(), authboss.TxtSMSWaitToResend)}
} else if err != nil {
return err
}
@ -401,7 +403,7 @@ func (s *SMSValidator) validateCode(w http.ResponseWriter, r *http.Request, user
logger.Infof("user %s sms 2fa failure (wrong code)", user.GetPID())
data := authboss.HTMLData{
authboss.DataValidation: map[string][]string{FormValueCode: {"2fa code was invalid"}},
authboss.DataValidation: map[string][]string{FormValueCode: {s.Localize(r.Context(), authboss.TxtInvalid2FACode)}},
}
return s.Authboss.Core.Responder.Respond(w, r, http.StatusOK, s.Page, data)
}

View File

@ -272,7 +272,7 @@ func TestPostSetup(t *testing.T) {
t.Error("page wrong:", h.responder.Page)
}
validation := h.responder.Data[authboss.DataValidation].(map[string][]string)
if got := validation[FormValuePhoneNumber][0]; got != "must provide a phone number" {
if got := validation[FormValuePhoneNumber][0]; got != h.ab.Localize(context.Background(), authboss.TxtSMSNumberRequired) {
t.Error("data wrong:", got)
}
})
@ -547,7 +547,7 @@ func TestValidatorPostOk(t *testing.T) {
w.WriteHeader(http.StatusOK)
validation := h.responder.Data[authboss.DataValidation].(map[string][]string)
if got := validation[FormValueCode][0]; got != "2fa code was invalid" {
if got := validation[FormValueCode][0]; got != h.ab.Localize(context.Background(), authboss.TxtInvalid2FACode) {
t.Error("data wrong:", got)
}
})
@ -574,7 +574,7 @@ func TestValidatorPostOk(t *testing.T) {
t.Error("page wrong:", h.responder.Page)
}
validation := h.responder.Data[authboss.DataValidation].(map[string][]string)
if got := validation[FormValueCode][0]; got != "2fa code was invalid" {
if got := validation[FormValueCode][0]; got != h.ab.Localize(context.Background(), authboss.TxtInvalid2FACode) {
t.Error("data wrong:", got)
}
})

View File

@ -49,16 +49,7 @@ const (
DataTOTPSecret = SessionTOTPSecret
)
// validation constants
const (
validationSuccess = "success"
validationErrRepeatCode = "2fa code was previously used"
validationErrInvalidCode = "2fa code was invalid"
)
var (
errNoTOTPEnabled = errors.New("user does not have totp 2fa enabled")
)
var errNoTOTPEnabled = errors.New("user does not have totp 2fa enabled")
// User for TOTP
type User interface {
@ -180,7 +171,6 @@ func (t *TOTP) PostSetup(w http.ResponseWriter, r *http.Request) error {
Issuer: t.Authboss.Config.Modules.TOTP2FAIssuer,
AccountName: user.GetEmail(),
})
if err != nil {
return errors.Wrap(err, "failed to create a totp key")
}
@ -278,8 +268,10 @@ func (t *TOTP) PostConfirm(w http.ResponseWriter, r *http.Request) error {
ok = totp.Validate(inputCode, totpSecret)
if !ok {
data := authboss.HTMLData{
authboss.DataValidation: map[string][]string{FormValueCode: {"2fa code was invalid"}},
DataTOTPSecret: totpSecret,
authboss.DataValidation: map[string][]string{FormValueCode: {
t.Localize(r.Context(), authboss.TxtInvalid2FACode),
}},
DataTOTPSecret: totpSecret,
}
return t.Authboss.Core.Responder.Respond(w, r, http.StatusOK, PageTOTPConfirm, data)
}
@ -333,11 +325,11 @@ func (t *TOTP) PostRemove(w http.ResponseWriter, r *http.Request) error {
user, status, err := t.validate(r)
switch {
case err == errNoTOTPEnabled:
data := authboss.HTMLData{authboss.DataErr: "totp 2fa not active"}
data := authboss.HTMLData{authboss.DataErr: t.Localize(r.Context(), authboss.TxtTOTP2FANotActive)}
return t.Authboss.Core.Responder.Respond(w, r, http.StatusOK, PageTOTPRemove, data)
case err != nil:
return err
case status != validationSuccess:
case status != t.Localize(r.Context(), authboss.TxtSuccess):
logger.Infof("user %s totp 2fa removal failure (%s)", user.GetPID(), status)
data := authboss.HTMLData{
authboss.DataValidation: map[string][]string{FormValueCode: {status}},
@ -376,11 +368,12 @@ func (t *TOTP) PostValidate(w http.ResponseWriter, r *http.Request) error {
switch {
case err == errNoTOTPEnabled:
logger.Infof("user %s totp failure (not enabled)", user.GetPID())
data := authboss.HTMLData{authboss.DataErr: "totp 2fa not active"}
data := authboss.HTMLData{authboss.DataErr: t.Localize(
r.Context(), authboss.TxtTOTP2FANotActive)}
return t.Authboss.Core.Responder.Respond(w, r, http.StatusOK, PageTOTPValidate, data)
case err != nil:
return err
case status != validationSuccess:
case status != t.Localize(r.Context(), authboss.TxtSuccess):
r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyUser, user))
handled, err := t.Authboss.Events.FireAfter(authboss.EventAuthFail, w, r)
if err != nil {
@ -478,10 +471,10 @@ func (t *TOTP) validate(r *http.Request) (User, string, error) {
return nil, "", err
}
} else {
return user, validationErrInvalidCode, nil
return user, t.Localize(r.Context(), authboss.TxtInvalid2FACode), nil
}
return user, validationSuccess, nil
return user, t.Localize(r.Context(), authboss.TxtSuccess), nil
}
input := totpCodeValues.GetCode()
@ -489,14 +482,14 @@ func (t *TOTP) validate(r *http.Request) (User, string, error) {
if oneTime, ok := user.(UserOneTime); ok {
oldCode := oneTime.GetTOTPLastCode()
if oldCode == input {
return user, validationErrRepeatCode, nil
return user, t.Localize(r.Context(), authboss.TxtRepeated2FACode), nil
}
oneTime.PutTOTPLastCode(input)
}
if !totp.Validate(input, secret) {
return user, validationErrInvalidCode, nil
return user, t.Localize(r.Context(), authboss.TxtInvalid2FACode), nil
}
return user, validationSuccess, nil
return user, t.Localize(r.Context(), authboss.TxtSuccess), nil
}

View File

@ -380,7 +380,7 @@ func TestPostRemove(t *testing.T) {
if h.responder.Page != PageTOTPRemove {
t.Error("page wrong:", h.responder.Page)
}
if got := h.responder.Data[authboss.DataErr]; got != "totp 2fa not active" {
if got := h.responder.Data[authboss.DataErr]; got != h.ab.Localize(context.Background(), authboss.TxtTOTP2FANotActive) {
t.Error("data wrong:", got)
}
})
@ -404,7 +404,7 @@ func TestPostRemove(t *testing.T) {
if h.responder.Page != PageTOTPRemove {
t.Error("page wrong:", h.responder.Page)
}
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != "2fa code was invalid" {
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != h.ab.Localize(context.Background(), authboss.TxtInvalid2FACode) {
t.Error("data wrong:", got)
}
})
@ -486,7 +486,7 @@ func TestPostValidate(t *testing.T) {
if h.responder.Page != PageTOTPValidate {
t.Error("page wrong:", h.responder.Page)
}
if got := h.responder.Data[authboss.DataErr]; got != "totp 2fa not active" {
if got := h.responder.Data[authboss.DataErr]; got != h.ab.Localize(context.Background(), authboss.TxtTOTP2FANotActive) {
t.Error("data wrong:", got)
}
})
@ -509,7 +509,7 @@ func TestPostValidate(t *testing.T) {
if h.responder.Page != PageTOTPValidate {
t.Error("page wrong:", h.responder.Page)
}
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != "2fa code was invalid" {
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != h.ab.Localize(context.Background(), authboss.TxtInvalid2FACode) {
t.Error("data wrong:", got)
}
})
@ -533,7 +533,7 @@ func TestPostValidate(t *testing.T) {
if h.responder.Page != PageTOTPValidate {
t.Error("page wrong:", h.responder.Page)
}
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != "2fa code was previously used" {
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != h.ab.Localize(context.Background(), authboss.TxtRepeated2FACode) {
t.Error("data wrong:", got)
}
})
@ -621,7 +621,7 @@ func TestPostValidate(t *testing.T) {
// Flush client state
w.WriteHeader(http.StatusOK)
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != "2fa code was invalid" {
if got := h.responder.Data[authboss.DataValidation].(map[string][]string); got[FormValueCode][0] != h.ab.Localize(context.Background(), authboss.TxtInvalid2FACode) {
t.Error("data wrong:", got)
}
})

View File

@ -110,7 +110,7 @@ func (e EmailVerify) PostStart(w http.ResponseWriter, r *http.Request) error {
ro := authboss.RedirectOptions{
Code: http.StatusTemporaryRedirect,
RedirectPath: e.Authboss.Config.Paths.TwoFactorEmailAuthNotOK,
Success: "An e-mail has been sent to confirm 2FA activation.",
Success: e.Localize(ctx, authboss.TxtEmailVerifyTriggered),
}
return e.Authboss.Config.Core.Redirector.Redirect(w, r, ro)
}
@ -125,7 +125,7 @@ func (e EmailVerify) SendVerifyEmail(ctx context.Context, to, token string) {
To: []string{to},
From: e.Config.Mail.From,
FromName: e.Config.Mail.FromName,
Subject: e.Config.Mail.SubjectPrefix + "Add 2FA to Account",
Subject: e.Config.Mail.SubjectPrefix + e.Localize(ctx, authboss.TxtEmailVerifySubject),
}
logger.Infof("sending add 2fa verification e-mail to: %s", to)
@ -168,7 +168,7 @@ func (e EmailVerify) End(w http.ResponseWriter, r *http.Request) error {
if 1 != subtle.ConstantTimeCompare([]byte(wantToken), []byte(givenToken)) {
ro := authboss.RedirectOptions{
Code: http.StatusTemporaryRedirect,
Failure: "invalid 2fa e-mail verification token",
Failure: e.Localize(r.Context(), authboss.TxtInvalid2FAVerificationToken),
RedirectPath: e.Authboss.Config.Paths.TwoFactorEmailAuthNotOK,
}
return e.Authboss.Core.Redirector.Redirect(w, r, ro)
@ -203,7 +203,7 @@ func (e EmailVerify) Wrap(handler http.Handler) http.Handler {
redirURL := path.Join(e.Authboss.Config.Paths.Mount, "2fa", e.TwofactorKind, "email/verify")
ro := authboss.RedirectOptions{
Code: http.StatusTemporaryRedirect,
Failure: "You must first authorize adding 2fa by e-mail.",
Failure: e.Localize(r.Context(), authboss.Txt2FAAuthorizationRequired),
RedirectPath: redirURL,
}

View File

@ -153,7 +153,7 @@ func TestEmailVerifyPostStart(t *testing.T) {
t.Error("code wrong:", ro.Code)
}
if ro.Success != "An e-mail has been sent to confirm 2FA activation." {
if ro.Success != h.ab.Localize(context.Background(), authboss.TxtEmailVerifyTriggered) {
t.Error("message was wrong:", ro.Success)
}
@ -240,7 +240,7 @@ func TestEmailVerifyEndFail(t *testing.T) {
t.Error("redir path wrong:", ro.RedirectPath)
}
if ro.Failure != "invalid 2fa e-mail verification token" {
if ro.Failure != h.ab.Localize(context.Background(), authboss.TxtInvalid2FAVerificationToken) {
t.Error("did not get correct failure")
}
@ -317,7 +317,7 @@ func TestEmailVerifyWrap(t *testing.T) {
t.Error("redir path wrong:", ro.RedirectPath)
}
if ro.Failure != "You must first authorize adding 2fa by e-mail." {
if ro.Failure != h.ab.Localize(context.Background(), authboss.Txt2FAAuthorizationRequired) {
t.Error("did not get correct failure")
}
})