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 <silvan.reusser@gmail.com>
This commit is contained in:
Livio Spring 2022-09-20 09:22:47 +02:00 committed by GitHub
parent fc4f4096e0
commit 05cb672cff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 100 additions and 111 deletions

View File

@ -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

View File

@ -31,7 +31,6 @@ type initPasswordData struct {
profileData
Code string
UserID string
PasswordPolicyDescription string
MinLength uint64
HasUppercase string
HasLowercase 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)
}

View File

@ -33,7 +33,6 @@ type initUserData struct {
Code string
UserID string
PasswordSet bool
PasswordPolicyDescription string
MinLength uint64
HasUppercase string
HasLowercase 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)
}

View File

@ -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)
}

View File

@ -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 := "<ul class=\"lgn-no-dots lgn-policy\" id=\"passwordcomplexity\">"
translator := l.getTranslator(r.Context(), authReq)
minLength := l.renderer.LocalizeFromRequest(translator, r, "Password.MinLength", nil)
description += "<li id=\"minlength\" class=\"invalid\"><i class=\"lgn-icon-times-solid lgn-warn\"></i><span>" + minLength + " " + strconv.Itoa(int(policy.MinLength)) + "</span></li>"
if policy.HasUppercase {
uppercase := l.renderer.LocalizeFromRequest(translator, r, "Password.HasUppercase", nil)
description += "<li id=\"uppercase\" class=\"invalid\"><i class=\"lgn-icon-times-solid lgn-warn\"></i><span>" + uppercase + "</span></li>"
}
if policy.HasLowercase {
lowercase := l.renderer.LocalizeFromRequest(translator, r, "Password.HasLowercase", nil)
description += "<li id=\"lowercase\" class=\"invalid\"><i class=\"lgn-icon-times-solid lgn-warn\"></i><span>" + lowercase + "</span></li>"
}
if policy.HasNumber {
hasnumber := l.renderer.LocalizeFromRequest(translator, r, "Password.HasNumber", nil)
description += "<li id=\"number\" class=\"invalid\"><i class=\"lgn-icon-times-solid lgn-warn\"></i><span>" + hasnumber + "</span></li>"
}
if policy.HasSymbol {
hassymbol := l.renderer.LocalizeFromRequest(translator, r, "Password.HasSymbol", nil)
description += "<li id=\"symbol\" class=\"invalid\"><i class=\"lgn-icon-times-solid lgn-warn\"></i><span>" + hassymbol + "</span></li>"
}
confirmation := l.renderer.LocalizeFromRequest(translator, r, "Password.Confirmation", nil)
description += "<li id=\"confirmation\" class=\"invalid\"><i class=\"lgn-icon-times-solid lgn-warn\"></i><span>" + confirmation + "</span></li>"
description += "</ul>"
return description, nil
logging.WithFields("orgID", user.ResourceOwner, "userID", userID).OnError(err).Error("could not load password complexity policy")
return policy
}

View File

@ -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)
}

View File

@ -30,7 +30,6 @@ type registerFormData struct {
type registerData struct {
baseData
registerFormData
PasswordPolicyDescription string
MinLength uint64
HasUppercase string
HasLowercase string
@ -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)
}

View File

@ -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)
}

View File

@ -611,7 +611,6 @@ type profileData struct {
type passwordData struct {
baseData
profileData
PasswordPolicyDescription string
MinLength uint64
HasUppercase string
HasLowercase string

View File

@ -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" . }}
</div>
<div class="field">

View File

@ -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" . }}
</div>
<div class="field">
<label class="lgn-label" for="passwordconfirm">{{t "InitPassword.NewPasswordConfirmLabel"}}</label>

View File

@ -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" . }}
</div>
<div class="field">
<label class="lgn-label" for="passwordconfirm">{{t "InitUser.NewPasswordConfirmLabel"}}</label>

View File

@ -0,0 +1,18 @@
{{define "password-complexity-policy-description"}}
<ul class="lgn-no-dots lgn-policy" id="passwordcomplexity">
<li id="minlength" class="invalid"><i class="lgn-icon-times-solid lgn-warn"></i><span>{{t "Password.MinLength"}} {{.MinLength}}</span></li>
{{if .HasUppercase }}
<li id="uppercase" class="invalid"><i class="lgn-icon-times-solid lgn-warn"></i><span>{{t "Password.HasUppercase"}}</span></li>
{{end}}
{{if .HasLowercase}}
<li id="lowercase" class="invalid"><i class="lgn-icon-times-solid lgn-warn"></i><span>{{t "Password.HasLowercase"}}</span></li>
{{end}}
{{if .HasNumber}}
<li id="number" class="invalid"><i class="lgn-icon-times-solid lgn-warn"></i><span>{{t "Password.HasNumber"}}</span></li>
{{end}}
{{if .HasSymbol}}
<li id="symbol" class="invalid"><i class="lgn-icon-times-solid lgn-warn"></i><span>{{t "Password.HasSymbol"}}</span></li>
{{end}}
<li id="confirmation" class="invalid"><i class="lgn-icon-times-solid lgn-warn"></i><span>{{t "Password.Confirmation"}}</span></li>
</ul>
{{end}}

View File

@ -97,7 +97,7 @@
</div>
<div class="lgn-field">
{{ .PasswordPolicyDescription }}
{{ template "password-complexity-policy-description" . }}
</div>
{{ if or .TOSLink .PrivacyLink }}

View File

@ -64,7 +64,7 @@
</div>
</div>
<div class="lgn-field">
{{ .PasswordPolicyDescription }}
{{ template "password-complexity-policy-description" . }}
</div>
{{ if or .TOSLink .PrivacyLink }}