diff options
| author | Alex Rudyy <orudyy@apache.org> | 2013-09-14 11:29:25 +0000 |
|---|---|---|
| committer | Alex Rudyy <orudyy@apache.org> | 2013-09-14 11:29:25 +0000 |
| commit | ae2447f47e3f00db76196cf5dc4ae35338c303ff (patch) | |
| tree | c8d2cebce4734f65690a08e3e1a369a4b89b1e6c | |
| parent | 43a52f691e64d400d798c9766fec0c22d9704415 (diff) | |
| download | qpid-python-ae2447f47e3f00db76196cf5dc4ae35338c303ff.tar.gz | |
QPID-5138: Add preferences REST interfaces to get, set and delete preferences
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1523221 13f79535-47bb-0310-9956-ffa450edef68
6 files changed, 532 insertions, 0 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index 00ad041512..4aebf90a75 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -49,6 +49,8 @@ import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet; import org.apache.qpid.server.management.plugin.servlet.rest.LogoutServlet; import org.apache.qpid.server.management.plugin.servlet.rest.MessageContentServlet; import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.PreferencesServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.UserPreferencesServlet; import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet; import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet; import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet; @@ -300,6 +302,8 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem addRestServlet(root, "plugin", Plugin.class); addRestServlet(root, "preferencesprovider", AuthenticationProvider.class, PreferencesProvider.class); + root.addServlet(new ServletHolder(new UserPreferencesServlet()), "/rest/userpreferences/*"); + root.addServlet(new ServletHolder(new PreferencesServlet()), "/rest/preferences"); root.addServlet(new ServletHolder(new StructureServlet()), "/rest/structure"); root.addServlet(new ServletHolder(new MessageServlet()), "/rest/message/*"); root.addServlet(new ServletHolder(new MessageContentServlet()), "/rest/message-content/*"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java index 42eecb28ac..c0f4b55f64 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; +import java.io.PrintWriter; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; @@ -40,6 +41,10 @@ import org.apache.qpid.server.management.plugin.HttpManagementConfiguration; import org.apache.qpid.server.management.plugin.HttpManagementUtil; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.SecurityManager; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; public abstract class AbstractServlet extends HttpServlet { @@ -254,4 +259,20 @@ public abstract class AbstractServlet extends HttpServlet throw new RuntimeException("Failed to send error response code " + errorCode, e); } } + + protected void sendJsonResponse(Object object, HttpServletResponse response) throws IOException, + JsonGenerationException, JsonMappingException + { + response.setStatus(HttpServletResponse.SC_OK); + + response.setHeader("Cache-Control","no-cache"); + response.setHeader("Pragma","no-cache"); + response.setDateHeader ("Expires", 0); + response.setContentType("application/json"); + + final PrintWriter writer = response.getWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + mapper.writeValue(writer, object); + } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java new file mode 100644 index 0000000000..84f074ba43 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java @@ -0,0 +1,109 @@ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; +import java.net.SocketAddress; +import java.security.Principal; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.security.auth.Subject; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.HttpManagementUtil; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.codehaus.jackson.map.ObjectMapper; + +public class PreferencesServlet extends AbstractServlet +{ + private static final long serialVersionUID = 1L; + + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + PreferencesProvider preferencesProvider = getPreferencesProvider(request); + String userName = getAuthenticatedUserName(request); + Map<String, Object> preferences = preferencesProvider.getPreferences(userName); + if (preferences == null) + { + preferences = Collections.<String, Object>emptyMap(); + } + sendJsonResponse(preferences, response); + } + + /* + * replace preferences + */ + @Override + protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + PreferencesProvider preferencesProvider = getPreferencesProvider(request); + String userName = getAuthenticatedUserName(request); + + ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + Map<String, Object> newPreferences = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + + preferencesProvider.deletePreferences(userName); + Map<String, Object> preferences = preferencesProvider.setPreferences(userName, newPreferences); + if (preferences == null) + { + preferences = Collections.<String, Object>emptyMap(); + } + sendJsonResponse(preferences, response); + } + + /* + * update preferences + */ + @Override + protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + PreferencesProvider preferencesProvider = getPreferencesProvider(request); + String userName = getAuthenticatedUserName(request); + + ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + Map<String, Object> newPreferences = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + Map<String, Object> preferences = preferencesProvider.setPreferences(userName, newPreferences); + if (preferences == null) + { + preferences = Collections.<String, Object>emptyMap(); + } + sendJsonResponse(preferences, response); + } + + private String getAuthenticatedUserName(HttpServletRequest request) + { + Subject subject = getAuthorisedSubject(request); + Principal principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + return principal.getName(); + } + + private AuthenticationProvider getAuthenticationProvider(HttpServletRequest request) + { + Broker broker = getBroker(); + SocketAddress localAddress = HttpManagementUtil.getSocketAddress(request); + return broker.getAuthenticationProvider(localAddress); + } + + private PreferencesProvider getPreferencesProvider(HttpServletRequest request) + { + PreferencesProvider preferencesProvider = getAuthenticationProvider(request).getPreferencesProvider(); + if (preferencesProvider == null) + { + throw new IllegalStateException("Preferences provider is not configured"); + } + return preferencesProvider; + } +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java new file mode 100644 index 0000000000..0dd2d6ff5f --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java @@ -0,0 +1,184 @@ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.User; + +public class UserPreferencesServlet extends AbstractServlet +{ + private static final Logger LOGGER = Logger.getLogger(UserPreferencesServlet.class); + private static final long serialVersionUID = 1L; + + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + String[] pathElements = null; + if (request.getPathInfo() != null && request.getPathInfo().length() > 0) + { + pathElements = request.getPathInfo().substring(1).split("/"); + } + if (pathElements != null && pathElements.length > 1) + { + getUserPreferences(pathElements[0], pathElements[1], response); + } + else + { + getUserList(pathElements, response); + } + } + + private void getUserPreferences(String authenticationProviderName, String userId, HttpServletResponse response) + throws IOException + { + Map<String, Object> preferences = null; + try + { + preferences = getUserPreferences(authenticationProviderName, userId); + } + catch (Exception e) + { + LOGGER.debug("Bad preferences request", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } + sendJsonResponse(preferences, response); + } + + private void getUserList(String[] pathElements, HttpServletResponse response) throws IOException + { + List<Map<String, Object>> users = null; + try + { + users = getUsers(pathElements); + } + catch (Exception e) + { + LOGGER.debug("Bad preferences request", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } + sendJsonResponse(users, response); + } + + private Map<String, Object> getUserPreferences(String authenticationProviderName, String userId) + { + AuthenticationProvider authenticationProvider = getAuthenticationProvider(authenticationProviderName); + if (authenticationProvider == null) + { + throw new IllegalArgumentException(String.format("Authentication provider '%s' is not found", + authenticationProviderName)); + } + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + if (preferencesProvider == null) + { + throw new IllegalStateException(String.format( + "Preferences provider is not set for authentication provider '%s'", authenticationProviderName)); + } + return preferencesProvider.getPreferences(userId); + } + + private AuthenticationProvider getAuthenticationProvider(String authenticationProviderName) + { + Broker broker = getBroker(); + Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if (authenticationProviderName.equals(authenticationProvider.getName())) + { + return authenticationProvider; + } + } + return null; + } + + private List<Map<String, Object>> getUsers(String[] pathElements) + { + List<Map<String, Object>> users = new ArrayList<Map<String, Object>>(); + String authenticationProviderName = pathElements != null && pathElements.length > 0 ? pathElements[0] : null; + + Broker broker = getBroker(); + Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if (authenticationProviderName != null && !authenticationProvider.getName().equals(authenticationProviderName)) + { + continue; + } + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + if (preferencesProvider != null) + { + Set<String> usernames = preferencesProvider.listUserIDs(); + for (String name : usernames) + { + Map<String, Object> userMap = new HashMap<String, Object>(); + userMap.put(User.NAME, name); + userMap.put("authenticationProvider", authenticationProvider.getName()); + users.add(userMap); + } + } + } + return users; + } + + /* + * removes preferences + */ + @Override + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) + { + final List<String[]> userData = new ArrayList<String[]>(); + for (String name : request.getParameterValues("user")) + { + String[] elements = name.split("/"); + if (elements.length != 2) + { + throw new IllegalArgumentException("Illegal parameter"); + } + userData.add(elements); + } + + if (!userData.isEmpty()) + { + Broker broker = getBroker(); + Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); + for (Iterator<String[]> it = userData.iterator(); it.hasNext();) + { + String[] data = (String[]) it.next(); + String authenticationProviderName = data[0]; + String userId = data[1]; + + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if (authenticationProviderName.equals(authenticationProvider.getName())) + { + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + if (preferencesProvider != null) + { + Set<String> usernames = preferencesProvider.listUserIDs(); + if (usernames.contains(userId)) + { + preferencesProvider.deletePreferences(userId); + } + } + break; + } + } + } + } + + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java new file mode 100644 index 0000000000..bf2044aa74 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java @@ -0,0 +1,95 @@ +package org.apache.qpid.systest.rest; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class PreferencesRestTest extends QpidRestTestCase +{ + private File _preferencesProviderFile; + + public void setUp() throws Exception + { + _preferencesProviderFile = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"webadmin\":{\"language\": \"en\", \"saveTabs\":true}}"); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_preferencesProviderFile != null) + { + _preferencesProviderFile.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, "test"); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesProviderFile.getAbsolutePath()); + brokerConfiguration.addPreferencesProviderConfiguration(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, + attributes); + + } + + public void testGetPreferences() throws Exception + { + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap("/rest/preferences"); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + } + + public void testUpdatePreferences() throws Exception + { + Map<String, Object> additionalPreferences = new HashMap<String, Object>(); + additionalPreferences.put("timezone", "Europe/London"); + additionalPreferences.put("test", 1); + + int status = getRestTestHelper().submitRequest("/rest/preferences", "POST", additionalPreferences); + assertEquals("Unexpected response code", 200, status); + + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap("/rest/preferences"); + assertEquals("Unexpected number of preferences", 4, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + assertEquals("Unexpected timezone preference", "Europe/London", preferences.get("timezone")); + assertEquals("Unexpected test preference", 1, preferences.get("test")); + } + + public void testReplacePreferences() throws Exception + { + Map<String, Object> additionalPreferences = new HashMap<String, Object>(); + additionalPreferences.put("timezone", "Europe/London"); + additionalPreferences.put("test", 1); + + int status = getRestTestHelper().submitRequest("/rest/preferences", "PUT", additionalPreferences); + assertEquals("Unexpected response code", 200, status); + + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap("/rest/preferences"); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected timezone preference", "Europe/London", preferences.get("timezone")); + assertEquals("Unexpected test preference", 1, preferences.get("test")); + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java new file mode 100644 index 0000000000..db6d513855 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java @@ -0,0 +1,119 @@ +package org.apache.qpid.systest.rest; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class UserPreferencesRestTest extends QpidRestTestCase +{ + private File _preferencesProviderFile; + + public void setUp() throws Exception + { + _preferencesProviderFile = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"webadmin\":{\"language\": \"en\", \"saveTabs\":true}," + + " \"admin\":{\"language\": \"fr\", \"saveTabs\":false}" + "}"); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_preferencesProviderFile != null) + { + _preferencesProviderFile.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, "test"); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesProviderFile.getAbsolutePath()); + brokerConfiguration.addPreferencesProviderConfiguration(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, + attributes); + + } + + public void testGetUserPreferences() throws Exception + { + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap( + "/rest/userpreferences/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/webadmin"); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + } + + public void testGetUserListForAuthenticationProvider() throws Exception + { + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList( + "/rest/userpreferences/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); + assertEquals("Unexpected number of users", 2, users.size()); + String[] expectedUsers = { "webadmin", "admin" }; + for (int i = 0; i < expectedUsers.length; i++) + { + Map<String, Object> user = findUser(expectedUsers[i], users); + assertNotNull(String.format("User %s is not found", expectedUsers[i]), user); + } + } + + public void testGetUserList() throws Exception + { + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/userpreferences"); + assertEquals("Unexpected number of users", 2, users.size()); + String[] expectedUsers = { "webadmin", "admin" }; + for (int i = 0; i < expectedUsers.length; i++) + { + Map<String, Object> user = findUser(expectedUsers[i], users); + assertNotNull(String.format("User %s is not found", expectedUsers[i]), user); + } + } + + public void testDeleteUser() throws Exception + { + int status = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/webadmin", + "UTF-8"), "DELETE", null); + assertEquals("Unexpected status ", 200, status); + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/userpreferences"); + assertEquals("Unexpected number of users", 1, users.size()); + Map<String, Object> user = findUser("admin", users); + assertNotNull("User admin is not found", user); + assertNull("User webadmin is found", findUser("webadmin", users)); + } + + private Map<String, Object> findUser(String userName, List<Map<String, Object>> users) + { + for (Map<String, Object> map : users) + { + if (userName.equals(map.get(User.NAME))) + { + return map; + } + } + return null; + } + +} |
