keycloak-uncached
Changes
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java 3(+3 -0)
Details
diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
index b3b6baf..5c0a60c 100755
--- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
+++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
@@ -112,10 +112,12 @@ public class ImportUtils {
RoleModel createRealmRole = realm.addRole(AdminRoles.CREATE_REALM);
adminRole.addCompositeRole(createRealmRole);
+ createRealmRole.setDescription("${role_"+AdminRoles.CREATE_REALM+"}");
} else {
adminRealm = model.getRealmByName(Config.getAdminRealm());
adminRole = adminRealm.getRole(AdminRoles.ADMIN);
}
+ adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}");
ApplicationModel realmAdminApp = KeycloakModelUtils.createApplication(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationName(realm));
realmAdminApp.setBearerOnly(true);
@@ -123,6 +125,7 @@ public class ImportUtils {
for (String r : AdminRoles.ALL_REALM_ROLES) {
RoleModel role = realmAdminApp.addRole(r);
+ role.setDescription("${role_"+r+"}");
adminRole.addCompositeRole(role);
}
}
diff --git a/forms/common-themes/src/main/resources/theme/base/account/template.ftl b/forms/common-themes/src/main/resources/theme/base/account/template.ftl
index 22bade4..d461118 100644
--- a/forms/common-themes/src/main/resources/theme/base/account/template.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/account/template.ftl
@@ -30,8 +30,8 @@
<ul class="nav navbar-nav navbar-utility">
<#if realm.internationalizationEnabled>
<li>
- <div class="kc-dropdown">
- <a href="#">${locale.current}</a>
+ <div class="kc-dropdown" id="kc-locale-dropdown">
+ <a href="#" id="kc-current-locale-link">${locale.current}</a>
<ul>
<#list locale.supported as l>
<li class="kc-dropdown-item"><a href="${l.url}">${l.label}</a></li>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
index 1b570c7..06abbb1 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
@@ -29,8 +29,10 @@ noAccount=Neuer Benutzer?
username=Benutzername
usernameOrEmail=Benutzername oder E-Mail
firstName=Vorname
-fullName=Name
+givenName=Vorname
+fullName=voller Name
lastName=Nachname
+familyName=Nachname
email=E-Mail
password=Passwort
passwordConfirm=Passwort best\u00E4tigen
@@ -38,11 +40,14 @@ passwordNew=Neues Passwort
passwordNewConfirm=Neues Passwort best\u00E4tigen
rememberMe=Angemeldet bleiben
authenticatorCode=One-time Code
+address=Adresse
street=Strasse
region=Staat, Provinz, Region
postal_code=PLZ
locality=Stadt oder Ortschaft
country=Land
+emailVerified=E-Mail verifiziert
+gssDelegationCredential=GSS delegierte Berechtigung
loginTotpStep1=Installieren Sie <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> oder <a href="http://code.google.com/p/google-authenticator/" target="_blank">Google Authenticator</a> auf Ihrem Smartphone.
loginTotpStep2=\u00D6ffnen Sie die Applikation und scannen Sie den Barcode oder geben sie den Code ein.
@@ -65,6 +70,24 @@ copyCodeInstruction=Bitte kopieren sie den folgenden Code und f\u00FCgen ihn in
personalInfo=Pers\u00F6nliche Informationen:
+role_admin=Admin
+role_realm-admin=Realm Admin
+role_create-realm=Realm erstellen
+role_view-realm=Realm ansehen
+role_view-users=Benutzer ansehen
+role_view-applications=Applicationen ansehen
+role_view-clients=Clients ansehen
+role_view-events=Events ansehen
+role_view-identity-providers=Identity Providers ansehen
+role_manage-realm=Realm verwalten
+role_manage-users=Benutzer verwalten
+role_manage-applications=Applikationen verwalten
+role_manage-identity-providers=Identity Provider verwalten
+role_manage-clients=Clients verwalten
+role_manage-events=Events verwalten
+role_view-profile=Profile ansehen
+role_manage-account=Profile verwalten
+
invalidUserMessage=Ung\u00FCltiger Benutzername oder Passwort.
invalidEmailMessage=Ung\u00FCltige E-Mail Adresse.
accountDisabledMessage=Benutzerkonto ist gesperrt, bitte kontaktieren Sie den Admin.
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
index 84f32c7..4bb3a66 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -29,8 +29,10 @@ noAccount=New user?
username=Username
usernameOrEmail=Username or email
firstName=First name
+givenName=Given name
fullName=Full name
lastName=Last name
+familyName=Family name
email=Email
password=Password
passwordConfirm=Confirm password
@@ -38,11 +40,14 @@ passwordNew=New Password
passwordNewConfirm=New Password confirmation
rememberMe=Remember me
authenticatorCode=One-time code
+address=Address
street=Street
locality=City or Locality
region=State, Province, or Region
postal_code=Zip or Postal code
country=Country
+emailVerified=Email verified
+gssDelegationCredential=gss delegation credential
loginTotpStep1=Install <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> or <a href="http://code.google.com/p/google-authenticator/" target="_blank">Google Authenticator</a> on your mobile
loginTotpStep2=Open the application and scan the barcode or enter the key
@@ -64,6 +69,24 @@ copyCodeInstruction=Please copy this code and paste it into your application:
personalInfo=Personal Info:
+role_admin=Admin
+role_realm-admin=Realm Admin
+role_create-realm=Crate realm
+role_view-realm=View realm
+role_view-users=View users
+role_view-applications=View applications
+role_view-clients=View clients
+role_view-events=View events
+role_view-identity-providers=View identity providers
+role_manage-realm=Manage realm
+role_manage-users=Manage users
+role_manage-applications=Manage applications
+role_manage-identity-providers=Manage identity providers
+role_manage-clients=Manage clients
+role_manage-events=Manage events
+role_view-profile=View profile
+role_manage-account=Manage account
+
invalidUserMessage=Invalid username or password.
invalidEmailMessage=Invalid email address.
accountDisabledMessage=Account is disabled, contact admin.
diff --git a/forms/common-themes/src/main/resources/theme/base/login/template.ftl b/forms/common-themes/src/main/resources/theme/base/login/template.ftl
index 9864214..34b2d4a 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/template.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/template.ftl
@@ -48,8 +48,8 @@
<#if realm.internationalizationEnabled>
<div id="kc-locale" class="${properties.kcLocaleClass!}">
<div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
- <div class="kc-dropdown">
- <a href="#">${locale.current}</a>
+ <div class="kc-dropdown" id="kc-locale-dropdown">
+ <a href="#" id="kc-current-locale-link">${locale.current}</a>
<ul>
<#list locale.supported as l>
<li class="kc-dropdown-item"><a href="${l.url}">${l.label}</a></li>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
index 83afe93..2387e1c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java
@@ -66,21 +66,21 @@ public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
X500SAMLProfileConstants.EMAIL.get(),
JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
X500SAMLProfileConstants.EMAIL.getFriendlyName(),
- true, "email");
+ true, "${email}");
builtins.add(model);
model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 givenName",
"firstName",
X500SAMLProfileConstants.GIVEN_NAME.get(),
JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
X500SAMLProfileConstants.GIVEN_NAME.getFriendlyName(),
- true, "given name");
+ true, "${givenName}");
builtins.add(model);
model = UserPropertyAttributeStatementMapper.createAttributeMapper("X500 surname",
"lastName",
X500SAMLProfileConstants.SURNAME.get(),
JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(),
X500SAMLProfileConstants.SURNAME.getFriendlyName(),
- true, "family name");
+ true, "${familyName}");
builtins.add(model);
model = RoleListMapper.create("role list", "Role", AttributeStatementHelper.BASIC, null, false);
builtins.add(model);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
index d91f7ea..fa95be1 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
@@ -52,7 +52,7 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
address.setProtocolMapper(PROVIDER_ID);
address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
address.setConsentRequired(true);
- address.setConsentText("address");
+ address.setConsentText("${address}");
config = new HashMap<String, String>();
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
@@ -66,7 +66,7 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
address.setProtocolMapper(PROVIDER_ID);
address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
address.setConsentRequired(true);
- address.setConsentText("address");
+ address.setConsentText("${address}");
config = new HashMap<String, String>();
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, Boolean.toString(idToken));
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken));
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
index c039929..0c81a3b 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
@@ -32,6 +32,13 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
public static final String GIVEN_NAME = "given name";
public static final String FAMILY_NAME = "family name";
public static final String FULL_NAME = "full name";
+ public static final String USERNAME_CONSENT_TEXT = "${username}";
+ public static final String EMAIL_CONSENT_TEXT = "${email}";
+ public static final String EMAIL_VERIFIED_CONSENT_TEXT = "${emailVerified}";
+ public static final String GIVEN_NAME_CONSENT_TEXT = "${givenName}";
+ public static final String FAMILY_NAME_CONSENT_TEXT = "${familyName}";
+ public static final String FULL_NAME_CONSENT_TEXT = "${fullName}";
+
@Override
public LoginProtocol create(KeycloakSession session) {
@@ -57,35 +64,35 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
model = UserPropertyMapper.createClaimMapper(USERNAME,
"username",
"preferred_username", "String",
- true, USERNAME,
+ true, USERNAME_CONSENT_TEXT,
true, true);
builtins.add(model);
defaultBuiltins.add(model);
model = UserPropertyMapper.createClaimMapper(EMAIL,
"email",
"email", "String",
- true, EMAIL,
+ true, EMAIL_CONSENT_TEXT,
true, true);
builtins.add(model);
defaultBuiltins.add(model);
model = UserPropertyMapper.createClaimMapper(GIVEN_NAME,
"firstName",
"given_name", "String",
- true, GIVEN_NAME,
+ true, GIVEN_NAME_CONSENT_TEXT,
true, true);
builtins.add(model);
defaultBuiltins.add(model);
model = UserPropertyMapper.createClaimMapper(FAMILY_NAME,
"lastName",
"family_name", "String",
- true, FAMILY_NAME,
+ true, FAMILY_NAME_CONSENT_TEXT,
true, true);
builtins.add(model);
defaultBuiltins.add(model);
model = UserPropertyMapper.createClaimMapper(EMAIL_VERIFIED,
"emailVerified",
"email_verified", "boolean",
- false, null,
+ false, EMAIL_VERIFIED_CONSENT_TEXT,
true, true);
builtins.add(model);
@@ -94,7 +101,7 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
fullName.setProtocolMapper(FullNameMapper.PROVIDER_ID);
fullName.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
fullName.setConsentRequired(true);
- fullName.setConsentText(FULL_NAME);
+ fullName.setConsentText(FULL_NAME_CONSENT_TEXT);
Map<String, String> config = new HashMap<String, String>();
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
@@ -108,7 +115,7 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
model = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
KerberosConstants.GSS_DELEGATION_CREDENTIAL,
KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String",
- true, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
+ true, "${gssDelegationCredential}",
true, false);
builtins.add(model);
}
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 240d5cb..4da8e12 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -179,11 +179,13 @@ public class RealmManager {
realmAdminApp = applicationManager.createApplication(realm, realmAdminApplicationName);
}
RoleModel adminRole = realmAdminApp.addRole(AdminRoles.REALM_ADMIN);
+ adminRole.setDescription("${role_"+AdminRoles.REALM_ADMIN+"}");
realmAdminApp.setBearerOnly(true);
realmAdminApp.setFullScopeAllowed(false);
for (String r : AdminRoles.ALL_REALM_ROLES) {
RoleModel role = realmAdminApp.addRole(r);
+ role.setDescription("${role_"+r+"}");
adminRole.addCompositeRole(role);
}
}
@@ -202,6 +204,7 @@ public class RealmManager {
for (String role : AccountRoles.ALL) {
application.addDefaultRole(role);
+ application.getRole(role).setDescription("${role_"+role+"}");
}
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index 18ca838..97e2095 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -111,7 +111,6 @@ public class ProfileTest {
assertEquals("Last", profile.getString("lastName"));
JSONObject attributes = profile.getJSONObject("attributes");
- assertEquals(2, attributes.length());
assertEquals("value1", attributes.getString("key1"));
assertEquals("value2", attributes.getString("key2"));
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/AccountPageTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/AccountPageTest.java
new file mode 100644
index 0000000..23b7398
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/AccountPageTest.java
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.i18n;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+
+/**
+ * @author <a href="mailto:gerbermichi@me.com">Michael Gerber</a>
+ */
+public class AccountPageTest {
+
+ @ClassRule
+ public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
+ @Override
+ public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+ UserModel user = manager.getSession().users().addUser(appRealm, "login-test");
+ user.setEmail("login@test.com");
+ user.setEnabled(true);
+
+ UserCredentialModel creds = new UserCredentialModel();
+ creds.setType(CredentialRepresentation.PASSWORD);
+ creds.setValue("password");
+
+ user.updateCredential(creds);
+ }
+ });
+
+ @Rule
+ public WebRule webRule = new WebRule(this);
+
+ @WebResource
+ protected AccountUpdateProfilePage accountUpdateProfilePage;
+
+ @WebResource
+ protected LoginPage loginPage;
+
+ @Test
+ public void languageDropdown() {
+ accountUpdateProfilePage.open();
+ loginPage.login("login@test.com", "password");
+ Assert.assertTrue(accountUpdateProfilePage.isCurrent());
+
+ Assert.assertEquals("English", accountUpdateProfilePage.getLanguageDropdownText());
+
+ accountUpdateProfilePage.openLanguage("German");
+ Assert.assertEquals("Deutsch", accountUpdateProfilePage.getLanguageDropdownText());
+
+ accountUpdateProfilePage.openLanguage("Englisch");
+ Assert.assertEquals("English", accountUpdateProfilePage.getLanguageDropdownText());
+ accountUpdateProfilePage.logout();
+ }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java
new file mode 100644
index 0000000..b8e2453
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.i18n;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.LoginPasswordResetPage;
+import org.keycloak.testsuite.rule.GreenMailRule;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author <a href="mailto:gerbermichi@me.com">Michael Gerber</a>
+ */
+public class EmailTest {
+ @ClassRule
+ public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
+ @Override
+ public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+ UserModel user = manager.getSession().users().addUser(appRealm, "login-test");
+ user.setEmail("login@test.com");
+ user.setEnabled(true);
+ user.setAttribute(UserModel.LOCALE, "de");
+
+ UserCredentialModel creds = new UserCredentialModel();
+ creds.setType(CredentialRepresentation.PASSWORD);
+ creds.setValue("password");
+
+ user.updateCredential(creds);
+ }
+ });
+
+ @Rule
+ public WebRule webRule = new WebRule(this);
+
+ @Rule
+ public GreenMailRule greenMail = new GreenMailRule();
+
+ @WebResource
+ protected LoginPage loginPage;
+
+ @WebResource
+ protected LoginPasswordResetPage resetPasswordPage;
+
+ @Test
+ public void restPasswordEmail() throws IOException, MessagingException {
+ loginPage.open();
+ loginPage.resetPassword();
+ resetPasswordPage.changePassword("login-test");
+
+ assertEquals(1, greenMail.getReceivedMessages().length);
+
+ MimeMessage message = greenMail.getReceivedMessages()[0];
+
+ Assert.assertEquals("Passwort zurückzusetzen", message.getSubject());
+
+ keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+ @Override
+ public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+ manager.getSession().users().getUserByUsername("login-test", appRealm).setAttribute(UserModel.LOCALE, "en");
+ }
+ });
+
+ resetPasswordPage.changePassword("login-test");
+
+ assertEquals(2, greenMail.getReceivedMessages().length);
+
+ message = greenMail.getReceivedMessages()[1];
+
+ Assert.assertEquals("Reset password", message.getSubject());
+ }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java
new file mode 100755
index 0000000..39bfd99
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.i18n;
+
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
+import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.adapters.HttpClientBuilder;
+import org.keycloak.freemarker.LocaleHelper;
+import org.keycloak.models.RealmModel;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:gerbermichi@me.com">Michael Gerber</a>
+ */
+public class LoginPageTest {
+
+ @ClassRule
+ public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
+ @Override
+ public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+
+ }
+ });
+
+ @Rule
+ public WebRule webRule = new WebRule(this);
+
+ @WebResource
+ protected OAuthClient oauth;
+
+ @WebResource
+ protected WebDriver driver;
+
+ @WebResource
+ protected LoginPage loginPage;
+
+ @Test
+ public void languageDropdown() {
+ loginPage.open();
+ Assert.assertEquals("English", loginPage.getLanguageDropdownText());
+
+ loginPage.openLanguage("German");
+ Assert.assertEquals("Deutsch", loginPage.getLanguageDropdownText());
+
+ loginPage.openLanguage("Englisch");
+ Assert.assertEquals("English", loginPage.getLanguageDropdownText());
+ }
+
+ @Test
+ public void uiLocalesParameter() {
+ loginPage.open();
+ Assert.assertEquals("English", loginPage.getLanguageDropdownText());
+
+ //test if cookie works
+ oauth.uiLocales("de");
+ loginPage.open();
+ Assert.assertEquals("English", loginPage.getLanguageDropdownText());
+
+ driver.manage().deleteAllCookies();
+ loginPage.open();
+ Assert.assertEquals("Deutsch", loginPage.getLanguageDropdownText());
+
+ oauth.uiLocales("en de");
+ driver.manage().deleteAllCookies();
+ loginPage.open();
+ Assert.assertEquals("English", loginPage.getLanguageDropdownText());
+
+ oauth.uiLocales("fr de");
+ driver.manage().deleteAllCookies();
+ loginPage.open();
+ Assert.assertEquals("Deutsch", loginPage.getLanguageDropdownText());
+ }
+
+ @Test
+ public void acceptLanguageHeader() {
+ DefaultHttpClient httpClient = (DefaultHttpClient) new HttpClientBuilder().build();
+ ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
+ ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
+
+ loginPage.open();
+ Response response = client.target(driver.getCurrentUrl()).request().acceptLanguage("de").get();
+ Assert.assertTrue(response.readEntity(String.class).contains("Anmeldung bei test"));
+ Assert.assertEquals("de", response.getCookies().get(LocaleHelper.LOCALE_COOKIE).getValue());
+
+ response = client.target(driver.getCurrentUrl()).request().acceptLanguage("en").get();
+ Assert.assertTrue(response.readEntity(String.class).contains("Log in to test"));
+ Assert.assertEquals("en", response.getCookies().get(LocaleHelper.LOCALE_COOKIE).getValue());
+ }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index 80d0310..3c81b8a 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -35,6 +35,7 @@ import org.junit.Assert;
import org.keycloak.OAuth2Constants;
import org.keycloak.RSATokenVerifier;
import org.keycloak.VerificationException;
+import org.keycloak.freemarker.LocaleHelper;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
@@ -73,6 +74,8 @@ public class OAuthClient {
private String state = "mystate";
+ private String uiLocales = null;
+
private PublicKey realmPublicKey;
public OAuthClient(WebDriver driver) {
@@ -296,6 +299,9 @@ public class OAuthClient {
if (state != null) {
b.queryParam(OAuth2Constants.STATE, state);
}
+ if(uiLocales != null){
+ b.queryParam(LocaleHelper.UI_LOCALES_PARAM, uiLocales);
+ }
return b.build(realm).toString();
}
@@ -349,6 +355,11 @@ public class OAuthClient {
return this;
}
+ public OAuthClient uiLocales(String uiLocales){
+ this.uiLocales = uiLocales;
+ return this;
+ }
+
public String getRealm() {
return realm;
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractAccountPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractAccountPage.java
index 3eee185..684eedf 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractAccountPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractAccountPage.java
@@ -21,6 +21,7 @@
*/
package org.keycloak.testsuite.pages;
+import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@@ -32,8 +33,21 @@ public abstract class AbstractAccountPage extends AbstractPage {
@FindBy(linkText = "Sign Out")
private WebElement logoutLink;
+ @FindBy(id = "kc-current-locale-link")
+ private WebElement languageText;
+
+ @FindBy(id = "kc-locale-dropdown")
+ private WebElement localeDropdown;
+
public void logout() {
logoutLink.click();
}
+ public String getLanguageDropdownText() {
+ return languageText.getText();
+ }
+
+ public void openLanguage(String language){
+ localeDropdown.findElement(By.linkText(language)).click();
+ }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
index 7d83b0c..1f0b7a2 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
@@ -68,6 +68,12 @@ public class LoginPage extends AbstractPage {
@FindBy(className = "feedback-warning")
private WebElement loginWarningMessage;
+ @FindBy(id = "kc-current-locale-link")
+ private WebElement languageText;
+
+ @FindBy(id = "kc-locale-dropdown")
+ private WebElement localeDropdown;
+
public void login(String username, String password) {
usernameInput.clear();
usernameInput.sendKeys(username);
@@ -103,7 +109,7 @@ public class LoginPage extends AbstractPage {
public boolean isCurrent() {
- return driver.getTitle().equals("Log in to test");
+ return driver.getTitle().equals("Log in to test") || driver.getTitle().equals("Anmeldung bei test");
}
public void clickRegister() {
@@ -145,4 +151,12 @@ public class LoginPage extends AbstractPage {
assertCurrent();
}
+ public String getLanguageDropdownText() {
+ return languageText.getText();
+ }
+
+ public void openLanguage(String language){
+ localeDropdown.findElement(By.linkText(language)).click();
+ }
+
}
diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json
index 17c54dc..cedc22d 100755
--- a/testsuite/integration/src/test/resources/testrealm.json
+++ b/testsuite/integration/src/test/resources/testrealm.json
@@ -112,5 +112,9 @@
"roles": ["customer-user"]
}
]
- }
+ },
+
+ "internationalizationEnabled": true,
+ "supportedLocales": ["en", "de"],
+ "defaultLocale": "en"
}