keycloak-aplcache

Merge pull request #1261 from panga/master KEYCLOAK-1306

5/19/2015 3:56:19 AM

Details

diff --git a/forms/common-themes/src/main/resources/theme/base/admin/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/messages_en.properties
new file mode 100644
index 0000000..ab297dd
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/messages_en.properties
@@ -0,0 +1,8 @@
+invalidPasswordMinLengthMessage=Invalid password: minimum length {0}.
+invalidPasswordMinLowerCaseCharsMessage=Invalid password: must contain at least {0} lower case characters.
+invalidPasswordMinDigitsMessage=Invalid password: must contain at least {0} numerical digits.
+invalidPasswordMinUpperCaseCharsMessage=Invalid password: must contain at least {0} upper case characters.
+invalidPasswordMinSpecialCharsMessage=Invalid password: must contain at least {0} special characters.
+invalidPasswordNotUsernameMessage=Invalid password: must not be equal to the username.
+invalidPasswordRegexPatternMessage=Invalid password: fails to match regex pattern(s).
+invalidPasswordHistoryMessage=Invalid password: must not be equal to any of last {0} passwords.
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
index bf5662b..9be9349 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
@@ -308,8 +308,12 @@ module.controller('UserCredentialsCtrl', function($scope, realm, user, User, Use
                 Notifications.success("The password has been reset");
                 $scope.password = null;
                 $scope.confirmPassword = null;
-            }, function() {
-                Notifications.error("Failed to reset user password");
+            }, function(response) {
+                if (response.data && response.data.errorMessage) {
+                    Notifications.error(response.data.errorMessage);
+                } else {
+                    Notifications.error("Failed to reset user password");
+                }
             });
         }, function() {
             $scope.password = null;
diff --git a/services/src/main/java/org/keycloak/messages/MessagesProvider.java b/services/src/main/java/org/keycloak/messages/MessagesProvider.java
new file mode 100644
index 0000000..ddb72dd
--- /dev/null
+++ b/services/src/main/java/org/keycloak/messages/MessagesProvider.java
@@ -0,0 +1,12 @@
+package org.keycloak.messages;
+
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public interface MessagesProvider extends Provider {
+
+    String getMessage(String messageKey, Object... parameters);
+
+}
diff --git a/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java b/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java
new file mode 100644
index 0000000..92c0df8
--- /dev/null
+++ b/services/src/main/java/org/keycloak/messages/MessagesProviderFactory.java
@@ -0,0 +1,10 @@
+package org.keycloak.messages;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public interface MessagesProviderFactory extends ProviderFactory<MessagesProvider> {
+
+}
diff --git a/services/src/main/java/org/keycloak/messages/MessagesSpi.java b/services/src/main/java/org/keycloak/messages/MessagesSpi.java
new file mode 100644
index 0000000..6e82006
--- /dev/null
+++ b/services/src/main/java/org/keycloak/messages/MessagesSpi.java
@@ -0,0 +1,32 @@
+package org.keycloak.messages;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public class MessagesSpi implements Spi {
+
+    @Override
+    public boolean isPrivate() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return "messages";
+    }
+
+    @Override
+    public Class<? extends Provider> getProviderClass() {
+        return MessagesProvider.class;
+    }
+
+    @Override
+    public Class<? extends ProviderFactory> getProviderFactoryClass() {
+        return MessagesProviderFactory.class;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/messages/AdminMessagesProvider.java b/services/src/main/java/org/keycloak/services/messages/AdminMessagesProvider.java
new file mode 100644
index 0000000..1da7bfb
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/messages/AdminMessagesProvider.java
@@ -0,0 +1,59 @@
+package org.keycloak.services.messages;
+
+import java.io.IOException;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.Properties;
+import org.jboss.logging.Logger;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.messages.MessagesProvider;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public class AdminMessagesProvider implements MessagesProvider {
+
+    private static final Logger logger = Logger.getLogger(AdminMessagesProvider.class);
+
+    private KeycloakSession session;
+    private Locale locale;
+    private Properties messagesBundle;
+
+    public AdminMessagesProvider(KeycloakSession session, Locale locale) {
+        this.session = session;
+        this.locale = locale;
+        this.messagesBundle = getMessagesBundle(locale);
+    }
+
+    @Override
+    public String getMessage(String messageKey, Object... parameters) {
+        String message = messagesBundle.getProperty(messageKey, messageKey);
+        return new MessageFormat(message, locale).format(parameters);
+    }
+
+    @Override
+    public void close() {
+    }
+
+    private Properties getMessagesBundle(Locale locale) {
+        Properties properties = new Properties();
+
+        if (locale == null) {
+            return properties;
+        }
+
+        URL url = getClass().getClassLoader().getResource(
+                "theme/base/admin/messages/messages_" + locale.toString() + ".properties");
+        if (url != null) {
+            try {
+                properties.load(url.openStream());
+            } catch (IOException ex) {
+                logger.warn("Failed to load messages", ex);
+            }
+        }
+
+        return properties;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/messages/AdminMessagesProviderFactory.java b/services/src/main/java/org/keycloak/services/messages/AdminMessagesProviderFactory.java
new file mode 100644
index 0000000..7fda4fd
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/messages/AdminMessagesProviderFactory.java
@@ -0,0 +1,37 @@
+package org.keycloak.services.messages;
+
+import java.util.Locale;
+import org.keycloak.Config;
+import org.keycloak.messages.MessagesProvider;
+import org.keycloak.messages.MessagesProviderFactory;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+public class AdminMessagesProviderFactory implements MessagesProviderFactory {
+
+    @Override
+    public MessagesProvider create(KeycloakSession session) {
+        return new AdminMessagesProvider(session, Locale.ENGLISH);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+    }
+
+    @Override
+    public void postInit(KeycloakSessionFactory factory) {
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public String getId() {
+        return "admin";
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index b0f02ad..e4c821c 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -39,7 +39,6 @@ import java.io.InputStream;
 import java.net.URI;
 import java.net.URL;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -75,6 +74,7 @@ public class KeycloakApplication extends Application {
         singletons.add(new ServerVersionResource());
         singletons.add(new RealmsResource());
         singletons.add(new AdminRoot());
+        singletons.add(new ModelExceptionMapper());
         classes.add(SkeletonKeyContextResolver.class);
         classes.add(QRCodeResource.class);
         classes.add(ThemeResource.class);
diff --git a/services/src/main/java/org/keycloak/services/resources/ModelExceptionMapper.java b/services/src/main/java/org/keycloak/services/resources/ModelExceptionMapper.java
new file mode 100644
index 0000000..c5cc88e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/ModelExceptionMapper.java
@@ -0,0 +1,27 @@
+package org.keycloak.services.resources;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import org.keycloak.messages.MessagesProvider;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelException;
+import org.keycloak.services.ErrorResponse;
+
+/**
+ * @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
+ */
+@Provider
+public class ModelExceptionMapper implements ExceptionMapper<ModelException> {
+
+    @Context
+    private KeycloakSession session;
+
+    @Override
+    public Response toResponse(ModelException ex) {
+        String message = session.getProvider(MessagesProvider.class, "admin")
+                .getMessage(ex.getMessage(), ex.getParameters());
+        return ErrorResponse.error(message, Response.Status.BAD_REQUEST);
+    }
+}
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.messages.MessagesProviderFactory b/services/src/main/resources/META-INF/services/org.keycloak.messages.MessagesProviderFactory
new file mode 100644
index 0000000..341e768
--- /dev/null
+++ b/services/src/main/resources/META-INF/services/org.keycloak.messages.MessagesProviderFactory
@@ -0,0 +1 @@
+org.keycloak.services.messages.AdminMessagesProviderFactory
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index e1c0b91..a9b5a54 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,4 +1,5 @@
 org.keycloak.protocol.LoginProtocolSpi
 org.keycloak.protocol.ProtocolMapperSpi
 org.keycloak.exportimport.ClientImportSpi
-org.keycloak.wellknown.WellKnownSpi
\ No newline at end of file
+org.keycloak.wellknown.WellKnownSpi
+org.keycloak.messages.MessagesSpi
\ No newline at end of file