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

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

View File

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

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

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,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 {

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">
@ -54,4 +54,4 @@
<script src="{{ resourceUrl "scripts/change_password_check.js" }}"></script>
{{template "main-bottom" .}}
{{template "main-bottom" .}}

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 }}
@ -109,4 +109,4 @@
<script src="{{ resourceUrl "scripts/register_check.js" }}"></script>
<script src="{{ resourceUrl "scripts/loginname_suffix.js" }}"></script>
{{template "main-bottom" .}}
{{template "main-bottom" .}}