fix(login): mfa prompt UI improvements, fix register field validation, email validation (#4672)

* fix: mfa prompt styling

* register password field validation

* loginname overflow, mfa hover effect

* cleanup

* Update internal/api/ui/login/static/resources/scripts/password_policy_check.js

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* prettier if check

* cleanup

* Update internal/api/ui/login/static/resources/scripts/password_policy_check.js

Co-authored-by: Livio Spring <livio.a@gmail.com>

* fix confirmation validation, cleanup

* rm log

* email type validation

* add email validation

* change pattern

* pattern

* comment RFC 2822

* dont wrapp org name

* rm email validation

Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Max Peintner 2022-11-17 13:25:09 +01:00 committed by GitHub
parent 7db87f4646
commit 2a8dfab192
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 240 additions and 180 deletions

View File

@ -1,16 +1,14 @@
function CheckChangePwPolicy() { function CheckChangePwPolicy() {
let policyElement = document.getElementById("change-new-password"); const pwNew = document.getElementById("change-new-password");
let pwNew = policyElement.value; const pwNewValue = pwNew.value;
let pwNewConfirmation = document.getElementById("change-password-confirmation").value; const pwNewConfirmation = document.getElementById(
"change-password-confirmation"
);
const pwNewConfirmationValue = pwNewConfirmation.value;
if (ComplexityPolicyCheck(policyElement, pwNew, pwNewConfirmation) === false) { ComplexityPolicyCheck(pwNew, pwNewConfirmation);
policyElement.setAttribute("color", "warn");
return false;
} else {
policyElement.setAttribute("color", "primary");
}
return pwNew === pwNewConfirmation; return pwNewValue == pwNewConfirmationValue;
} }
let button = document.getElementById("change-password-button"); let button = document.getElementById("change-password-button");

View File

@ -1,13 +1,12 @@
function CheckInitPwPolicy() { function CheckInitPwPolicy() {
let policyElement = document.getElementById("password"); const pwNew = document.getElementById("password");
let pwNew = policyElement.value; const pwNewValue = pwNew.value;
let pwNewConfirmation = document.getElementById("passwordconfirm").value; const pwNewConfirmation = document.getElementById("passwordconfirm");
const pwNewConfirmationValue = pwNewConfirmation.value;
if (ComplexityPolicyCheck(policyElement, pwNew, pwNewConfirmation) === false) { ComplexityPolicyCheck(pwNew, pwNewConfirmation);
return false;
}
return pwNew == pwNewConfirmation; return pwNewValue == pwNewConfirmationValue;
} }
let button = document.getElementById("init-button"); let button = document.getElementById("init-button");

View File

@ -0,0 +1,20 @@
validate();
document.querySelectorAll('input[name="provider"]').forEach((input) => {
input.addEventListener("change", validate);
});
function validate() {
const checkedMfaMethod = document.querySelector(
'input[name="provider"]:checked'
);
const submitButton = document.querySelector(
'button.lgn-raised-button[type="submit"]'
);
if (checkedMfaMethod && submitButton) {
submitButton.disabled = false;
} else if (submitButton) {
submitButton.disabled = true;
}
}

View File

@ -1,77 +1,93 @@
function ComplexityPolicyCheck(policyElement, pwNew, pwNewConfirmation) { function ComplexityPolicyCheck(passwordElement, passwordConfirmationElement) {
let minLength = policyElement.dataset.minlength; const minLength = passwordElement.dataset.minlength;
let upperRegex = policyElement.dataset.hasUppercase; const upperRegex = passwordElement.dataset.hasUppercase;
let lowerRegex = policyElement.dataset.hasLowercase; const lowerRegex = passwordElement.dataset.hasLowercase;
let numberRegex = policyElement.dataset.hasNumber; const numberRegex = passwordElement.dataset.hasNumber;
let symbolRegex = policyElement.dataset.hasSymbol; const symbolRegex = passwordElement.dataset.hasSymbol;
let invalid = 0; let invalid = 0;
let minlengthelem = document.getElementById('minlength'); const minLengthElem = document.getElementById("minlength");
if (pwNew.length >= minLength) { if (passwordElement.value.length >= minLength) {
ValidPolicy(minlengthelem); ValidPolicy(minLengthElem);
} else { } else {
InvalidPolicy(minlengthelem); InvalidPolicy(minLengthElem);
invalid++; invalid++;
} }
let upper = document.getElementById('uppercase');
const upper = document.getElementById("uppercase");
if (upperRegex !== "") { if (upperRegex !== "") {
if (RegExp(upperRegex).test(pwNew)) { if (RegExp(upperRegex).test(passwordElement.value)) {
ValidPolicy(upper); ValidPolicy(upper);
} else { } else {
InvalidPolicy(upper); InvalidPolicy(upper);
invalid++; invalid++;
} }
} }
let lower = document.getElementById('lowercase');
const lower = document.getElementById("lowercase");
if (lowerRegex !== "") { if (lowerRegex !== "") {
if (RegExp(lowerRegex).test(pwNew)) { if (RegExp(lowerRegex).test(passwordElement.value)) {
ValidPolicy(lower); ValidPolicy(lower);
} else { } else {
InvalidPolicy(lower); InvalidPolicy(lower);
invalid++; invalid++;
} }
} }
let number = document.getElementById('number');
const number = document.getElementById("number");
if (numberRegex !== "") { if (numberRegex !== "") {
if (RegExp(numberRegex).test(pwNew)) { if (RegExp(numberRegex).test(passwordElement.value)) {
ValidPolicy(number); ValidPolicy(number);
} else { } else {
InvalidPolicy(number); InvalidPolicy(number);
invalid++; invalid++;
} }
} }
let symbol = document.getElementById('symbol');
const symbol = document.getElementById("symbol");
if (symbolRegex !== "") { if (symbolRegex !== "") {
if (RegExp(symbolRegex).test(pwNew)) { if (RegExp(symbolRegex).test(passwordElement.value)) {
ValidPolicy(symbol); ValidPolicy(symbol);
} else { } else {
InvalidPolicy(symbol); InvalidPolicy(symbol);
invalid++; invalid++;
} }
} }
let confirmation = document.getElementById('confirmation');
if (pwNew === pwNewConfirmation && pwNewConfirmation !== "" ) { const confirmation = document.getElementById("confirmation");
if (
passwordElement.value === passwordConfirmationElement.value &&
passwordConfirmationElement.value !== ""
) {
ValidPolicy(confirmation); ValidPolicy(confirmation);
passwordConfirmationElement.setAttribute("color", "primary");
} else { } else {
InvalidPolicy(confirmation); InvalidPolicy(confirmation);
invalid++; passwordConfirmationElement.setAttribute("color", "warn");
}
if (invalid > 0) {
passwordElement.setAttribute("color", "warn");
return false;
} else {
passwordElement.setAttribute("color", "primary");
return true;
} }
return invalid===0;
} }
function ValidPolicy(element) { function ValidPolicy(element) {
element.classList.remove('invalid'); element.classList.remove("invalid");
element.getElementsByTagName('i')[0].classList.remove('lgn-icon-times-solid'); element.getElementsByTagName("i")[0].classList.remove("lgn-icon-times-solid");
element.getElementsByTagName('i')[0].classList.remove('lgn-warn'); element.getElementsByTagName("i")[0].classList.remove("lgn-warn");
element.getElementsByTagName('i')[0].classList.add('lgn-icon-check-solid'); element.getElementsByTagName("i")[0].classList.add("lgn-icon-check-solid");
element.getElementsByTagName('i')[0].classList.add('lgn-valid'); element.getElementsByTagName("i")[0].classList.add("lgn-valid");
} }
function InvalidPolicy(element) { function InvalidPolicy(element) {
element.classList.add('invalid'); element.classList.add("invalid");
element.getElementsByTagName('i')[0].classList.remove('lgn-valid'); element.getElementsByTagName("i")[0].classList.remove("lgn-valid");
element.getElementsByTagName('i')[0].classList.remove('lgn-icon-check-solid'); element.getElementsByTagName("i")[0].classList.remove("lgn-icon-check-solid");
element.getElementsByTagName('i')[0].classList.add('lgn-warn'); element.getElementsByTagName("i")[0].classList.add("lgn-warn");
element.getElementsByTagName('i')[0].classList.add('lgn-icon-times-solid'); element.getElementsByTagName("i")[0].classList.add("lgn-icon-times-solid");
} }

View File

@ -1,16 +1,14 @@
function CheckRegisterPwPolicy() { function CheckRegisterPwPolicy() {
let policyElement = document.getElementById("register-password"); const pwNew = document.getElementById("register-password");
let pwNew = policyElement.value; const pwNewConfirmation = document.getElementById(
let pwNewConfirmation = document.getElementById("register-password-confirmation").value; "register-password-confirmation"
);
const pwNewValue = pwNew.value;
const pwNewConfirmationValue = pwNewConfirmation.value;
if (ComplexityPolicyCheck(policyElement, pwNew, pwNewConfirmation) === false) { ComplexityPolicyCheck(pwNew, pwNewConfirmation);
policyElement.setAttribute("color", "warn");
return false;
} else {
policyElement.setAttribute("color", "primary");
}
return pwNew == pwNewConfirmation; return pwNewValue == pwNewConfirmationValue;
} }
let button = document.getElementById("register-button"); let button = document.getElementById("register-button");

View File

@ -89,9 +89,15 @@ $lgn-container-bottom-margin: 50px;
.lgn-displayname { .lgn-displayname {
margin: 0.5rem 1rem; margin: 0.5rem 1rem;
} }
.lgn-loginname { .lgn-loginname {
min-width: 0;
p { p {
margin: 0.5rem 1rem; margin: 0.5rem 0.5rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
} }
} }
} }

