mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Require user to agree to 'terms and conditions' during registration
This commit is contained in:
parent
8080085cc1
commit
eb9bb281ec
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@ -14,6 +14,7 @@ include::users/proc-configuring-user-attributes.adoc[leveloffset=+2]
|
||||
include::users/con-user-registration.adoc[leveloffset=+2]
|
||||
include::users/proc-enabling-user-registration.adoc[leveloffset=3]
|
||||
include::users/proc-registering-new-user.adoc[leveloffset=3]
|
||||
include::users/proc-requiring-tac-agreement-at-registration.adoc[leveloffset=3]
|
||||
|
||||
include::users/con-required-actions.adoc[leveloffset=+2]
|
||||
include::users/proc-setting-required-actions.adoc[leveloffset=+3]
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// con-user-registration.adoc
|
||||
|
||||
[id="proc-requiring-tac-agreement-at-registration_{context}"]
|
||||
= Requiring user to agree to terms and conditions during registration
|
||||
|
||||
[role="_abstract"]
|
||||
For a user to register, you can require agreement to your terms and conditions.
|
||||
|
||||
.Registration form with required terms and conditions agreement
|
||||
image:images/registration-form-with-required-tac.png[]
|
||||
|
||||
.Prerequisite
|
||||
* User registration is enabled.
|
||||
* Terms and conditions required action is enabled.
|
||||
|
||||
.Procedure
|
||||
. Click the *Flows* tab.
|
||||
. Click the *registration* flow.
|
||||
. Select *Required* on the *Terms and Conditions* row.
|
||||
+
|
||||
.Make the terms and conditions agreement required at registration
|
||||
image:images/require-tac-agreement-at-registration.png[]
|
||||
@ -51,7 +51,7 @@ public class DefaultAuthenticationFlows {
|
||||
public static void addFlows(RealmModel realm) {
|
||||
if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm);
|
||||
if (realm.getFlowByAlias(DIRECT_GRANT_FLOW) == null) directGrantFlow(realm, false);
|
||||
if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm);
|
||||
if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm, false);
|
||||
if (realm.getFlowByAlias(RESET_CREDENTIALS_FLOW) == null) resetCredentialsFlow(realm);
|
||||
if (realm.getFlowByAlias(CLIENT_AUTHENTICATION_FLOW) == null) clientAuthFlow(realm);
|
||||
if (realm.getFlowByAlias(FIRST_BROKER_LOGIN_FLOW) == null) firstBrokerLoginFlow(realm, false);
|
||||
@ -61,7 +61,7 @@ public class DefaultAuthenticationFlows {
|
||||
public static void migrateFlows(RealmModel realm) {
|
||||
if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm, true);
|
||||
if (realm.getFlowByAlias(DIRECT_GRANT_FLOW) == null) directGrantFlow(realm, true);
|
||||
if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm);
|
||||
if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm, true);
|
||||
if (realm.getFlowByAlias(RESET_CREDENTIALS_FLOW) == null) resetCredentialsFlow(realm);
|
||||
if (realm.getFlowByAlias(CLIENT_AUTHENTICATION_FLOW) == null) clientAuthFlow(realm);
|
||||
if (realm.getFlowByAlias(FIRST_BROKER_LOGIN_FLOW) == null) firstBrokerLoginFlow(realm, true);
|
||||
@ -69,7 +69,7 @@ public class DefaultAuthenticationFlows {
|
||||
if (realm.getFlowByAlias(DOCKER_AUTH) == null) dockerAuthenticationFlow(realm);
|
||||
}
|
||||
|
||||
public static void registrationFlow(RealmModel realm) {
|
||||
public static void registrationFlow(RealmModel realm, boolean migrate) {
|
||||
AuthenticationFlowModel registrationFlow = new AuthenticationFlowModel();
|
||||
registrationFlow.setAlias(REGISTRATION_FLOW);
|
||||
registrationFlow.setDescription("registration flow");
|
||||
@ -137,6 +137,16 @@ public class DefaultAuthenticationFlows {
|
||||
execution.setAuthenticatorFlow(false);
|
||||
//execution.setAuthenticatorConfig(captchaConfig.getId());
|
||||
realm.addAuthenticatorExecution(execution);
|
||||
|
||||
if (!migrate) {
|
||||
execution = new AuthenticationExecutionModel();
|
||||
execution.setParentFlow(registrationFormFlow.getId());
|
||||
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
|
||||
execution.setAuthenticator("registration-terms-and-conditions");
|
||||
execution.setPriority(70);
|
||||
execution.setAuthenticatorFlow(false);
|
||||
realm.addAuthenticatorExecution(execution);
|
||||
}
|
||||
}
|
||||
|
||||
public static void browserFlow(RealmModel realm) {
|
||||
|
||||
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.authentication.forms;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.FormAction;
|
||||
import org.keycloak.authentication.FormActionFactory;
|
||||
import org.keycloak.authentication.FormContext;
|
||||
import org.keycloak.authentication.ValidationContext;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.forms.login.LoginFormsProvider;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.FormMessage;
|
||||
import org.keycloak.provider.ConfiguredProvider;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class RegistrationTermsAndConditions implements FormAction, FormActionFactory, ConfiguredProvider {
|
||||
|
||||
public static final String PROVIDER_ID = "registration-terms-and-conditions";
|
||||
|
||||
protected static final String FIELD = "termsAccepted";
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Terms and conditions";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferenceCategory() {
|
||||
return "terms-and-conditions";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
|
||||
AuthenticationExecutionModel.Requirement.REQUIRED,
|
||||
AuthenticationExecutionModel.Requirement.DISABLED
|
||||
};
|
||||
@Override
|
||||
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
|
||||
return REQUIREMENT_CHOICES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserSetupAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildPage(FormContext context, LoginFormsProvider form) {
|
||||
form.setAttribute("termsAcceptanceRequired", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(ValidationContext context) {
|
||||
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
|
||||
if (formData.containsKey(FIELD)) {
|
||||
context.success();
|
||||
return;
|
||||
}
|
||||
|
||||
context.error(Errors.INVALID_REGISTRATION);
|
||||
context.validationError(formData, Collections.singletonList(new FormMessage(FIELD, "termsAcceptanceRequired")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(FormContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUser() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Asks the user to accept terms and conditions before submitting its registration form.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormAction create(KeycloakSession session) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
}
|
||||
@ -18,4 +18,5 @@
|
||||
org.keycloak.authentication.forms.RegistrationPassword
|
||||
org.keycloak.authentication.forms.RegistrationProfile
|
||||
org.keycloak.authentication.forms.RegistrationUserCreation
|
||||
org.keycloak.authentication.forms.RegistrationRecaptcha
|
||||
org.keycloak.authentication.forms.RegistrationRecaptcha
|
||||
org.keycloak.authentication.forms.RegistrationTermsAndConditions
|
||||
|
||||
@ -162,6 +162,9 @@ public class AccountFields extends FieldsBase {
|
||||
@FindBy(id = "input-error-username")
|
||||
private WebElement usernameError;
|
||||
|
||||
@FindBy(id = "input-error-terms-accepted")
|
||||
private WebElement termsError;
|
||||
|
||||
public String getFirstNameError() {
|
||||
try {
|
||||
return getTextFromElement(firstNameError);
|
||||
@ -201,5 +204,13 @@ public class AccountFields extends FieldsBase {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getTermsError(){
|
||||
try {
|
||||
return getTextFromElement(termsError);
|
||||
} catch (NoSuchElementException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,10 +56,13 @@ public class RegisterPage extends AbstractPage {
|
||||
|
||||
@FindBy(id = "password-confirm")
|
||||
private WebElement passwordConfirmInput;
|
||||
|
||||
|
||||
@FindBy(id = "department")
|
||||
private WebElement departmentInput;
|
||||
|
||||
@FindBy(id = "termsAccepted")
|
||||
private WebElement termsAcceptedInput;
|
||||
|
||||
@FindBy(css = "input[type=\"submit\"]")
|
||||
private WebElement submitButton;
|
||||
|
||||
@ -77,6 +80,10 @@ public class RegisterPage extends AbstractPage {
|
||||
}
|
||||
|
||||
public void register(String firstName, String lastName, String email, String username, String password, String passwordConfirm, String department) {
|
||||
register(firstName, lastName, email, username, password, passwordConfirm, department, null);
|
||||
}
|
||||
|
||||
public void register(String firstName, String lastName, String email, String username, String password, String passwordConfirm, String department, Boolean termsAccepted) {
|
||||
firstNameInput.clear();
|
||||
if (firstName != null) {
|
||||
firstNameInput.sendKeys(firstName);
|
||||
@ -114,6 +121,15 @@ public class RegisterPage extends AbstractPage {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
termsAcceptedInput.clear();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ignore
|
||||
}
|
||||
if (termsAccepted != null && termsAccepted) {
|
||||
termsAcceptedInput.click();
|
||||
}
|
||||
|
||||
submitButton.click();
|
||||
}
|
||||
|
||||
@ -173,7 +189,7 @@ public class RegisterPage extends AbstractPage {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String getLabelForField(String fieldId) {
|
||||
return driver.findElement(By.cssSelector("label[for="+fieldId+"]")).getText();
|
||||
}
|
||||
@ -218,7 +234,7 @@ public class RegisterPage extends AbstractPage {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isCurrent() {
|
||||
return PageUtils.getPageTitle(driver).equals("Register");
|
||||
}
|
||||
|
||||
@ -70,6 +70,8 @@ public class ProvidersTest extends AbstractAuthenticationTest {
|
||||
addProviderInfo(expected, "registration-user-creation", "Registration User Creation",
|
||||
"This action must always be first! Validates the username of the user in validation phase. " +
|
||||
"In success phase, this will create the user in the database.");
|
||||
addProviderInfo(expected, "registration-terms-and-conditions", "Terms and conditions",
|
||||
"Asks the user to accept terms and conditions before submitting its registration form.");
|
||||
|
||||
compareProviders(expected, result);
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import org.keycloak.authentication.authenticators.browser.CookieAuthenticatorFac
|
||||
import org.keycloak.authentication.forms.RegistrationPassword;
|
||||
import org.keycloak.authentication.forms.RegistrationProfile;
|
||||
import org.keycloak.authentication.forms.RegistrationRecaptcha;
|
||||
import org.keycloak.authentication.forms.RegistrationTermsAndConditions;
|
||||
import org.keycloak.authentication.forms.RegistrationUserCreation;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventType;
|
||||
@ -34,6 +35,7 @@ import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.representations.idm.EventRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
@ -52,6 +54,7 @@ import org.keycloak.testsuite.util.AccountHelper;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
@ -353,7 +356,7 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
|
||||
|
||||
//contains few special characters we want to be sure they are allowed in username
|
||||
String username = "register.U-se@rS_uccess";
|
||||
|
||||
|
||||
registerPage.register("firstName", "lastName", "registerUserSuccess@email", username, "password", "password");
|
||||
|
||||
appPage.assertCurrent();
|
||||
@ -644,6 +647,56 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
|
||||
registerPage.assertCurrent();
|
||||
}
|
||||
|
||||
//KEYCLOAK-15244
|
||||
@Test
|
||||
public void registerUserMissingTermsAcceptance() {
|
||||
configureRegistrationFlowWithCustomRegistrationPageForm(UUID.randomUUID().toString(),
|
||||
AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||
|
||||
try {
|
||||
loginPage.open();
|
||||
loginPage.clickRegister();
|
||||
registerPage.assertCurrent();
|
||||
|
||||
registerPage.register("firstName", "lastName", "registerUserMissingTermsAcceptance@email",
|
||||
"registerUserMissingTermsAcceptance", "password", "password", null, false);
|
||||
|
||||
registerPage.assertCurrent();
|
||||
assertEquals("You must agree to our terms and conditions.", registerPage.getInputAccountErrors().getTermsError());
|
||||
|
||||
events.expectRegister("registerUserMissingTermsAcceptance", "registerUserMissingTermsAcceptance@email")
|
||||
.removeDetail(Details.USERNAME)
|
||||
.removeDetail(Details.EMAIL)
|
||||
.error("invalid_registration").assertEvent();
|
||||
} finally {
|
||||
configureRegistrationFlowWithCustomRegistrationPageForm(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
//KEYCLOAK-15244
|
||||
@Test
|
||||
public void registerUserSuccessTermsAcceptance() {
|
||||
configureRegistrationFlowWithCustomRegistrationPageForm(UUID.randomUUID().toString(),
|
||||
AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||
|
||||
try {
|
||||
loginPage.open();
|
||||
loginPage.clickRegister();
|
||||
registerPage.assertCurrent();
|
||||
|
||||
registerPage.register("firstName", "lastName", "registerUserSuccessTermsAcceptance@email",
|
||||
"registerUserSuccessTermsAcceptance", "password", "password", null, true);
|
||||
|
||||
assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
|
||||
String userId = events.expectRegister("registerUserSuccessTermsAcceptance", "registerUserSuccessTermsAcceptance@email")
|
||||
.assertEvent().getUserId();
|
||||
assertUserRegistered(userId, "registerUserSuccessTermsAcceptance", "registerUserSuccessTermsAcceptance@email");
|
||||
} finally {
|
||||
configureRegistrationFlowWithCustomRegistrationPageForm(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected RealmAttributeUpdater configureRealmRegistrationEmailAsUsername(final boolean value) {
|
||||
return getRealmAttributeUpdater().setRegistrationEmailAsUsername(value);
|
||||
}
|
||||
@ -709,19 +762,24 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
|
||||
}
|
||||
|
||||
private void configureRegistrationFlowWithCustomRegistrationPageForm(String newFlowAlias) {
|
||||
configureRegistrationFlowWithCustomRegistrationPageForm(newFlowAlias, AuthenticationExecutionModel.Requirement.DISABLED);
|
||||
}
|
||||
|
||||
private void configureRegistrationFlowWithCustomRegistrationPageForm(String newFlowAlias, AuthenticationExecutionModel.Requirement termsAndConditionRequirement) {
|
||||
testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyRegistrationFlow(newFlowAlias));
|
||||
testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session)
|
||||
.selectFlow(newFlowAlias)
|
||||
.clear()
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.ALTERNATIVE, CookieAuthenticatorFactory.PROVIDER_ID)
|
||||
.addSubFlowExecution("Sub Flow", AuthenticationFlow.BASIC_FLOW, AuthenticationExecutionModel.Requirement.ALTERNATIVE, subflow -> subflow
|
||||
.addSubFlowExecution("Sub sub Form Flow", AuthenticationFlow.FORM_FLOW, AuthenticationExecutionModel.Requirement.REQUIRED, subsubflow -> subsubflow
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, RegistrationUserCreation.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, RegistrationProfile.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, RegistrationPassword.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.DISABLED, RegistrationRecaptcha.PROVIDER_ID)
|
||||
)
|
||||
.clear()
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.ALTERNATIVE, CookieAuthenticatorFactory.PROVIDER_ID)
|
||||
.addSubFlowExecution("Sub Flow", AuthenticationFlow.BASIC_FLOW, AuthenticationExecutionModel.Requirement.ALTERNATIVE, subflow -> subflow
|
||||
.addSubFlowExecution("Sub sub Form Flow", AuthenticationFlow.FORM_FLOW, AuthenticationExecutionModel.Requirement.REQUIRED, subsubflow -> subsubflow
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, RegistrationUserCreation.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, RegistrationProfile.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, RegistrationPassword.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.DISABLED, RegistrationRecaptcha.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(termsAndConditionRequirement, RegistrationTermsAndConditions.PROVIDER_ID)
|
||||
)
|
||||
)
|
||||
.defineAsRegistrationFlow() // Activate this new flow
|
||||
);
|
||||
}
|
||||
|
||||
@ -63,6 +63,8 @@ termsTitle=Termes et Conditions
|
||||
termsTitleHtml=Termes et Conditions
|
||||
termsText=<p>Termes et conditions \u00e0 d\u00e9finir</p>
|
||||
termsPlainText=Termes et conditions \u00e0 d\u00e9finir
|
||||
termsAcceptanceRequired=Vous devez accepter les termes et conditions.
|
||||
acceptTerms=J''accepte les termes et conditions
|
||||
|
||||
recaptchaFailed=Re-captcha invalide
|
||||
recaptchaNotConfigured=Re-captcha est requis, mais il n''est pas configur\u00e9
|
||||
|
||||
@ -68,6 +68,8 @@ unknown=Unknown
|
||||
termsTitle=Terms and Conditions
|
||||
termsText=<p>Terms and conditions to be defined</p>
|
||||
termsPlainText=Terms and conditions to be defined.
|
||||
termsAcceptanceRequired=You must agree to our terms and conditions.
|
||||
acceptTerms=I agree to the terms and conditions
|
||||
|
||||
recaptchaFailed=Invalid Recaptcha
|
||||
recaptchaNotConfigured=Recaptcha is required, but not configured
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
<#macro termsAcceptance>
|
||||
<#if termsAcceptanceRequired??>
|
||||
<div class="form-group">
|
||||
<div class="${properties.kcInputWrapperClass!}">
|
||||
${msg("termsTitle")}
|
||||
<div id="kc-registration-terms-text">
|
||||
${kcSanitize(msg("termsText"))?no_esc}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="${properties.kcLabelWrapperClass!}">
|
||||
<input type="checkbox" id="termsAccepted" name="termsAccepted" class="${properties.kcCheckboxInputClass!}"
|
||||
aria-invalid="<#if messagesPerField.existsError('termsAccepted')>true</#if>"
|
||||
/>
|
||||
<label for="termsAccepted" class="${properties.kcLabelClass!}">${msg("acceptTerms")}</label>
|
||||
</div>
|
||||
<#if messagesPerField.existsError('termsAccepted')>
|
||||
<div class="${properties.kcLabelWrapperClass!}">
|
||||
<span id="input-error-terms-accepted" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||
${kcSanitize(messagesPerField.get('termsAccepted'))?no_esc}
|
||||
</span>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</#if>
|
||||
</#macro>
|
||||
@ -1,5 +1,6 @@
|
||||
<#import "template.ftl" as layout>
|
||||
<#import "user-profile-commons.ftl" as userProfileCommons>
|
||||
<#import "register-commons.ftl" as registerCommons>
|
||||
<@layout.registrationLayout displayMessage=messagesPerField.exists('global') displayRequiredFields=true; section>
|
||||
<#if section = "header">
|
||||
${msg("registerTitle")}
|
||||
@ -49,6 +50,8 @@
|
||||
</#if>
|
||||
</#if>
|
||||
</@userProfileCommons.userProfileFormFields>
|
||||
|
||||
<@registerCommons.termsAcceptance/>
|
||||
|
||||
<#if recaptchaRequired??>
|
||||
<div class="form-group">
|
||||
@ -71,4 +74,4 @@
|
||||
</div>
|
||||
</form>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
</@layout.registrationLayout>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<#import "template.ftl" as layout>
|
||||
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('firstName','lastName','email','username','password','password-confirm'); section>
|
||||
<#import "register-commons.ftl" as registerCommons>
|
||||
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('firstName','lastName','email','username','password','password-confirm','termsAccepted'); section>
|
||||
<#if section = "header">
|
||||
${msg("registerTitle")}
|
||||
<#elseif section = "form">
|
||||
@ -117,6 +118,8 @@
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
<@registerCommons.termsAcceptance/>
|
||||
|
||||
<#if recaptchaRequired??>
|
||||
<div class="form-group">
|
||||
<div class="${properties.kcInputWrapperClass!}">
|
||||
@ -138,4 +141,4 @@
|
||||
</div>
|
||||
</form>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
</@layout.registrationLayout>
|
||||
|
||||
@ -178,6 +178,13 @@ div.kc-logo-text span {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#kc-registration-terms-text {
|
||||
max-height: 100px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
#kc-registration {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user