parent
e255fc1a10
commit
2496dc114c
|
@ -16,6 +16,7 @@
|
|||
*******************************************************************************/
|
||||
package org.mitre.openid.connect.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
@ -25,6 +26,9 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -56,6 +60,8 @@ public class ConfigurationPropertiesBean {
|
|||
|
||||
private Locale locale = Locale.ENGLISH; // we default to the english translation
|
||||
|
||||
private List<String> languageNamespaces = Lists.newArrayList("messages");
|
||||
|
||||
public boolean dualClient = false;
|
||||
|
||||
public ConfigurationPropertiesBean() {
|
||||
|
@ -67,7 +73,7 @@ public class ConfigurationPropertiesBean {
|
|||
* @throws HttpsUrlRequiredException
|
||||
*/
|
||||
@PostConstruct
|
||||
public void checkForHttps() {
|
||||
public void checkConfigConsistency() {
|
||||
if (!StringUtils.startsWithIgnoreCase(issuer, "https")) {
|
||||
if (this.forceHttps) {
|
||||
logger.error("Configured issuer url is not using https scheme. Server will be shut down!");
|
||||
|
@ -77,6 +83,10 @@ public class ConfigurationPropertiesBean {
|
|||
logger.warn("\n\n**\n** WARNING: Configured issuer url is not using https scheme.\n**\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (languageNamespaces == null || languageNamespaces.isEmpty()) {
|
||||
logger.error("No configured language namespaces! Text rendering will fail!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,6 +181,20 @@ public class ConfigurationPropertiesBean {
|
|||
this.locale = locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the languageNamespaces
|
||||
*/
|
||||
public List<String> getLanguageNamespaces() {
|
||||
return languageNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param languageNamespaces the languageNamespaces to set
|
||||
*/
|
||||
public void setLanguageNamespaces(List<String> languageNamespaces) {
|
||||
this.languageNamespaces = languageNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if dual client is configured, otherwise false
|
||||
*/
|
||||
|
@ -184,4 +208,19 @@ public class ConfigurationPropertiesBean {
|
|||
public void setDualClient(boolean dualClient) {
|
||||
this.dualClient = dualClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of namespaces as a JSON string
|
||||
* @return
|
||||
*/
|
||||
public String getLanguageNamespacesString() {
|
||||
return new Gson().toJson(getLanguageNamespaces());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default namespace (first in the nonempty list)
|
||||
*/
|
||||
public String getDefaultLanguageNamespace() {
|
||||
return getLanguageNamespaces().get(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class ConfigurationPropertiesBeanTest {
|
|||
// leave as default, which is unset/false
|
||||
try {
|
||||
bean.setIssuer("http://localhost:8080/openid-connect-server/");
|
||||
bean.checkForHttps();
|
||||
bean.checkConfigConsistency();
|
||||
} catch (BeanCreationException e) {
|
||||
fail("Unexpected BeanCreationException for http issuer with default forceHttps, message:" + e.getMessage());
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class ConfigurationPropertiesBeanTest {
|
|||
try {
|
||||
bean.setIssuer("http://localhost:8080/openid-connect-server/");
|
||||
bean.setForceHttps(false);
|
||||
bean.checkForHttps();
|
||||
bean.checkConfigConsistency();
|
||||
} catch (BeanCreationException e) {
|
||||
fail("Unexpected BeanCreationException for http issuer with forceHttps=false, message:" + e.getMessage());
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ public class ConfigurationPropertiesBeanTest {
|
|||
// set to true
|
||||
bean.setIssuer("http://localhost:8080/openid-connect-server/");
|
||||
bean.setForceHttps(true);
|
||||
bean.checkForHttps();
|
||||
bean.checkConfigConsistency();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -100,7 +100,7 @@ public class ConfigurationPropertiesBeanTest {
|
|||
// leave as default, which is unset/false
|
||||
try {
|
||||
bean.setIssuer("https://localhost:8080/openid-connect-server/");
|
||||
bean.checkForHttps();
|
||||
bean.checkConfigConsistency();
|
||||
} catch (BeanCreationException e) {
|
||||
fail("Unexpected BeanCreationException for https issuer with default forceHttps, message:" + e.getMessage());
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ public class ConfigurationPropertiesBeanTest {
|
|||
try {
|
||||
bean.setIssuer("https://localhost:8080/openid-connect-server/");
|
||||
bean.setForceHttps(false);
|
||||
bean.checkForHttps();
|
||||
bean.checkConfigConsistency();
|
||||
} catch (BeanCreationException e) {
|
||||
fail("Unexpected BeanCreationException for https issuer with forceHttps=false, message:" + e.getMessage());
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class ConfigurationPropertiesBeanTest {
|
|||
try {
|
||||
bean.setIssuer("https://localhost:8080/openid-connect-server/");
|
||||
bean.setForceHttps(true);
|
||||
bean.checkForHttps();
|
||||
bean.checkConfigConsistency();
|
||||
} catch (BeanCreationException e) {
|
||||
fail("Unexpected BeanCreationException for https issuer with forceHttps=true, message:" + e.getMessage());
|
||||
}
|
||||
|
|
|
@ -49,6 +49,17 @@
|
|||
<!-- This property sets the locale for server text -->
|
||||
<!-- <property name="locale" value="sv" /> -->
|
||||
|
||||
<!-- This property sets the set of namespaces for language translation files. The default is "messages". These are checked in the order presented here. -->
|
||||
<!--
|
||||
<property name="languageNamespaces">
|
||||
<list>
|
||||
<value>foo</value>
|
||||
<value>bar</value>
|
||||
<value>messages</value>
|
||||
</list>
|
||||
</property>
|
||||
-->
|
||||
|
||||
<!-- This property indicates if a dynamically registered client supports dual flows, such as client_credentials
|
||||
at the same time with authorization_code or implicit -->
|
||||
<!-- <property name="dualClient" value="true" /> -->
|
||||
|
|
|
@ -40,7 +40,12 @@
|
|||
$.i18n.init({
|
||||
fallbackLng: "en",
|
||||
lng: "${config.locale}",
|
||||
resGetPath: "resources/js/locale/__lng__/messages.json"
|
||||
resGetPath: "resources/js/locale/__lng__/__ns__.json",
|
||||
ns: {
|
||||
namespaces: ${config.languageNamespacesString},
|
||||
defaultNs: '${config.defaultLanguageNamespace}'
|
||||
},
|
||||
fallbackNS: ${config.languageNamespacesString}
|
||||
});
|
||||
moment.locale("${config.locale}");
|
||||
// safely set the title of the application
|
||||
|
|
|
@ -21,13 +21,16 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.AbstractMessageSource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
|
@ -50,19 +53,22 @@ public class JsonMessageSource extends AbstractMessageSource {
|
|||
|
||||
private Locale fallbackLocale = new Locale("en"); // US English is the fallback language
|
||||
|
||||
private Map<Locale, JsonObject> languageMaps = new HashMap<>();
|
||||
private Map<Locale, List<JsonObject>> languageMaps = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
private ConfigurationPropertiesBean config;
|
||||
|
||||
@Override
|
||||
protected MessageFormat resolveCode(String code, Locale locale) {
|
||||
|
||||
JsonObject lang = getLanguageMap(locale);
|
||||
List<JsonObject> langs = getLanguageMap(locale);
|
||||
|
||||
String value = getValue(code, lang);
|
||||
String value = getValue(code, langs);
|
||||
|
||||
if (value == null) {
|
||||
// if we haven't found anything, try the default locale
|
||||
lang = getLanguageMap(fallbackLocale);
|
||||
value = getValue(code, lang);
|
||||
langs = getLanguageMap(fallbackLocale);
|
||||
value = getValue(code, langs);
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
|
@ -76,6 +82,31 @@ public class JsonMessageSource extends AbstractMessageSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a value from the set of maps, taking the first match in order
|
||||
* @param code
|
||||
* @param langs
|
||||
* @return
|
||||
*/
|
||||
private String getValue(String code, List<JsonObject> langs) {
|
||||
if (langs == null || langs.isEmpty()) {
|
||||
// no language maps, nothing to look up
|
||||
return null;
|
||||
}
|
||||
|
||||
for (JsonObject lang : langs) {
|
||||
String value = getValue(code, lang);
|
||||
if (value != null) {
|
||||
// short circuit out of here if we find a match, otherwise keep going through the list
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find anything return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a single map
|
||||
* @param code
|
||||
* @param locale
|
||||
* @param lang
|
||||
|
@ -126,11 +157,13 @@ public class JsonMessageSource extends AbstractMessageSource {
|
|||
* @param locale
|
||||
* @return
|
||||
*/
|
||||
private JsonObject getLanguageMap(Locale locale) {
|
||||
private List<JsonObject> getLanguageMap(Locale locale) {
|
||||
|
||||
if (!languageMaps.containsKey(locale)) {
|
||||
try {
|
||||
String filename = locale.getLanguage() + File.separator + "messages.json";
|
||||
List<JsonObject> set = new ArrayList<>();
|
||||
for (String namespace : config.getLanguageNamespaces()) {
|
||||
String filename = locale.getLanguage() + File.separator + namespace + ".json";
|
||||
|
||||
Resource r = getBaseDirectory().createRelative(filename);
|
||||
|
||||
|
@ -139,7 +172,9 @@ public class JsonMessageSource extends AbstractMessageSource {
|
|||
JsonParser parser = new JsonParser();
|
||||
JsonObject obj = (JsonObject) parser.parse(new InputStreamReader(r.getInputStream(), "UTF-8"));
|
||||
|
||||
languageMaps.put(locale, obj);
|
||||
set.add(obj);
|
||||
}
|
||||
languageMaps.put(locale, set);
|
||||
} catch (JsonIOException | JsonSyntaxException | IOException e) {
|
||||
logger.error("Unable to load locale", e);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue