commit
b3bb68aed7
13 changed files with 50 additions and 324 deletions
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.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);
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.messages;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
|
||||
*/
|
||||
public interface MessagesProviderFactory extends ProviderFactory<MessagesProvider> {
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.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 isInternal() {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.services.messages;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.messages.MessagesProvider;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
|
||||
*/
|
||||
public class AdminMessagesProvider implements MessagesProvider {
|
||||
|
||||
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
|
||||
|
||||
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);
|
||||
|
||||
try {
|
||||
return new MessageFormat(message, locale).format(parameters);
|
||||
} catch (Exception e) {
|
||||
logger.failedToFormatMessage(e.getMessage());
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@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.failedToloadMessages(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.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";
|
||||
}
|
||||
|
||||
}
|
|
@ -82,7 +82,6 @@ public class KeycloakApplication extends Application {
|
|||
singletons.add(new ServerVersionResource());
|
||||
singletons.add(new RealmsResource());
|
||||
singletons.add(new AdminRoot());
|
||||
singletons.add(new ModelExceptionMapper());
|
||||
classes.add(QRCodeResource.class);
|
||||
classes.add(ThemeResource.class);
|
||||
classes.add(JsResource.class);
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.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;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:leonardo.zanivan@gmail.com">Leonardo Zanivan</a>
|
||||
*/
|
||||
@Provider
|
||||
public class ModelExceptionMapper implements ExceptionMapper<ModelException> {
|
||||
|
||||
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
|
||||
|
||||
@Context
|
||||
private KeycloakSession session;
|
||||
|
||||
@Override
|
||||
public Response toResponse(ModelException ex) {
|
||||
String message = session.getProvider(MessagesProvider.class, "admin")
|
||||
.getMessage(ex.getMessage(), ex.getParameters());
|
||||
|
||||
logger.error(message, ex);
|
||||
return ErrorResponse.error(message, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@ import org.keycloak.theme.BrowserSecurityHeaderSetup;
|
|||
import org.keycloak.theme.FreeMarkerException;
|
||||
import org.keycloak.theme.FreeMarkerUtil;
|
||||
import org.keycloak.theme.Theme;
|
||||
import org.keycloak.theme.ThemeProvider;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
|
@ -281,7 +280,7 @@ public class AdminConsole {
|
|||
if (!uriInfo.getRequestUri().getPath().endsWith("/")) {
|
||||
return Response.status(302).location(uriInfo.getRequestUriBuilder().path("/").build()).build();
|
||||
} else {
|
||||
Theme theme = getTheme();
|
||||
Theme theme = AdminRoot.getTheme(session, realm);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
|
@ -303,11 +302,6 @@ public class AdminConsole {
|
|||
}
|
||||
}
|
||||
|
||||
private Theme getTheme() throws IOException {
|
||||
ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
|
||||
return themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{indexhtml: index.html}") // this expression is a hack to get around jaxdoclet generation bug. Doesn't like index.html
|
||||
public Response getIndexHtmlRedirect() {
|
||||
|
@ -318,11 +312,7 @@ public class AdminConsole {
|
|||
@Path("messages.json")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Properties getMessages(@QueryParam("lang") String lang) {
|
||||
try {
|
||||
Locale locale = lang != null ? Locale.forLanguageTag(lang) : Locale.ENGLISH;
|
||||
return getTheme().getMessages("admin-messages", locale);
|
||||
} catch (IOException e) {
|
||||
throw new WebApplicationException("Failed to load message bundle", e);
|
||||
}
|
||||
return AdminRoot.getMessages(session, realm, "admin-messages", lang);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ import org.keycloak.services.managers.AuthenticationManager;
|
|||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.Cors;
|
||||
import org.keycloak.services.resources.admin.info.ServerInfoAdminResource;
|
||||
import org.keycloak.theme.Theme;
|
||||
import org.keycloak.theme.ThemeProvider;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
@ -47,6 +49,9 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Root resource for admin console and admin REST API
|
||||
|
@ -265,4 +270,31 @@ public class AdminRoot {
|
|||
}
|
||||
}
|
||||
|
||||
public static Theme getTheme(KeycloakSession session, RealmModel realm) throws IOException {
|
||||
ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
|
||||
return themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN);
|
||||
}
|
||||
|
||||
public static Properties getMessages(KeycloakSession session, RealmModel realm, String lang) {
|
||||
try {
|
||||
Theme theme = getTheme(session, realm);
|
||||
Locale locale = lang != null ? Locale.forLanguageTag(lang) : Locale.ENGLISH;
|
||||
return theme.getMessages(locale);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load messages from theme", e);
|
||||
return new Properties();
|
||||
}
|
||||
}
|
||||
|
||||
public static Properties getMessages(KeycloakSession session, RealmModel realm, String bundle, String lang) {
|
||||
try {
|
||||
Theme theme = getTheme(session, realm);
|
||||
Locale locale = lang != null ? Locale.forLanguageTag(lang) : Locale.ENGLISH;
|
||||
return theme.getMessages(bundle, locale);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load messages from theme", e);
|
||||
return new Properties();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.keycloak.models.GroupModel;
|
|||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ModelReadOnlyException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
|
@ -54,6 +55,7 @@ import org.keycloak.representations.idm.GroupRepresentation;
|
|||
import org.keycloak.representations.idm.UserConsentRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||
import org.keycloak.services.ErrorResponseException;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.managers.UserManager;
|
||||
|
@ -74,11 +76,14 @@ import javax.ws.rs.core.Context;
|
|||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -86,6 +91,7 @@ import java.util.HashSet;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.keycloak.models.UsernameLoginFailureModel;
|
||||
|
@ -94,6 +100,9 @@ import org.keycloak.services.managers.UserSessionManager;
|
|||
import org.keycloak.services.resources.AccountService;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.services.validation.Validation;
|
||||
import org.keycloak.theme.Theme;
|
||||
import org.keycloak.theme.Theme.Type;
|
||||
import org.keycloak.theme.ThemeProvider;
|
||||
|
||||
/**
|
||||
* Base resource for managing users
|
||||
|
@ -719,6 +728,10 @@ public class UsersResource {
|
|||
throw new BadRequestException("Resetting to N old passwords is not allowed.");
|
||||
} catch (ModelReadOnlyException mre) {
|
||||
throw new BadRequestException("Can't reset password as account is read only");
|
||||
} catch (ModelException e) {
|
||||
Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
|
||||
throw new ErrorResponseException(e.getMessage(), MessageFormat.format(messages.getProperty(e.getMessage(), e.getMessage()), e.getParameters()),
|
||||
Status.BAD_REQUEST);
|
||||
}
|
||||
if (pass.isTemporary() != null && pass.isTemporary()) user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#
|
||||
# Copyright 2016 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.
|
||||
#
|
||||
|
||||
org.keycloak.services.messages.AdminMessagesProviderFactory
|
|
@ -17,5 +17,4 @@
|
|||
|
||||
org.keycloak.exportimport.ClientDescriptionConverterSpi
|
||||
org.keycloak.wellknown.WellKnownSpi
|
||||
org.keycloak.messages.MessagesSpi
|
||||
org.keycloak.services.clientregistration.ClientRegistrationSpi
|
||||
|
|
|
@ -506,8 +506,8 @@ module.controller('UserCredentialsCtrl', function($scope, realm, user, RequiredA
|
|||
$scope.password = null;
|
||||
$scope.confirmPassword = null;
|
||||
}, function(response) {
|
||||
if (response.data && response.data.errorMessage) {
|
||||
Notifications.error(response.data.errorMessage);
|
||||
if (response.data && response.data['error_description']) {
|
||||
Notifications.error(response.data['error_description']);
|
||||
} else {
|
||||
Notifications.error("Failed to reset user password");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue