Merge pull request #1261 from panga/master
KEYCLOAK-1306 - Better Admin API error handling (new)
This commit is contained in:
commit
c193ba0c81
11 changed files with 195 additions and 4 deletions
|
@ -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.
|
|
@ -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() {
|
||||
}, 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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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> {
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.services.messages.AdminMessagesProviderFactory
|
|
@ -2,3 +2,4 @@ org.keycloak.protocol.LoginProtocolSpi
|
|||
org.keycloak.protocol.ProtocolMapperSpi
|
||||
org.keycloak.exportimport.ClientImportSpi
|
||||
org.keycloak.wellknown.WellKnownSpi
|
||||
org.keycloak.messages.MessagesSpi
|
Loading…
Reference in a new issue