Merge pull request #3757 from mstruk/KEYCLOAK-4150
KEYCLOAK-4150 Unresolved variable ${cliane_security-admin-console} in admin web client
This commit is contained in:
commit
536b88790e
7 changed files with 191 additions and 3 deletions
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2017 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.theme;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class TemplatingUtil {
|
||||
|
||||
public static String resolveVariables(String text, Properties props) {
|
||||
return resolveVariables(text, props, "${", "}");
|
||||
}
|
||||
|
||||
public static String resolveVariables(String text, Properties props, String startMarker, String endMarker) {
|
||||
|
||||
int e = 0;
|
||||
int s = text.indexOf(startMarker);
|
||||
if (s == -1) {
|
||||
return text;
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
do {
|
||||
if (e < s) {
|
||||
sb.append(text.substring(e, s));
|
||||
}
|
||||
e = text.indexOf(endMarker, s + startMarker.length());
|
||||
if (e != -1) {
|
||||
String key = text.substring(s + startMarker.length(), e);
|
||||
sb.append(props.getProperty(key, key));
|
||||
e += endMarker.length();
|
||||
s = text.indexOf(startMarker, e);
|
||||
} else {
|
||||
e = s;
|
||||
break;
|
||||
}
|
||||
} while (s != -1);
|
||||
|
||||
if (e < text.length()) {
|
||||
sb.append(text.substring(e));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,10 +17,13 @@
|
|||
|
||||
package org.keycloak.theme.beans;
|
||||
|
||||
import freemarker.template.SimpleScalar;
|
||||
import freemarker.template.TemplateMethodModelEx;
|
||||
import freemarker.template.TemplateModelException;
|
||||
import org.keycloak.theme.TemplatingUtil;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
@ -40,10 +43,27 @@ public class MessageFormatterMethod implements TemplateMethodModelEx {
|
|||
@Override
|
||||
public Object exec(List list) throws TemplateModelException {
|
||||
if (list.size() >= 1) {
|
||||
// resolve any remaining ${} expressions
|
||||
List<Object> resolved = resolve(list.subList(1, list.size()));
|
||||
String key = list.get(0).toString();
|
||||
return new MessageFormat(messages.getProperty(key,key),locale).format(list.subList(1, list.size()).toArray());
|
||||
return new MessageFormat(messages.getProperty(key,key),locale).format(resolved.toArray());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Object> resolve(List<Object> list) {
|
||||
ArrayList<Object> result = new ArrayList<>();
|
||||
for (Object item: list) {
|
||||
if (item instanceof SimpleScalar) {
|
||||
item = ((SimpleScalar) item).getAsString();
|
||||
}
|
||||
if (item instanceof String) {
|
||||
result.add(TemplatingUtil.resolveVariables((String) item, messages));
|
||||
} else {
|
||||
result.add(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2017 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.theme.beans;
|
||||
|
||||
import freemarker.template.TemplateModelException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class MessageFormatterMethodTest {
|
||||
|
||||
@Test
|
||||
public void test() throws TemplateModelException {
|
||||
|
||||
Locale locale = Locale.US;
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("backToApplication", "Back to application");
|
||||
properties.setProperty("backToClient", "Back to {0}");
|
||||
properties.setProperty("client_admin-console", "Admin Console");
|
||||
properties.setProperty("realm_example-realm", "Example Realm");
|
||||
|
||||
|
||||
MessageFormatterMethod fmt = new MessageFormatterMethod(locale, properties);
|
||||
|
||||
String msg = (String) fmt.exec(Arrays.asList("backToClient", "${client_admin-console}"));
|
||||
Assert.assertEquals("Back to Admin Console", msg);
|
||||
|
||||
msg = (String) fmt.exec(Arrays.asList("backToClient", "client_admin-console"));
|
||||
Assert.assertEquals("Back to client_admin-console", msg);
|
||||
|
||||
msg = (String) fmt.exec(Arrays.asList("backToClient", "client '${client_admin-console}' from '${realm_example-realm}'."));
|
||||
Assert.assertEquals("Back to client 'Admin Console' from 'Example Realm'.", msg);
|
||||
}
|
||||
}
|
|
@ -864,7 +864,7 @@ public class AccountTest extends AbstractTestRealmKeycloakTest {
|
|||
Assert.assertTrue(applicationsPage.isCurrent());
|
||||
|
||||
Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("Account", "test-app", "test-app-scope", "third-party", "test-app-authz", "My Named Test App"));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("Account", "test-app", "test-app-scope", "third-party", "test-app-authz", "My Named Test App", "Test App Named - ${client_account}"));
|
||||
|
||||
AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
|
||||
Assert.assertEquals(2, accountEntry.getRolesAvailable().size());
|
||||
|
@ -951,7 +951,20 @@ public class AccountTest extends AbstractTestRealmKeycloakTest {
|
|||
// When a client has a name provided, the name should be available to the back link
|
||||
Assert.assertEquals("Back to " + namedClient.getName(), profilePage.getBackToApplicationLinkText());
|
||||
Assert.assertEquals(namedClient.getBaseUrl(), profilePage.getBackToApplicationLinkHref());
|
||||
|
||||
|
||||
foundClients = testRealm.clients().findByClientId("var-named-test-app");
|
||||
if (foundClients.isEmpty()) {
|
||||
Assert.fail("Unable to find var-named-test-app");
|
||||
}
|
||||
namedClient = foundClients.get(0);
|
||||
|
||||
driver.navigate().to(profilePage.getPath() + "?referrer=" + namedClient.getClientId());
|
||||
Assert.assertTrue(profilePage.isCurrent());
|
||||
// When a client has a name provided as a variable, the name should be resolved using a localized bundle and available to the back link
|
||||
Assert.assertEquals("Back to Test App Named - Account", profilePage.getBackToApplicationLinkText());
|
||||
Assert.assertEquals(namedClient.getBaseUrl(), profilePage.getBackToApplicationLinkHref());
|
||||
|
||||
|
||||
foundClients = testRealm.clients().findByClientId("test-app");
|
||||
if (foundClients.isEmpty()) {
|
||||
Assert.fail("Unable to find test-app");
|
||||
|
|
|
@ -19,9 +19,13 @@ package org.keycloak.testsuite.i18n;
|
|||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:gerbermichi@me.com">Michael Gerber</a>
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
|
||||
|
@ -49,4 +53,25 @@ public class AccountPageTest extends AbstractI18NTest {
|
|||
Assert.assertEquals("English", accountUpdateProfilePage.getLanguageDropdownText());
|
||||
accountUpdateProfilePage.logout();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalizedReferrerLinkContent() {
|
||||
RealmResource testRealm = testRealm();
|
||||
List<ClientRepresentation> foundClients = testRealm.clients().findByClientId("var-named-test-app");
|
||||
if (foundClients.isEmpty()) {
|
||||
Assert.fail("Unable to find var-named-test-app");
|
||||
}
|
||||
ClientRepresentation namedClient = foundClients.get(0);
|
||||
|
||||
driver.navigate().to(accountUpdateProfilePage.getPath() + "?referrer=" + namedClient.getClientId());
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
Assert.assertTrue(accountUpdateProfilePage.isCurrent());
|
||||
|
||||
accountUpdateProfilePage.openLanguage("Deutsch");
|
||||
Assert.assertEquals("Deutsch", accountUpdateProfilePage.getLanguageDropdownText());
|
||||
|
||||
// When a client has a name provided as a variable, the name should be resolved using a localized bundle and available to the back link
|
||||
Assert.assertEquals("Zur\u00FCck zu Test App Named - Konto", accountUpdateProfilePage.getBackToApplicationLinkText());
|
||||
Assert.assertEquals(namedClient.getBaseUrl(), accountUpdateProfilePage.getBackToApplicationLinkHref());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,6 +331,17 @@
|
|||
],
|
||||
"adminUrl": "http://localhost:8180/namedapp/base/admin",
|
||||
"secret": "password"
|
||||
},
|
||||
{
|
||||
"clientId": "var-named-test-app",
|
||||
"name": "Test App Named - ${client_account}",
|
||||
"enabled": true,
|
||||
"baseUrl": "http://localhost:8180/varnamedapp/base",
|
||||
"redirectUris": [
|
||||
"http://localhost:8180/varnamedapp/base/*"
|
||||
],
|
||||
"adminUrl": "http://localhost:8180/varnamedapp/base/admin",
|
||||
"secret": "password"
|
||||
}
|
||||
],
|
||||
"roles" : {
|
||||
|
|
|
@ -50,6 +50,7 @@ role_manage-clients=Clients verwalten
|
|||
role_manage-events=Events verwalten
|
||||
role_view-profile=Profile ansehen
|
||||
role_manage-account=Profile verwalten
|
||||
client_account=Konto
|
||||
|
||||
requiredFields=Erforderliche Felder
|
||||
allFieldsRequired=Alle Felder sind Erforderlich
|
||||
|
|
Loading…
Reference in a new issue