From 05cb672cff573aa9035664ecc0e7b464a26182f1 Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Tue, 20 Sep 2022 09:22:47 +0200 Subject: [PATCH] fix(login): custom texts for pages called directly form mail link (#4415) * fix(login): translate init password correctly * refactor: no error return params * fix(login): custom texts for pages called directly form mail link * fix custom text on registration pages Co-authored-by: adlerhurst --- .../api/ui/login/change_password_handler.go | 3 +- .../api/ui/login/init_password_handler.go | 28 +++++---- internal/api/ui/login/init_user_handler.go | 30 ++++----- internal/api/ui/login/mail_verify_handler.go | 7 ++- .../password_complexity_policy_handler.go | 61 +++---------------- .../passwordless_registration_handler.go | 10 ++- internal/api/ui/login/register_handler.go | 23 +++---- internal/api/ui/login/register_org_handler.go | 6 +- internal/api/ui/login/renderer.go | 11 ++-- .../static/templates/change_password.html | 4 +- .../login/static/templates/init_password.html | 2 +- .../ui/login/static/templates/init_user.html | 2 +- .../templates/password_complexity_policy.html | 18 ++++++ .../ui/login/static/templates/register.html | 2 +- .../login/static/templates/register_org.html | 4 +- 15 files changed, 100 insertions(+), 111 deletions(-) create mode 100644 internal/api/ui/login/static/templates/password_complexity_policy.html diff --git a/internal/api/ui/login/change_password_handler.go b/internal/api/ui/login/change_password_handler.go index e6117c5fe..3c1abb6f5 100644 --- a/internal/api/ui/login/change_password_handler.go +++ b/internal/api/ui/login/change_password_handler.go @@ -44,9 +44,8 @@ func (l *Login) renderChangePassword(w http.ResponseWriter, r *http.Request, aut baseData: l.getBaseData(r, authReq, "Change Password", errID, errMessage), profileData: l.getProfileData(authReq), } - policy, description, _ := l.getPasswordComplexityPolicy(r, authReq, authReq.UserOrgID) + policy := l.getPasswordComplexityPolicy(r, authReq.UserOrgID) if policy != nil { - data.PasswordPolicyDescription = description data.MinLength = policy.MinLength if policy.HasUppercase { data.HasUppercase = UpperCaseRegex diff --git a/internal/api/ui/login/init_password_handler.go b/internal/api/ui/login/init_password_handler.go index 0555214fd..ca577c995 100644 --- a/internal/api/ui/login/init_password_handler.go +++ b/internal/api/ui/login/init_password_handler.go @@ -29,14 +29,13 @@ type initPasswordFormData struct { type initPasswordData struct { baseData profileData - Code string - UserID string - PasswordPolicyDescription string - MinLength uint64 - HasUppercase string - HasLowercase string - HasNumber string - HasSymbol string + Code string + UserID string + MinLength uint64 + HasUppercase string + HasLowercase string + HasNumber string + HasSymbol string } func InitPasswordLink(origin, userID, code, orgID string) string { @@ -85,7 +84,7 @@ func (l *Login) checkPWCode(w http.ResponseWriter, r *http.Request, authReq *dom l.renderInitPassword(w, r, authReq, data.UserID, "", err) return } - l.renderInitPasswordDone(w, r, authReq) + l.renderInitPasswordDone(w, r, authReq, userOrg) } func (l *Login) resendPasswordSet(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) { @@ -130,9 +129,8 @@ func (l *Login) renderInitPassword(w http.ResponseWriter, r *http.Request, authR UserID: userID, Code: code, } - policy, description, _ := l.getPasswordComplexityPolicyByUserID(r, authReq, userID) + policy := l.getPasswordComplexityPolicyByUserID(r, userID) if policy != nil { - data.PasswordPolicyDescription = description data.MinLength = policy.MinLength if policy.HasUppercase { data.HasUppercase = UpperCaseRegex @@ -157,7 +155,11 @@ func (l *Login) renderInitPassword(w http.ResponseWriter, r *http.Request, authR l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplInitPassword], data, nil) } -func (l *Login) renderInitPasswordDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) { +func (l *Login) renderInitPasswordDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, orgID string) { data := l.getUserData(r, authReq, "Password Init Done", "", "") - l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplInitPasswordDone], data, nil) + translator := l.getTranslator(r.Context(), authReq) + if authReq == nil { + l.customTexts(r.Context(), translator, orgID) + } + l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplInitPasswordDone], data, nil) } diff --git a/internal/api/ui/login/init_user_handler.go b/internal/api/ui/login/init_user_handler.go index b90e1070d..fb1240c48 100644 --- a/internal/api/ui/login/init_user_handler.go +++ b/internal/api/ui/login/init_user_handler.go @@ -30,15 +30,14 @@ type initUserFormData struct { type initUserData struct { baseData profileData - Code string - UserID string - PasswordSet bool - PasswordPolicyDescription string - MinLength uint64 - HasUppercase string - HasLowercase string - HasNumber string - HasSymbol string + Code string + UserID string + PasswordSet bool + MinLength uint64 + HasUppercase string + HasLowercase string + HasNumber string + HasSymbol string } func InitUserLink(origin, userID, code, orgID string, passwordSet bool) string { @@ -87,7 +86,7 @@ func (l *Login) checkUserInitCode(w http.ResponseWriter, r *http.Request, authRe l.renderInitUser(w, r, authReq, data.UserID, "", data.PasswordSet, err) return } - l.renderInitUserDone(w, r, authReq) + l.renderInitUserDone(w, r, authReq, userOrgID) } func (l *Login) resendUserInit(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, userID string, showPassword bool) { @@ -119,9 +118,8 @@ func (l *Login) renderInitUser(w http.ResponseWriter, r *http.Request, authReq * Code: code, PasswordSet: passwordSet, } - policy, description, _ := l.getPasswordComplexityPolicyByUserID(r, nil, userID) + policy := l.getPasswordComplexityPolicyByUserID(r, userID) if policy != nil { - data.PasswordPolicyDescription = description data.MinLength = policy.MinLength if policy.HasUppercase { data.HasUppercase = UpperCaseRegex @@ -146,7 +144,11 @@ func (l *Login) renderInitUser(w http.ResponseWriter, r *http.Request, authReq * l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplInitUser], data, nil) } -func (l *Login) renderInitUserDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) { +func (l *Login) renderInitUserDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, orgID string) { data := l.getUserData(r, authReq, "User Init Done", "", "") - l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplInitUserDone], data, nil) + translator := l.getTranslator(r.Context(), authReq) + if authReq == nil { + l.customTexts(r.Context(), translator, orgID) + } + l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplInitUserDone], data, nil) } diff --git a/internal/api/ui/login/mail_verify_handler.go b/internal/api/ui/login/mail_verify_handler.go index 36449fdfb..db781005c 100644 --- a/internal/api/ui/login/mail_verify_handler.go +++ b/internal/api/ui/login/mail_verify_handler.go @@ -81,7 +81,7 @@ func (l *Login) checkMailCode(w http.ResponseWriter, r *http.Request, authReq *d l.renderMailVerification(w, r, authReq, userID, err) return } - l.renderMailVerified(w, r, authReq) + l.renderMailVerified(w, r, authReq, userOrg) } func (l *Login) renderMailVerification(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, userID string, err error) { @@ -107,11 +107,14 @@ func (l *Login) renderMailVerification(w http.ResponseWriter, r *http.Request, a l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplMailVerification], data, nil) } -func (l *Login) renderMailVerified(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) { +func (l *Login) renderMailVerified(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, orgID string) { data := mailVerificationData{ baseData: l.getBaseData(r, authReq, "Mail Verified", "", ""), profileData: l.getProfileData(authReq), } translator := l.getTranslator(r.Context(), authReq) + if authReq == nil { + l.customTexts(r.Context(), translator, orgID) + } l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplMailVerified], data, nil) } diff --git a/internal/api/ui/login/password_complexity_policy_handler.go b/internal/api/ui/login/password_complexity_policy_handler.go index b4d344bea..805194a07 100644 --- a/internal/api/ui/login/password_complexity_policy_handler.go +++ b/internal/api/ui/login/password_complexity_policy_handler.go @@ -2,10 +2,9 @@ package login import ( "net/http" - "regexp" - "strconv" - "github.com/zitadel/zitadel/internal/domain" + "github.com/zitadel/logging" + iam_model "github.com/zitadel/zitadel/internal/iam/model" ) @@ -16,59 +15,19 @@ const ( SymbolRegex = `[^A-Za-z0-9]` ) -var ( - hasStringLowerCase = regexp.MustCompile(LowerCaseRegex).MatchString - hasStringUpperCase = regexp.MustCompile(UpperCaseRegex).MatchString - hasNumber = regexp.MustCompile(NumberRegex).MatchString - hasSymbol = regexp.MustCompile(SymbolRegex).MatchString -) - -func (l *Login) getPasswordComplexityPolicy(r *http.Request, authReq *domain.AuthRequest, orgID string) (*iam_model.PasswordComplexityPolicyView, string, error) { +func (l *Login) getPasswordComplexityPolicy(r *http.Request, orgID string) *iam_model.PasswordComplexityPolicyView { policy, err := l.authRepo.GetMyPasswordComplexityPolicy(setContext(r.Context(), orgID)) - if err != nil { - return nil, err.Error(), err - } - description, err := l.generatePolicyDescription(r, authReq, policy) - return policy, description, nil + logging.WithFields("orgID", orgID).OnError(err).Error("could not load password complexity policy") + return policy } -func (l *Login) getPasswordComplexityPolicyByUserID(r *http.Request, authReq *domain.AuthRequest, userID string) (*iam_model.PasswordComplexityPolicyView, string, error) { +func (l *Login) getPasswordComplexityPolicyByUserID(r *http.Request, userID string) *iam_model.PasswordComplexityPolicyView { user, err := l.query.GetUserByID(r.Context(), false, userID) if err != nil { - return nil, "", nil + logging.WithFields("userID", userID).OnError(err).Error("could not load user for password complexity policy") + return nil } policy, err := l.authRepo.GetMyPasswordComplexityPolicy(setContext(r.Context(), user.ResourceOwner)) - if err != nil { - return nil, err.Error(), err - } - description, err := l.generatePolicyDescription(r, authReq, policy) - return policy, description, nil -} - -func (l *Login) generatePolicyDescription(r *http.Request, authReq *domain.AuthRequest, policy *iam_model.PasswordComplexityPolicyView) (string, error) { - description := "" - return description, nil + logging.WithFields("orgID", user.ResourceOwner, "userID", userID).OnError(err).Error("could not load password complexity policy") + return policy } diff --git a/internal/api/ui/login/passwordless_registration_handler.go b/internal/api/ui/login/passwordless_registration_handler.go index 18be29f1c..4ec7e9d6e 100644 --- a/internal/api/ui/login/passwordless_registration_handler.go +++ b/internal/api/ui/login/passwordless_registration_handler.go @@ -183,10 +183,10 @@ func (l *Login) checkPasswordlessRegistration(w http.ResponseWriter, r *http.Req l.renderPasswordlessRegistration(w, r, authReq, formData.UserID, formData.OrgID, formData.CodeID, formData.Code, formData.RequestPlatformType, err) return } - l.renderPasswordlessRegistrationDone(w, r, authReq, nil) + l.renderPasswordlessRegistrationDone(w, r, authReq, formData.OrgID, nil) } -func (l *Login) renderPasswordlessRegistrationDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, err error) { +func (l *Login) renderPasswordlessRegistrationDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, orgID string, err error) { var errID, errMessage string if err != nil { errID, errMessage = l.getErrorMessage(r, err) @@ -195,5 +195,9 @@ func (l *Login) renderPasswordlessRegistrationDone(w http.ResponseWriter, r *htt userData: l.getUserData(r, authReq, "Passwordless Registration Done", errID, errMessage), HideNextButton: authReq == nil, } - l.renderer.RenderTemplate(w, r, l.getTranslator(r.Context(), authReq), l.renderer.Templates[tmplPasswordlessRegistrationDone], data, nil) + translator := l.getTranslator(r.Context(), authReq) + if authReq == nil { + l.customTexts(r.Context(), translator, orgID) + } + l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplPasswordlessRegistrationDone], data, nil) } diff --git a/internal/api/ui/login/register_handler.go b/internal/api/ui/login/register_handler.go index 271654350..6d2d69e3b 100644 --- a/internal/api/ui/login/register_handler.go +++ b/internal/api/ui/login/register_handler.go @@ -30,15 +30,14 @@ type registerFormData struct { type registerData struct { baseData registerFormData - PasswordPolicyDescription string - MinLength uint64 - HasUppercase string - HasLowercase string - HasNumber string - HasSymbol string - ShowUsername bool - ShowUsernameSuffix bool - OrgRegister bool + MinLength uint64 + HasUppercase string + HasLowercase string + HasNumber string + HasSymbol string + ShowUsername bool + ShowUsernameSuffix bool + OrgRegister bool } func (l *Login) handleRegister(w http.ResponseWriter, r *http.Request) { @@ -124,9 +123,8 @@ func (l *Login) renderRegister(w http.ResponseWriter, r *http.Request, authReque registerFormData: *formData, } - pwPolicy, description, _ := l.getPasswordComplexityPolicy(r, authRequest, resourceOwner) + pwPolicy := l.getPasswordComplexityPolicy(r, resourceOwner) if pwPolicy != nil { - data.PasswordPolicyDescription = description data.MinLength = pwPolicy.MinLength if pwPolicy.HasUppercase { data.HasUppercase = UpperCaseRegex @@ -171,6 +169,9 @@ func (l *Login) renderRegister(w http.ResponseWriter, r *http.Request, authReque return formData.Gender == g }, } + if authRequest == nil { + l.customTexts(r.Context(), translator, resourceOwner) + } l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplRegister], data, funcs) } diff --git a/internal/api/ui/login/register_org_handler.go b/internal/api/ui/login/register_org_handler.go index fb5d7b19f..4338a86b9 100644 --- a/internal/api/ui/login/register_org_handler.go +++ b/internal/api/ui/login/register_org_handler.go @@ -90,9 +90,8 @@ func (l *Login) renderRegisterOrg(w http.ResponseWriter, r *http.Request, authRe baseData: l.getBaseData(r, authRequest, "Register", errID, errMessage), registerOrgFormData: *formData, } - pwPolicy, description, _ := l.getPasswordComplexityPolicy(r, authRequest, "0") + pwPolicy := l.getPasswordComplexityPolicy(r, "0") if pwPolicy != nil { - data.PasswordPolicyDescription = description data.MinLength = pwPolicy.MinLength if pwPolicy.HasUppercase { data.HasUppercase = UpperCaseRegex @@ -114,6 +113,9 @@ func (l *Login) renderRegisterOrg(w http.ResponseWriter, r *http.Request, authRe } translator := l.getTranslator(r.Context(), authRequest) + if authRequest == nil { + l.customTexts(r.Context(), translator, "") + } l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplRegisterOrg], data, nil) } diff --git a/internal/api/ui/login/renderer.go b/internal/api/ui/login/renderer.go index 21f5ae719..1255ff740 100644 --- a/internal/api/ui/login/renderer.go +++ b/internal/api/ui/login/renderer.go @@ -611,12 +611,11 @@ type profileData struct { type passwordData struct { baseData profileData - PasswordPolicyDescription string - MinLength uint64 - HasUppercase string - HasLowercase string - HasNumber string - HasSymbol string + MinLength uint64 + HasUppercase string + HasLowercase string + HasNumber string + HasSymbol string } type userSelectionData struct { diff --git a/internal/api/ui/login/static/templates/change_password.html b/internal/api/ui/login/static/templates/change_password.html index 642723f68..de4ca2bb1 100644 --- a/internal/api/ui/login/static/templates/change_password.html +++ b/internal/api/ui/login/static/templates/change_password.html @@ -26,7 +26,7 @@ data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}" data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="change-new-password" name="change-new-password" autocomplete="new-password" required> - {{ .PasswordPolicyDescription }} + {{ template "password-complexity-policy-description" . }}
@@ -54,4 +54,4 @@ -{{template "main-bottom" .}} \ No newline at end of file +{{template "main-bottom" .}} diff --git a/internal/api/ui/login/static/templates/init_password.html b/internal/api/ui/login/static/templates/init_password.html index 613ce3d09..eea512cc8 100644 --- a/internal/api/ui/login/static/templates/init_password.html +++ b/internal/api/ui/login/static/templates/init_password.html @@ -27,7 +27,7 @@ data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}" data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="password" name="password" autocomplete="new-password" autofocus required> - {{ .PasswordPolicyDescription }} + {{ template "password-complexity-policy-description" . }}
diff --git a/internal/api/ui/login/static/templates/init_user.html b/internal/api/ui/login/static/templates/init_user.html index 075d143cb..d375dd6f1 100644 --- a/internal/api/ui/login/static/templates/init_user.html +++ b/internal/api/ui/login/static/templates/init_user.html @@ -31,7 +31,7 @@ data-has-lowercase="{{ .HasLowercase }}" data-has-number="{{ .HasNumber }}" data-has-symbol="{{ .HasSymbol }}" class="lgn-input" type="password" id="password" name="password" autocomplete="new-password" autofocus required> - {{ .PasswordPolicyDescription }} + {{ template "password-complexity-policy-description" . }}
diff --git a/internal/api/ui/login/static/templates/password_complexity_policy.html b/internal/api/ui/login/static/templates/password_complexity_policy.html new file mode 100644 index 000000000..f8f5d3476 --- /dev/null +++ b/internal/api/ui/login/static/templates/password_complexity_policy.html @@ -0,0 +1,18 @@ +{{define "password-complexity-policy-description"}} +
    +
  • {{t "Password.MinLength"}} {{.MinLength}}
  • + {{if .HasUppercase }} +
  • {{t "Password.HasUppercase"}}
  • + {{end}} + {{if .HasLowercase}} +
  • {{t "Password.HasLowercase"}}
  • + {{end}} + {{if .HasNumber}} +
  • {{t "Password.HasNumber"}}
  • + {{end}} + {{if .HasSymbol}} +
  • {{t "Password.HasSymbol"}}
  • + {{end}} +
  • {{t "Password.Confirmation"}}
  • +
+{{end}} diff --git a/internal/api/ui/login/static/templates/register.html b/internal/api/ui/login/static/templates/register.html index 08280b2b3..ab82b17b4 100644 --- a/internal/api/ui/login/static/templates/register.html +++ b/internal/api/ui/login/static/templates/register.html @@ -97,7 +97,7 @@
- {{ .PasswordPolicyDescription }} + {{ template "password-complexity-policy-description" . }}
{{ if or .TOSLink .PrivacyLink }} diff --git a/internal/api/ui/login/static/templates/register_org.html b/internal/api/ui/login/static/templates/register_org.html index c49814d59..9ffe13194 100644 --- a/internal/api/ui/login/static/templates/register_org.html +++ b/internal/api/ui/login/static/templates/register_org.html @@ -64,7 +64,7 @@
- {{ .PasswordPolicyDescription }} + {{ template "password-complexity-policy-description" . }}
{{ if or .TOSLink .PrivacyLink }} @@ -109,4 +109,4 @@ -{{template "main-bottom" .}} \ No newline at end of file +{{template "main-bottom" .}}