View File

@ -23,5 +23,6 @@ select,
max-width: 150px; max-width: 150px;
overflow-x: hidden; overflow-x: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap;
} }
} }

View File

@ -11,38 +11,32 @@
flex: 1; flex: 1;
padding: 0 0.5rem; padding: 0 0.5rem;
input[type="radio"] + label { label {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: relative;
input[type="radio"] {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
span { span {
text-align: center; text-align: center;
} }
.mfa-img { .mfa-img {
border: 1px solid var(--zitadel-color-input-border); border-width: 1px;
border-style: solid;
border-radius: 0.5rem; border-radius: 0.5rem;
padding: 1rem; padding: 1rem;
display: flex; display: flex;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
transition: all 0.2s ease; transition: all 0.2s ease;
&:hover {
border: 1px solid var(--zitadel-color-input-border-active);
}
}
}
input[type="radio"] {
display: none;
&:checked {
& + label {
.mfa-img {
border: 1px solid var(--zitadel-color-primary);
}
}
} }
} }
} }

View File

@ -4,24 +4,25 @@
@mixin lgn-mfa-theme() { @mixin lgn-mfa-theme() {
.lgn-mfa-options { .lgn-mfa-options {
.mfa { .mfa {
input[type="radio"] + label { label {
input[type="radio"] {
&:hover,
&:focus {
+ .mfa-img {
background-color: var(--zitadel-color-card-hover);
border-color: var(--zitadel-color-input-border-hover);
}
}
}
.mfa-img { .mfa-img {
border: 1px solid var(--zitadel-color-input-border); border: 1px solid var(--zitadel-color-input-border);
background-color: var(--zitadel-color-input-background);
&:hover {
border: 1px solid var(--zitadel-color-input-border-hover);
}
}
} }
input[type="radio"] { input[type="radio"]:checked + .mfa-img {
&:checked { background-color: var(--zitadel-color-card-hover);
& + label { border: 1px solid var(--zitadel-color-input-border-active);
.mfa-img { box-shadow: 0 0 0 2px var(--zitadel-color-input-border-active);
border: 1px solid var(--zitadel-color-primary);
}
}
} }
} }
} }

View File

@ -44,6 +44,8 @@
--zitadel-color-footer-line: rgba(0, 0, 0, 0.12); --zitadel-color-footer-line: rgba(0, 0, 0, 0.12);
--zitadel-color-card-hover: #ffffff;
--zitadel-color-input-background: #00000003; --zitadel-color-input-background: #00000003;
--zitadel-color-input-border: #1a191938; --zitadel-color-input-border: #1a191938;
--zitadel-color-input-border-hover: #1a1b1b; --zitadel-color-input-border-hover: #1a1b1b;
@ -155,9 +157,11 @@
--zitadel-color-footer-line: rgba(255, 255, 255, 0.12); --zitadel-color-footer-line: rgba(255, 255, 255, 0.12);
--zitadel-color-card-hover: #ffffff20;
--zitadel-color-input-background: rgba(0, 0, 0, 0.2); --zitadel-color-input-background: rgba(0, 0, 0, 0.2);
--zitadel-color-input-border: #f9f7f725; --zitadel-color-input-border: #f9f7f725;
--zitadel-color-input-border-hover: #aeafb1; --zitadel-color-input-border-hover: #ffffff;
--zitadel-color-input-border-active: var(--zitadel-color-primary-500); --zitadel-color-input-border-active: var(--zitadel-color-primary-500);
--zitadel-color-input-placeholder: var(--zitadel-color-grey-600); --zitadel-color-input-placeholder: var(--zitadel-color-grey-600);

View File

@ -39,6 +39,7 @@
--zitadel-color-background-900: rgb(142, 142, 142); --zitadel-color-background-900: rgb(142, 142, 142);
--zitadel-color-background-contrast: rgb(0, 0, 0); --zitadel-color-background-contrast: rgb(0, 0, 0);
--zitadel-color-footer-line: rgba(0, 0, 0, 0.12); --zitadel-color-footer-line: rgba(0, 0, 0, 0.12);
--zitadel-color-card-hover: #ffffff;
--zitadel-color-input-background: #00000003; --zitadel-color-input-background: #00000003;
--zitadel-color-input-border: #1a191938; --zitadel-color-input-border: #1a191938;
--zitadel-color-input-border-hover: #1a1b1b; --zitadel-color-input-border-hover: #1a1b1b;
@ -135,9 +136,10 @@
--zitadel-color-background-900: rgb(23, 23, 23); --zitadel-color-background-900: rgb(23, 23, 23);
--zitadel-color-background-contrast: rgb(255, 255, 255); --zitadel-color-background-contrast: rgb(255, 255, 255);
--zitadel-color-footer-line: rgba(255, 255, 255, 0.12); --zitadel-color-footer-line: rgba(255, 255, 255, 0.12);
--zitadel-color-card-hover: #ffffff20;
--zitadel-color-input-background: rgba(0, 0, 0, 0.2); --zitadel-color-input-background: rgba(0, 0, 0, 0.2);
--zitadel-color-input-border: #f9f7f725; --zitadel-color-input-border: #f9f7f725;
--zitadel-color-input-border-hover: #aeafb1; --zitadel-color-input-border-hover: #ffffff;
--zitadel-color-input-border-active: var(--zitadel-color-primary-500); --zitadel-color-input-border-active: var(--zitadel-color-primary-500);
--zitadel-color-input-placeholder: var(--zitadel-color-grey-600); --zitadel-color-input-placeholder: var(--zitadel-color-grey-600);
--zitadel-color-text-50: rgb(255, 255, 255); --zitadel-color-text-50: rgb(255, 255, 255);
@ -654,8 +656,14 @@ a.sub-formfield-link {
.content-container .lgn-login-profile .lgn-names .lgn-displayname { .content-container .lgn-login-profile .lgn-names .lgn-displayname {
margin: 0.5rem 1rem; margin: 0.5rem 1rem;
} }
.content-container .lgn-login-profile .lgn-names .lgn-loginname {
min-width: 0;
}
.content-container .lgn-login-profile .lgn-names .lgn-loginname p { .content-container .lgn-login-profile .lgn-names .lgn-loginname p {
margin: 0.5rem 1rem; margin: 0.5rem 0.5rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
} }
.content-container .lgn-left-action { .content-container .lgn-left-action {
position: absolute; position: absolute;
@ -1147,31 +1155,31 @@ i {
flex: 1; flex: 1;
padding: 0 0.5rem; padding: 0 0.5rem;
} }
.lgn-mfa-options .mfa input[type=radio] + label { .lgn-mfa-options .mfa label {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: relative;
} }
.lgn-mfa-options .mfa input[type=radio] + label span { .lgn-mfa-options .mfa label input[type=radio] {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.lgn-mfa-options .mfa label span {
text-align: center; text-align: center;
} }
.lgn-mfa-options .mfa input[type=radio] + label .mfa-img { .lgn-mfa-options .mfa label .mfa-img {
border: 1px solid var(--zitadel-color-input-border); border-width: 1px;
border-style: solid;
border-radius: 0.5rem; border-radius: 0.5rem;
padding: 1rem; padding: 1rem;
display: flex; display: flex;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.lgn-mfa-options .mfa input[type=radio] + label .mfa-img:hover {
border: 1px solid var(--zitadel-color-input-border-active);
}
.lgn-mfa-options .mfa input[type=radio] {
display: none;
}
.lgn-mfa-options .mfa input[type=radio]:checked + label .mfa-img {
border: 1px solid var(--zitadel-color-primary);
}
footer { footer {
width: 100%; width: 100%;
@ -1622,8 +1630,14 @@ a.sub-formfield-link {
.content-container .lgn-login-profile .lgn-names .lgn-displayname { .content-container .lgn-login-profile .lgn-names .lgn-displayname {
margin: 0.5rem 1rem; margin: 0.5rem 1rem;
} }
.content-container .lgn-login-profile .lgn-names .lgn-loginname {
min-width: 0;
}
.content-container .lgn-login-profile .lgn-names .lgn-loginname p { .content-container .lgn-login-profile .lgn-names .lgn-loginname p {
margin: 0.5rem 1rem; margin: 0.5rem 0.5rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
} }
.content-container .lgn-left-action { .content-container .lgn-left-action {
position: absolute; position: absolute;
@ -2115,31 +2129,31 @@ i {
flex: 1; flex: 1;
padding: 0 0.5rem; padding: 0 0.5rem;
} }
.lgn-mfa-options .mfa input[type=radio] + label { .lgn-mfa-options .mfa label {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: relative;
} }
.lgn-mfa-options .mfa input[type=radio] + label span { .lgn-mfa-options .mfa label input[type=radio] {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.lgn-mfa-options .mfa label span {
text-align: center; text-align: center;
} }
.lgn-mfa-options .mfa input[type=radio] + label .mfa-img { .lgn-mfa-options .mfa label .mfa-img {
border: 1px solid var(--zitadel-color-input-border); border-width: 1px;
border-style: solid;
border-radius: 0.5rem; border-radius: 0.5rem;
padding: 1rem; padding: 1rem;
display: flex; display: flex;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.lgn-mfa-options .mfa input[type=radio] + label .mfa-img:hover {
border: 1px solid var(--zitadel-color-input-border-active);
}
.lgn-mfa-options .mfa input[type=radio] {
display: none;
}
.lgn-mfa-options .mfa input[type=radio]:checked + label .mfa-img {
border: 1px solid var(--zitadel-color-primary);
}
@font-face { @font-face {
font-family: Aileron; font-family: Aileron;
@ -2480,8 +2494,14 @@ i {
.content-container .lgn-login-profile .lgn-names .lgn-displayname { .content-container .lgn-login-profile .lgn-names .lgn-displayname {
margin: 0.5rem 1rem; margin: 0.5rem 1rem;
} }
.content-container .lgn-login-profile .lgn-names .lgn-loginname {
min-width: 0;
}
.content-container .lgn-login-profile .lgn-names .lgn-loginname p { .content-container .lgn-login-profile .lgn-names .lgn-loginname p {
margin: 0.5rem 1rem; margin: 0.5rem 0.5rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
} }
.content-container .lgn-left-action { .content-container .lgn-left-action {
position: absolute; position: absolute;
@ -3035,15 +3055,17 @@ ul li i.lgn-valid {
background-color: var(--zitadel-color-success-background); background-color: var(--zitadel-color-success-background);
} }
.lgn-mfa-options .mfa input[type=radio] + label .mfa-img { .lgn-mfa-options .mfa label input[type=radio]:hover + .mfa-img, .lgn-mfa-options .mfa label input[type=radio]:focus + .mfa-img {
background-color: var(--zitadel-color-card-hover);
border-color: var(--zitadel-color-input-border-hover);
}
.lgn-mfa-options .mfa label .mfa-img {
border: 1px solid var(--zitadel-color-input-border); border: 1px solid var(--zitadel-color-input-border);
background-color: var(--zitadel-color-input-background);
} }
.lgn-mfa-options .mfa input[type=radio] + label .mfa-img:hover { .lgn-mfa-options .mfa label input[type=radio]:checked + .mfa-img {
border: 1px solid var(--zitadel-color-input-border-hover); background-color: var(--zitadel-color-card-hover);
} border: 1px solid var(--zitadel-color-input-border-active);
.lgn-mfa-options .mfa input[type=radio]:checked + label .mfa-img { box-shadow: 0 0 0 2px var(--zitadel-color-input-border-active);
border: 1px solid var(--zitadel-color-primary);
} }
/*# sourceMappingURL=zitadel.css.map */ /*# sourceMappingURL=zitadel.css.map */

File diff suppressed because one or more lines are too long

View File

@ -47,7 +47,7 @@
<div class="lgn-field double"> <div class="lgn-field double">
<label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label> <label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required> <input class="lgn-input" type="email" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div> </div>
<div class="lgn-field double"> <div class="lgn-field double">

View File

@ -47,7 +47,7 @@
<div class="lgn-field double"> <div class="lgn-field double">
<label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label> <label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required> <input class="lgn-input" type="email" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div> </div>
<div class="lgn-field double"> <div class="lgn-field double">

View File

@ -16,6 +16,7 @@
{{ range $provider := .MFAProviders}} {{ $providerName := (t (printf {{ range $provider := .MFAProviders}} {{ $providerName := (t (printf
"InitMFAPrompt.Provider%v" $provider)) }} "InitMFAPrompt.Provider%v" $provider)) }}
<div class="mfa"> <div class="mfa">
<label>
<input <input
id="{{ $provider }}" id="{{ $provider }}"
type="radio" type="radio"
@ -23,9 +24,7 @@
value="{{ $provider }}" value="{{ $provider }}"
required required
/> />
{{ if eq $provider 0 }}
<label for="{{ $provider }}"
>{{ if eq $provider 0 }}
<div class="mfa-img"> <div class="mfa-img">
<img width="100px" height="100px" alt="OTP" src="{{ resourceUrl <img width="100px" height="100px" alt="OTP" src="{{ resourceUrl
"images/mfa/mfa-otp.svg" }}" /> "images/mfa/mfa-otp.svg" }}" />
@ -66,4 +65,6 @@
</div> </div>
</form> </form>
<script src="{{ resourceUrl "scripts/mfa.js" }}"></script>
{{template "main-bottom" .}} {{template "main-bottom" .}}

View File

@ -34,7 +34,7 @@
<div class="lgn-field double"> <div class="lgn-field double">
<label class="lgn-label" for="email">{{t "RegistrationUser.EmailLabel"}}</label> <label class="lgn-label" for="email">{{t "RegistrationUser.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required> <input class="lgn-input" type="email" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div> </div>
{{if .ShowUsername}} {{if .ShowUsername}}

View File

@ -46,7 +46,7 @@
{{end}} {{end}}
<div class="lgn-field"> <div class="lgn-field">
<label class="lgn-label" for="email">{{t "RegistrationOrg.EmailLabel"}}</label> <label class="lgn-label" for="email">{{t "RegistrationOrg.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" <input class="lgn-input" type="email" id="email" name="email" autocomplete="email" value="{{ .Email }}"
autofocus required> autofocus required>
</div> </div>
<div class="double-col"> <div class="double-col">