diff options
| author | Robert Gemmell <robbie@apache.org> | 2012-08-24 15:33:00 +0000 |
|---|---|---|
| committer | Robert Gemmell <robbie@apache.org> | 2012-08-24 15:33:00 +0000 |
| commit | 881f4a51e4b9e44f888366fc06f6070f47921b90 (patch) | |
| tree | c081e6cd763dde58e1f9254cdddbba872be619b6 /qpid/java/broker-plugins/management-http/src | |
| parent | 3196cc6e0e4f6c537ab7f3694d7b2e454cd97fbc (diff) | |
| download | qpid-python-881f4a51e4b9e44f888366fc06f6070f47921b90.tar.gz | |
QPID-4236, QPID-4237, QPID-4245: Added group management functionality, and exposed it via the web management interface. Removed group definition functionality from the ACL plugin. The ACL plugin uses groups but no longer defines them.
Introduced SubjectCreator as a facade to AuthenticationManager and group
management classes.
Applied access control to user and group management.
Fixed bug in choosing between update and creation in RestServlet.
Moved lots of RestTest helper methods to RestTestHelper.
Fixed authentication, authorisation, and status logging when using the web ui.
Applied patch from Philip Harvey <phil@philharveyonline.com>, Keith Wall and myself.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1376968 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker-plugins/management-http/src')
43 files changed, 2364 insertions, 543 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java index c2f9b73b54..38a8722852 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java @@ -44,6 +44,9 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Connection; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Queue; @@ -158,6 +161,9 @@ public class Management addRestServlet(root, "virtualhost", VirtualHost.class); addRestServlet(root, "authenticationprovider", AuthenticationProvider.class); addRestServlet(root, "user", AuthenticationProvider.class, User.class); + addRestServlet(root, "groupprovider", GroupProvider.class); + addRestServlet(root, "group", GroupProvider.class, Group.class); + addRestServlet(root, "groupmember", GroupProvider.class, Group.class, GroupMember.class); addRestServlet(root, "exchange", VirtualHost.class, Exchange.class); addRestServlet(root, "queue", VirtualHost.class, Queue.class); addRestServlet(root, "connection", VirtualHost.class, Connection.class); 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 a76bd98179..1469808565 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 @@ -24,8 +24,10 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.security.Principal; -import java.util.Collections; +import java.security.AccessControlException; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + import javax.security.auth.Subject; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -33,168 +35,293 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.HttpManagementActor; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; public abstract class AbstractServlet extends HttpServlet { + private static final Logger LOGGER = Logger.getLogger(AbstractServlet.class); + + protected static final String ATTR_SUBJECT = "subject"; + private static final String ATTR_LOG_ACTOR = "AbstractServlet.logActor"; + private final Broker _broker; + private RootMessageLogger _rootLogger; + protected AbstractServlet() { super(); _broker = ApplicationRegistry.getInstance().getBroker(); + _rootLogger = ApplicationRegistry.getInstance().getRootMessageLogger(); } protected AbstractServlet(Broker broker) { _broker = broker; + _rootLogger = ApplicationRegistry.getInstance().getRootMessageLogger(); } @Override - protected final void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException + protected final void doGet(final HttpServletRequest request, final HttpServletResponse resp) { - setAuthorizedSubject(request); - try - { - onGet(request, resp); - } - finally - { - clearAuthorizedSubject(); - } + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() + { + @Override + public Void run() throws Exception + { + doGetWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); } - protected void onGet(HttpServletRequest request, HttpServletResponse resp) throws IOException, ServletException + /** + * Performs the GET action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { - super.doGet(request, resp); + throw new UnsupportedOperationException("GET not supported by this servlet"); } - private void clearAuthorizedSubject() + + @Override + protected final void doPost(final HttpServletRequest request, final HttpServletResponse resp) { - org.apache.qpid.server.security.SecurityManager.setThreadSubject(null); + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() + { + @Override + public Void run() throws Exception + { + doPostWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); } - - private void setAuthorizedSubject(HttpServletRequest request) + /** + * Performs the POST action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doPostWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - HttpSession session = request.getSession(true); - Subject subject = (Subject) session.getAttribute("subject"); + throw new UnsupportedOperationException("POST not supported by this servlet"); + } - if(subject == null) - { - Principal principal = request.getUserPrincipal(); - if(principal != null) - { - subject = new Subject(false, Collections.singleton(principal),Collections.emptySet(), - Collections.emptySet()); - } - else + @Override + protected final void doPut(final HttpServletRequest request, final HttpServletResponse resp) + { + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() { - String header = request.getHeader("Authorization"); + @Override + public Void run() throws Exception + { + doPutWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); + } - /* - * TODO - Should configure whether basic authentication is allowed... and in particular whether it - * should be allowed over non-ssl connections - * */ + /** + * Performs the PUT action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doPutWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + throw new UnsupportedOperationException("PUT not supported by this servlet"); + } - if (header != null) + @Override + protected final void doDelete(final HttpServletRequest request, final HttpServletResponse resp) + throws ServletException, IOException + { + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() + { + @Override + public Void run() throws Exception { - String[] tokens = header.split("\\s"); - if(tokens.length >= 2 - && "BASIC".equalsIgnoreCase(tokens[0])) - { - String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2); - if(credentials.length == 2) - { - SocketAddress address = getSocketAddress(request); - AuthenticationManager authenticationManager = - ApplicationRegistry.getInstance().getAuthenticationManager(address); - AuthenticationResult authResult = - authenticationManager.authenticate(credentials[0], credentials[1]); - subject = authResult.getSubject(); - - } - } + doDeleteWithSubjectAndActor(request, resp); + return null; } - } - } - if (subject == null) - { - subject = AnonymousAuthenticationManager.ANONYMOUS_SUBJECT; - } - org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject); - + }, + request, + resp + ); } - protected Subject getSubject(HttpSession session) + /** + * Performs the PUT action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doDeleteWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - return (Subject)session.getAttribute("subject"); + throw new UnsupportedOperationException("DELETE not supported by this servlet"); } - @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + private void doWithSubjectAndActor( + PrivilegedExceptionAction<Void> privilegedExceptionAction, + final HttpServletRequest request, + final HttpServletResponse resp) { - setAuthorizedSubject(req); + Subject subject = getAndCacheAuthorizedSubject(request); + org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject); + try { - onPost(req, resp); + HttpManagementActor logActor = getLogActorAndCacheInSession(request); + CurrentActor.set(logActor); + try + { + Subject.doAs(subject, privilegedExceptionAction); + } + catch(RuntimeException e) + { + LOGGER.error("Unable to perform action", e); + throw e; + } + catch (PrivilegedActionException e) + { + LOGGER.error("Unable to perform action", e); + throw new RuntimeException(e.getCause()); + } + finally + { + CurrentActor.remove(); + } } finally { - clearAuthorizedSubject(); + org.apache.qpid.server.security.SecurityManager.setThreadSubject(null); } - } - protected void onPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + /** + * Gets the logged-in {@link Subject} by trying the following: + * + * <ul> + * <li>Get it from the session</li> + * <li>Get it from the request</li> + * <li>Log in using the username and password in the Authorization HTTP header</li> + * <li>Create a Subject representing the anonymous user.</li> + * </ul> + * + * If an authenticated subject is found it is cached in the http session. + */ + private Subject getAndCacheAuthorizedSubject(HttpServletRequest request) { - super.doPost(req, resp); - } + HttpSession session = request.getSession(); + Subject subject = getSubjectFromSession(session); - @Override - protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException - { - setAuthorizedSubject(req); - try + if(subject != null) { - onPut(req, resp); + return subject; + } + SubjectCreator subjectCreator = ApplicationRegistry.getInstance().getSubjectCreator(getSocketAddress(request)); + + String remoteUser = request.getRemoteUser(); + if(remoteUser != null) + { + subject = subjectCreator.createSubjectWithGroups(remoteUser); } - finally + else { - clearAuthorizedSubject(); + String header = request.getHeader("Authorization"); + + /* + * TODO - Should configure whether basic authentication is allowed... and in particular whether it + * should be allowed over non-ssl connections + * */ + + if (header != null) + { + String[] tokens = header.split("\\s"); + if(tokens.length >= 2 + && "BASIC".equalsIgnoreCase(tokens[0])) + { + String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2); + if(credentials.length == 2) + { + SubjectAuthenticationResult authResult = subjectCreator.authenticate(credentials[0], credentials[1]); + if( authResult.getStatus() != AuthenticationStatus.SUCCESS) + { + //TODO: write a return response indicating failure? + throw new AccessControlException("Incorrect username or password"); + } + subject = authResult.getSubject(); + } + else + { + //TODO: write a return response indicating failure? + throw new AccessControlException("Invalid number of credentials supplied: " + + credentials.length); + } + } + } } - } - protected void onPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException - { - super.doPut(req,resp); + if (subject != null) + { + setSubjectInSession(subject, session); + } + else + { + subject = subjectCreator.createSubjectWithGroups(AnonymousAuthenticationManager.ANONYMOUS_USERNAME); + } + + return subject; } - @Override - protected final void doDelete(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException + private HttpManagementActor getLogActorAndCacheInSession(HttpServletRequest req) { - setAuthorizedSubject(req); - try - { - onDelete(req, resp); - } - finally + HttpSession session = req.getSession(); + + HttpManagementActor actor = (HttpManagementActor) session.getAttribute(ATTR_LOG_ACTOR); + if(actor == null) { - clearAuthorizedSubject(); + actor = new HttpManagementActor(_rootLogger, req.getRemoteAddr(), req.getRemotePort()); + session.setAttribute(ATTR_LOG_ACTOR, actor); } + + return actor; } - protected void onDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + protected Subject getSubjectFromSession(HttpSession session) { - super.doDelete(req, resp); + return (Subject)session.getAttribute(ATTR_SUBJECT); } + protected void setSubjectInSession(Subject subject, final HttpSession session) + { + session.setAttribute(ATTR_SUBJECT, subject); + } protected Broker getBroker() { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java index 404793b592..04eda2a787 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java @@ -44,7 +44,7 @@ public class LogRecordsServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java index bc87f0bcc5..ae794472bf 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java @@ -48,7 +48,7 @@ public class MessageContentServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java index 6e7bc1d935..3920443b07 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java @@ -62,7 +62,7 @@ public class MessageServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2) @@ -400,7 +400,7 @@ public class MessageServlet extends AbstractServlet * POST moves or copies messages to the given queue from a queue specified in the posted JSON data */ @Override - protected void onPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try @@ -450,7 +450,7 @@ public class MessageServlet extends AbstractServlet * DELETE removes messages from the queue */ @Override - protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) { final Queue sourceQueue = getQueueFromRequest(request); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 6a79916d07..f2ca25d664 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -31,7 +31,6 @@ import org.apache.qpid.server.model.*; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; - public class RestServlet extends AbstractServlet { private static final Logger LOGGER = Logger.getLogger(RestServlet.class); @@ -285,7 +284,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -319,7 +318,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); @@ -336,7 +335,8 @@ public class RestServlet extends AbstractServlet if(names.size() != _hierarchy.length) { - throw new IllegalArgumentException("Path to object to create must be fully specified"); + throw new IllegalArgumentException("Path to object to create must be fully specified. " + + "Found " + names.size() + " expecting " + _hierarchy.length); } } @@ -428,8 +428,11 @@ public class RestServlet extends AbstractServlet || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents))) { doUpdate(obj, providedObject); + response.setStatus(HttpServletResponse.SC_OK); + return; } } + theParent.createChild(objClass, providedObject, otherParents); } catch (RuntimeException e) @@ -464,11 +467,12 @@ public class RestServlet extends AbstractServlet { if (e.getCause() instanceof AMQSecurityException) { + LOGGER.debug("Caught AMQSecurityException", e); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } else { - LOGGER.warn("Unexpected exception is caught", e); + LOGGER.warn("Caught exception", e); // TODO response.setStatus(HttpServletResponse.SC_CONFLICT); @@ -476,7 +480,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java index 1b78611a50..b5929875ff 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java @@ -27,8 +27,8 @@ import org.codehaus.jackson.map.SerializationConfig; import org.apache.log4j.Logger; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import javax.security.auth.Subject; import javax.security.sasl.SaslException; @@ -67,7 +67,7 @@ public class SaslServlet extends AbstractServlet super(broker); } - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -79,15 +79,16 @@ public class SaslServlet extends AbstractServlet response.setDateHeader ("Expires", 0); HttpSession session = request.getSession(); - Random rand = getRandom(session); + getRandom(session); - AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request)); - String[] mechanisms = authManager.getMechanisms().split(" "); + SubjectCreator subjectCreator = ApplicationRegistry.getInstance().getSubjectCreator(getSocketAddress(request)); + String[] mechanisms = subjectCreator.getMechanisms().split(" "); Map<String, Object> outputObject = new LinkedHashMap<String, Object>(); - final Subject subject = (Subject) session.getAttribute("subject"); + + final Subject subject = getSubjectFromSession(session); if(subject != null) { - final Principal principal = subject.getPrincipals().iterator().next(); + Principal principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); outputObject.put("user", principal.getName()); } else if (request.getRemoteUser() != null) @@ -121,8 +122,7 @@ public class SaslServlet extends AbstractServlet @Override - protected void onPost(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException + protected void doPostWithSubjectAndActor(final HttpServletRequest request, final HttpServletResponse response) throws IOException { try { @@ -137,14 +137,14 @@ public class SaslServlet extends AbstractServlet String id = request.getParameter("id"); String saslResponse = request.getParameter("response"); - AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request)); + SubjectCreator subjectCreator = ApplicationRegistry.getInstance().getSubjectCreator(getSocketAddress(request)); if(mechanism != null) { if(id == null) { - SaslServer saslServer = authManager.createSaslServer(mechanism, request.getServerName(), null/*TODO*/); - evaluateSaslResponse(response, session, saslResponse, saslServer); + SaslServer saslServer = subjectCreator.createSaslServer(mechanism, request.getServerName(), null/*TODO*/); + evaluateSaslResponse(response, session, saslResponse, saslServer, subjectCreator); } else { @@ -152,9 +152,7 @@ public class SaslServlet extends AbstractServlet session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - } - } else { @@ -163,8 +161,7 @@ public class SaslServlet extends AbstractServlet if(id.equals(session.getAttribute(ATTR_ID)) && System.currentTimeMillis() < (Long) session.getAttribute(ATTR_EXPIRY)) { SaslServer saslServer = (SaslServer) session.getAttribute(ATTR_SASL_SERVER); - evaluateSaslResponse(response, session, saslResponse, saslServer); - + evaluateSaslResponse(response, session, saslResponse, saslServer, subjectCreator); } else { @@ -180,7 +177,6 @@ public class SaslServlet extends AbstractServlet session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - } } } @@ -199,7 +195,7 @@ public class SaslServlet extends AbstractServlet private void evaluateSaslResponse(final HttpServletResponse response, final HttpSession session, - final String saslResponse, final SaslServer saslServer) throws IOException + final String saslResponse, final SaslServer saslServer, SubjectCreator subjectCreator) throws IOException { final String id; byte[] challenge; @@ -209,7 +205,6 @@ public class SaslServlet extends AbstractServlet } catch(SaslException e) { - session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); @@ -220,16 +215,14 @@ public class SaslServlet extends AbstractServlet if(saslServer.isComplete()) { - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal(saslServer.getAuthorizationID())); - session.setAttribute("subject", subject); + Subject subject = subjectCreator.createSubjectWithGroups(saslServer.getAuthorizationID()); + + setSubjectInSession(subject, session); session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); response.setStatus(HttpServletResponse.SC_OK); - - } else { @@ -250,7 +243,6 @@ public class SaslServlet extends AbstractServlet ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); mapper.writeValue(writer, outputObject); - } } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java index 60f977ca66..5f553beb26 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java @@ -47,7 +47,7 @@ public class StructureServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -56,6 +56,8 @@ public class StructureServlet extends AbstractServlet response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); + // TODO filtering??? request.getParameter("filter"); // filter=1,2,3 /groups/*/* + Map<String,Object> structure = generateStructure(getBroker(), Broker.class); final PrintWriter writer = response.getWriter(); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html index baadc8c35f..e6c067fddf 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html @@ -23,7 +23,5 @@ <div class="users"></div> <button data-dojo-type="dijit.form.Button" class="addUserButton">Add User</button> <button data-dojo-type="dijit.form.Button" class="deleteUserButton">Delete Users</button> - </div> - </div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html new file mode 100644 index 0000000000..0372468f91 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html @@ -0,0 +1,37 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you 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. + - + --> +<div class="dijitHidden"> + <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Group Member'" id="addGroupMember"> + <form id="formAddGroupMember" method="post" dojoType="dijit.form.Form"> + <table cellpadding="0" cellspacing="2"> + <tr> + <td valign="top"><strong>Name*: </strong></td> + <td><input type="text" required="true" name="name" id="formAddGroupMember.name" placeholder="Name" + dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td> + </tr> + </table> + <br/> + + <!-- submit buttons --> + <input type="submit" value="Add Group Member" label="Add Group Member" dojoType="dijit.form.Button" /> + </form> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html new file mode 100644 index 0000000000..4fddf727d0 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html @@ -0,0 +1,30 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you 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. + - + --> +<div class="group"> + <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span> + <br/> + <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Group Members'"> + <div class="groupMembers"></div> + <button data-dojo-type="dijit.form.Button" class="addGroupMemberButton" type="button">Add Group Member</button> + <button data-dojo-type="dijit.form.Button" class="removeGroupMemberButton" type="button">Remove Group Members</button> + </div> +</div> + diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html new file mode 100644 index 0000000000..8d3431808a --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html @@ -0,0 +1,38 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you 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. + - + --> +<div class="dijitHidden"> + <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Group'" id="addGroup"> + <form id="formAddGroup" method="post" dojoType="dijit.form.Form"> + <table cellpadding="0" cellspacing="2"> + <tr> + <td valign="top"><strong>Group Name*: </strong></td> + <td><input type="text" required="true" name="name" id="formAddGroup.name" placeholder="Group Name" + dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td> + </tr> + </table> + <br/> + + <!-- submit buttons --> + <input type="submit" value="Create Group" label="Create Group" dojoType="dijit.form.Button" /> + + </form> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html new file mode 100644 index 0000000000..734e8b5419 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html @@ -0,0 +1,28 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you 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. + - + --> +<div class="FileGroupManager"> + <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Groups'"> + <div class="groups"></div> + <button data-dojo-type="dijit.form.Button" class="addGroupButton">Add Group</button> + <button data-dojo-type="dijit.form.Button" class="deleteGroupButton">Delete Groups</button> + </div> + +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index 08fdf5c99b..5557c37a2c 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -58,10 +58,10 @@ define(["dojo/_base/xhr"], return exchangeName == null || exchangeName == "" || "<<default>>" == exchangeName || exchangeName.indexOf("amq.") == 0 || exchangeName.indexOf("qpid.") == 0; }; - util.deleteGridSelections = function(updater, gridName, url, confirmationMessageStart) + util.deleteGridSelections = function(updater, grid, url, confirmationMessageStart) { - var grid = updater[gridName].grid; var data = grid.selection.getSelected(); + if(data.length) { var confirmationMessage = null; @@ -103,7 +103,8 @@ define(["dojo/_base/xhr"], xhr.del({url: query, sync: true, handleAs: "json"}).then( function(data) { - grid.setQuery({id: "*"}); + // TODO why query *?? + //grid.setQuery({id: "*"}); grid.selection.deselectAll(); updater.update(); }, diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js index 37bae1ef8e..5a5a6515ef 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js @@ -115,7 +115,7 @@ define(["dojo/_base/xhr", { util.deleteGridSelections( this.exchangeUpdater, - "bindingsGrid", + that.exchangeUpdater.bindingsGrid.grid, "rest/binding/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name), "Are you sure you want to delete binding for queue"); } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js new file mode 100644 index 0000000000..4e05f4b0ea --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dojo/_base/connect", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid) { + + function GroupProvider(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "groupprovider", name: name }; + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + GroupProvider.prototype.getTitle = function() { + return "GroupProvider"; + }; + + GroupProvider.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + xhr.get({url: "showGroupProvider.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.groupProviderAdapter = new GroupProviderUpdater(contentPane.containerNode, that.modelObj, that.controller); + + updater.add( that.groupProviderAdapter ); + + that.groupProviderAdapter.update(); + + }}); + }; + + GroupProvider.prototype.close = function() { + updater.remove( this.groupProviderAdapter ); + }; + + function GroupProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.name = query(".name", node)[0]; + this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) + { + that.groupProviderData = data[0]; + + util.flattenStatistics( that.groupProviderData ); + + that.updateHeader(); + + require(["qpid/management/groupprovider/"+that.groupProviderData.type], + function(SpecificProvider) { + that.details = new SpecificProvider(node, groupProviderObj, controller); + that.details.update(); + }); + + }); + + } + + GroupProviderUpdater.prototype.updateHeader = function() + { + this.name.innerHTML = this.groupProviderData[ "name" ]; + }; + + GroupProviderUpdater.prototype.update = function() + { + var that = this; + }; + + return GroupProvider; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js index 957f2381cf..2efc46476d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js @@ -72,7 +72,7 @@ define(["dojo/_base/xhr", function(evt){ util.deleteGridSelections( that.vhostUpdater, - "queuesGrid", + that.vhostUpdater.queuesGrid.grid, "rest/queue/"+ encodeURIComponent(that.name), "Are you sure you want to delete queue"); } @@ -87,7 +87,7 @@ define(["dojo/_base/xhr", { util.deleteGridSelections( that.vhostUpdater, - "exchangesGrid", + that.vhostUpdater.exchangesGrid.grid, "rest/exchange/"+ encodeURIComponent(that.name), "Are you sure you want to delete exchange"); } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js index 1aa05a5a3c..5d3a666760 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js @@ -27,13 +27,17 @@ define(["dojo/dom", "qpid/management/Queue", "qpid/management/Connection", "qpid/management/AuthenticationProvider", + "qpid/management/GroupProvider", + "qpid/management/group/Group", "dojo/ready", "dojo/domReady!"], - function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, ready) { + function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, ready) { var controller = {}; var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange, - queue: Queue, connection: Connection, authenticationprovider: AuthProvider }; + queue: Queue, connection: Connection, + authenticationprovider: AuthProvider, groupprovider: GroupProvider, + group: Group }; var tabDiv = dom.byId("managedViews"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js new file mode 100644 index 0000000000..801f35c7aa --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js @@ -0,0 +1,215 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dijit/registry", + "dojo/_base/connect", + "dojo/_base/event", + "dojo/json", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/formatter", + "qpid/common/UpdatableStore", + "dojo/store/JsonRest", + "dojox/grid/EnhancedGrid", + "dojo/data/ObjectStore", + "qpid/management/group/addGroupMember", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, registry, connect, event, json, properties, updater, util, formatter, + UpdatableStore, JsonRest, EnhancedGrid, ObjectStore, addGroupMember) { + + function Group(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "group", name: name }; + + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + Group.prototype.getGroupName = function() + { + return this.name; + }; + + + Group.prototype.getGroupProviderName = function() + { + return this.modelObj.parent.groupprovider.name; + }; + + Group.prototype.getTitle = function() + { + return "Group: " + this.name; + }; + + Group.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + + xhr.get({url: "group/showGroup.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.groupUpdater = new GroupUpdater(contentPane.containerNode, that, that.controller); + + updater.add( that.groupUpdater ); + + that.groupUpdater.update(); + + var addGroupMemberButton = query(".addGroupMemberButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(addGroupMemberButton), "onClick", + function(evt){ + addGroupMember.show(that.getGroupProviderName(), that.getGroupName()) + } + ); + + var removeGroupMemberButton = query(".removeGroupMemberButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(removeGroupMemberButton), "onClick", + function(evt){ + util.deleteGridSelections( + that.groupUpdater, + that.groupUpdater.groupMembersUpdatableStore.grid, + "rest/groupmember/"+ encodeURIComponent(that.getGroupProviderName()) + + "/" + encodeURIComponent(that.getGroupName()), + "Are you sure you want to remove group member"); + } + ); + }}); + }; + + Group.prototype.close = function() { + updater.remove( this.groupUpdater ); + }; + + function GroupUpdater(containerNode, groupObj, controller) + { + var that = this; + + function findNode(name) { + return query("." + name, containerNode)[0]; + } + + function storeNodes(names) + { + for(var i = 0; i < names.length; i++) { + that[names[i]] = findNode(names[i]); + } + } + + storeNodes(["name", + "state", + "durable", + "lifetimePolicy", + "type"]); + + this.query = "rest/groupmember/"+ encodeURIComponent(groupObj.getGroupProviderName()) + "/" + encodeURIComponent(groupObj.getGroupName()); + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) + { + that.groupMemberData = data; + + util.flattenStatistics( that.groupMemberData ); + + var gridProperties = { + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + + that.groupMembersUpdatableStore = new UpdatableStore(that.groupMemberData, findNode("groupMembers"), + [ { name: "Group Member Name", field: "name", width: "100%" }], + function(obj) + { + connect.connect(obj.grid, "onRowDblClick", obj.grid, + function(evt){ + + }); + } , gridProperties, EnhancedGrid); + + }); + + } + + GroupUpdater.prototype.update = function() + { + + var that = this; + + console.log("updater called "); + console.dir(that); + + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupMemberData = data; + + console.log("updater data "); + console.dir(that.groupMemberData); + + + util.flattenStatistics( that.groupMemberData ); + + that.groupMembersUpdatableStore.update(that.groupMemberData); + + console.log("updated grid"); + console.dir(that.groupMembersUpdatableStore.grid); + }); + }; + + Group.prototype.deleteGroupMember = function() { + if(confirm("Are you sure you want to delete group member'" +this.name+"'?")) { + var query = "rest/groupmember/"+ encodeURIComponent(this.getGroupProviderName()) + "/" + encodeURIComponent(this.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + } + + return Group; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js new file mode 100644 index 0000000000..1861cc6ffe --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/dom-construct", + "dojo/_base/window", + "dijit/registry", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/event", + 'dojo/_base/json', + "dijit/form/NumberSpinner", // required by the form + /* dojox/ validate resources */ + "dojox/validate/us", "dojox/validate/web", + /* basic dijit classes */ + "dijit/Dialog", + "dijit/form/CheckBox", "dijit/form/Textarea", + "dijit/form/FilteringSelect", "dijit/form/TextBox", + "dijit/form/ValidationTextBox", "dijit/form/DateTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/RadioButton", "dijit/form/Form", + "dijit/form/DateTextBox", + /* basic dojox classes */ + "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect", + "dojo/domReady!"], + function (xhr, dom, construct, win, registry, parser, array, event, json) { + + var addGroupMember = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToGroupMember = function convertToGroupMember(formValues) + { + var newGroupMember = {}; + newGroupMember.name = formValues.name; + return newGroupMember; + }; + + xhr.get({url: "group/addGroupMember.html", + sync: true, + load: function(data) { + var theForm; + node.innerHTML = data; + addGroupMember.dialogNode = dom.byId("addGroupMember"); + parser.instantiate([addGroupMember.dialogNode]); + + theForm = registry.byId("formAddGroupMember"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + + var newGroupMember = convertToGroupMember(theForm.getValues()); + var that = this; + xhr.put({url: "rest/groupmember/"+encodeURIComponent(addGroupMember.groupProvider) + + "/" + encodeURIComponent(addGroupMember.group) + "/" + encodeURIComponent(newGroupMember.name), sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newGroupMember), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + + if(this.success === true) + { + registry.byId("addGroupMember").hide(); + } + else + { + alert("Error:" + this.failureReason); + } + + return false; + + + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + + }); + }}); + + addGroupMember.show = function(groupProvider, group) { + addGroupMember.groupProvider = groupProvider; + addGroupMember.group = group; + registry.byId("formAddGroupMember").reset(); + registry.byId("addGroupMember").show(); + }; + + return addGroupMember; + });
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js new file mode 100644 index 0000000000..44fc9702e2 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js @@ -0,0 +1,251 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/parser", + "dojo/query", + "dojo/dom-construct", + "dojo/_base/connect", + "dojo/_base/window", + "dojo/_base/event", + "dojo/_base/json", + "dijit/registry", + "qpid/common/util", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojox/validate/us", "dojox/validate/web", + "dijit/Dialog", + "dijit/form/TextBox", + "dijit/form/ValidationTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/Form", + "dijit/form/DateTextBox", + "dojo/domReady!"], + function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) { + function DatabaseGroupManager(containerNode, groupProviderObj, controller) { + var node = construct.create("div", null, containerNode, "last"); + var that = this; + this.name = groupProviderObj.name; + xhr.get({url: "groupprovider/showFileGroupManager.html", + sync: true, + load: function(data) { + node.innerHTML = data; + parser.parse(node); + + + that.groupDatabaseUpdater= new GroupProviderUpdater(node, groupProviderObj, controller); + + updater.add( that.groupDatabaseUpdater); + + that.groupDatabaseUpdater.update(); + + + }}); + } + + DatabaseGroupManager.prototype.update = function() { + this.groupDatabaseUpdater.update(); + }; + + DatabaseGroupManager.prototype.close = function() { + updater.remove( this.groupDatabaseUpdater ); + }; + + function GroupProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); + this.name = groupProviderObj.name; + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupProviderData = data[0]; + + util.flattenStatistics( that.groupProviderData ); + + var groupDiv = query(".groups")[0]; + + var gridProperties = { + height: 400, + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + + + that.groupsGrid = + new UpdatableStore(that.groupProviderData.groups, groupDiv, + [ { name: "Group Name", field: "name", width: "100%" } + ], null, gridProperties, EnhancedGrid); + + + var addGroupButton = query(".addGroupButton", node)[0]; + connect.connect(registry.byNode(addGroupButton), "onClick", function(evt){ addGroup.show(groupProviderObj.name) }); + + var deleteMessagesButton = query(".deleteGroupButton", node)[0]; + var deleteWidget = registry.byNode(deleteMessagesButton); + connect.connect(deleteWidget, "onClick", + function(evt){ + event.stop(evt); + that.deleteGroups(); + }); + }); + } + + GroupProviderUpdater.prototype.deleteGroups = function() + { + var grid = this.groupsGrid.grid; + var data = grid.selection.getSelected(); + if(data.length) { + var that = this; + if(confirm("Delete " + data.length + " groups?")) { + var i, queryParam; + for(i = 0; i<data.length; i++) { + if(queryParam) { + queryParam += "&"; + } else { + queryParam = "?"; + } + + queryParam += "id=" + data[i].id; + } + var query = "rest/group/"+ encodeURIComponent(that.name) + + queryParam; + that.success = true + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + grid.setQuery({id: "*"}); + grid.selection.deselectAll(); + that.update(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!that.success ) { + alert("Error:" + this.failureReason); + } + } +} + }; + + GroupProviderUpdater.prototype.update = function() + { + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupProviderData = data[0]; + util.flattenStatistics( that.groupProviderData ); + + that.groupsGrid.update(that.groupProviderData.groups); + + }); + + + }; + + var addGroup = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToGroup = function convertToGroup(formValues) { + var newGroup = {}; + newGroup.name = formValues.name; + for(var propName in formValues) + { + if(formValues.hasOwnProperty(propName)) { + if(formValues[ propName ] !== "") { + newGroup[ propName ] = formValues[propName]; + } + } + } + + return newGroup; + }; + + + xhr.get({url: "groupprovider/addGroup.html", + sync: true, + load: function(data) { + var theForm; + node.innerHTML = data; + addGroup.dialogNode = dom.byId("addGroup"); + parser.instantiate([addGroup.dialogNode]); + + var that = this; + + theForm = registry.byId("formAddGroup"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + + var newGroup = convertToGroup(theForm.getValues()); + + + var url = "rest/group/"+encodeURIComponent(addGroup.groupProvider) + + "/"+encodeURIComponent(newGroup.name); + + xhr.put({url: url, sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newGroup), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + + if(that.success === true) { + registry.byId("addGroup").hide(); + } else { + alert("Error:" + that.failureReason); + } + + return false; + + + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + + }); + }}); + + addGroup.show = function(groupProvider) { + addGroup.groupProvider = groupProvider; + registry.byId("formAddGroup").reset(); + registry.byId("addGroup").show(); + }; + + return DatabaseGroupManager; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js index b1d4abf8c1..59356cfce1 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js @@ -273,10 +273,12 @@ define(["dojo/_base/xhr", controller.show("port", details.port, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}}); } else if (details.type == 'authenticationprovider') { controller.show("authenticationprovider", details.authenticationprovider, {broker: {type:"broker", name:""}}); + } else if (details.type == 'groupprovider') { + controller.show("groupprovider", details.groupprovider, {broker: {type:"broker", name:""}}); + } else if (details.type == 'group') { + controller.show("group", details.group, { type: "groupprovider", name: details.groupprovider, parent: {broker: {type:"broker", name:""}}}); } - - }; TreeViewModel.prototype.update = function () { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html new file mode 100644 index 0000000000..914857db5c --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html @@ -0,0 +1,25 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you 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. + - + --> +<div class="groupProvider"> + <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span> + <br/> + <span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span> +</div>
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java index 5e6d9a998a..86533b76b4 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java @@ -33,13 +33,13 @@ public class AuthenticationProviderRestTest extends QpidRestTestCase public void testGet() throws Exception { - List<Map<String, Object>> providerDetails = getJsonAsList("/rest/authenticationprovider"); + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider"); assertNotNull("Providers details cannot be null", providerDetails); assertEquals("Unexpected number of providers", 1, providerDetails.size()); for (Map<String, Object> provider : providerDetails) { assertProvider("PrincipalDatabaseAuthenticationManager", provider); - Map<String, Object> data = getJsonAsSingletonList("/rest/authenticationprovider/" + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/authenticationprovider/" + provider.get(AuthenticationProvider.NAME)); assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data); assertProvider("PrincipalDatabaseAuthenticationManager", data); diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java index 1ed0d97185..c2f11ed237 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java @@ -32,7 +32,7 @@ public class BindingRestTest extends QpidRestTestCase public void testGetAllBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding"); assertNotNull("Bindings cannot be null", bindings); assertTrue("Unexpected number of bindings", bindings.size() >= EXPECTED_HOSTS.length * EXPECTED_QUEUES.length); for (Map<String, Object> binding : bindings) @@ -43,7 +43,7 @@ public class BindingRestTest extends QpidRestTestCase public void testGetVirtualHostBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length * 2, bindings.size()); for (String queueName : EXPECTED_QUEUES) @@ -52,31 +52,31 @@ public class BindingRestTest extends QpidRestTestCase searchAttributes.put(Binding.NAME, queueName); searchAttributes.put(Binding.EXCHANGE, "amq.direct"); - Map<String, Object> binding = find(searchAttributes, bindings); + Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); Asserts.assertBinding(queueName, "amq.direct", binding); searchAttributes.put(Binding.EXCHANGE, "<<default>>"); - binding = find(searchAttributes, bindings); + binding = getRestTestHelper().find(searchAttributes, bindings); Asserts.assertBinding(queueName, "<<default>>", binding); } } public void testGetVirtualHostExchangeBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size()); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> binding = find(Binding.NAME, queueName, bindings); + Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); Asserts.assertBinding(queueName, "amq.direct", binding); } } public void testGetVirtualHostExchangeQueueBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", 1, bindings.size()); Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); @@ -85,25 +85,25 @@ public class BindingRestTest extends QpidRestTestCase public void testDeleteBinding() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); assertEquals("Unexpected number of bindings", 1, bindings.size()); Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); assertEquals("Binding should be deleted", 0, bindings.size()); } public void testDeleteBindingById() throws Exception { - Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); assertEquals("Binding should be deleted", 0, bindings.size()); } @@ -115,13 +115,13 @@ public class BindingRestTest extends QpidRestTestCase bindingData.put(Binding.QUEUE, "queue"); bindingData.put(Binding.EXCHANGE, "amq.direct"); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); connection.connect(); - writeJsonRequest(connection, bindingData); + getRestTestHelper().writeJsonRequest(connection, bindingData); int responseCode = connection.getResponseCode(); connection.disconnect(); assertEquals("Unexpected response code", 201, responseCode); - Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java index 4bbe9155cd..08b5863004 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java @@ -21,13 +21,8 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; import java.util.Map; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; - import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.Broker; @@ -48,37 +43,16 @@ public class BrokerRestHttpsTest extends QpidRestTestCase @Override protected void customizeConfiguration() throws ConfigurationException, IOException { + getRestTestHelper().setUseSsl(true); setConfigurationProperty("management.enabled", "true"); setConfigurationProperty("management.http.enabled", "false"); setConfigurationProperty("management.https.enabled", "true"); - setConfigurationProperty("management.https.port", Integer.toString(getHttpPort())); - } - - @Override - protected String getHostName() - { - return "localhost"; - } - - @Override - protected String getProtocol() - { - return "https"; - } - - @Override - protected HttpURLConnection openManagementConection(String path) throws IOException - { - URL url = getManagementURL(path); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - ((HttpsURLConnection) httpCon).setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); - httpCon.setDoOutput(true); - return httpCon; + setConfigurationProperty("management.https.port", Integer.toString(getRestTestHelper().getHttpPort())); } public void testGetWithHttps() throws Exception { - Map<String, Object> brokerDetails = getJsonAsSingletonList("/rest/broker"); + Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED); diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java index f2970e2ba9..c4cd00416b 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java @@ -43,7 +43,7 @@ public class BrokerRestTest extends QpidRestTestCase public void testGet() throws Exception { - Map<String, Object> brokerDetails = getJsonAsSingletonList("/rest/broker"); + Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); assertBrokerAttributes(brokerDetails); @@ -55,9 +55,9 @@ public class BrokerRestTest extends QpidRestTestCase List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE); assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); - Asserts.assertVirtualHost("development", find(VirtualHost.NAME, "development", virtualhosts)); - Asserts.assertVirtualHost("localhost", find(VirtualHost.NAME, "localhost", virtualhosts)); - Asserts.assertVirtualHost("test", find(VirtualHost.NAME, "test", virtualhosts)); + Asserts.assertVirtualHost("development", getRestTestHelper().find(VirtualHost.NAME, "development", virtualhosts)); + Asserts.assertVirtualHost("localhost", getRestTestHelper().find(VirtualHost.NAME, "localhost", virtualhosts)); + Asserts.assertVirtualHost("test", getRestTestHelper().find(VirtualHost.NAME, "test", virtualhosts)); @SuppressWarnings("unchecked") List<Map<String, Object>> ports = (List<Map<String, Object>>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE); @@ -70,8 +70,8 @@ public class BrokerRestTest extends QpidRestTestCase String bindingAddress = (String)ports.get(0).get(Port.BINDING_ADDRESS); - Map<String, Object> amqpPort = find(Port.NAME, bindingAddress + ":" + getPort(), ports); - Map<String, Object> httpPort = find(Port.NAME, bindingAddress + ":" + getHttpPort(), ports); + Map<String, Object> amqpPort = getRestTestHelper().find(Port.NAME, bindingAddress + ":" + getPort(), ports); + Map<String, Object> httpPort = getRestTestHelper().find(Port.NAME, bindingAddress + ":" + getRestTestHelper().getHttpPort(), ports); assertNotNull("Cannot find AMQP port", amqpPort); assertNotNull("Cannot find HTTP port", httpPort); diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java index 3661b94a7c..500a5770fb 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java @@ -90,14 +90,14 @@ public class ConnectionRestTest extends QpidRestTestCase public void testGetAllConnections() throws Exception { - List<Map<String, Object>> connections = getJsonAsList("/rest/connection"); + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection"); assertEquals("Unexpected number of connections", 1, connections.size()); Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); } public void testGetVirtualHostConnections() throws Exception { - List<Map<String, Object>> connections = getJsonAsList("/rest/connection/test"); + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection/test"); assertEquals("Unexpected number of connections", 1, connections.size()); Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); } @@ -107,21 +107,21 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - Map<String, Object> connectionDetails = getJsonAsSingletonList("/rest/connection/test/" + Map<String, Object> connectionDetails = getRestTestHelper().getJsonAsSingletonList("/rest/connection/test/" + URLDecoder.decode(connectionName, "UTF-8")); assertConnection(connectionDetails); } public void testGetAllSessions() throws Exception { - List<Map<String, Object>> sessions = getJsonAsList("/rest/session"); + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session"); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); } public void testGetVirtualHostSessions() throws Exception { - List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test"); + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test"); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); } @@ -131,7 +131,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test/" + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + URLDecoder.decode(connectionName, "UTF-8")); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); @@ -142,7 +142,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test/" + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession<?, ?>) _session).getChannelId()); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); @@ -201,7 +201,7 @@ public class ConnectionRestTest extends QpidRestTestCase private String getConnectionName() throws IOException { - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE); diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java index 4904d2adf3..363652d37c 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java @@ -31,7 +31,7 @@ public class ExchangeRestTest extends QpidRestTestCase { public void testGet() throws Exception { - List<Map<String, Object>> exchanges = getJsonAsList("/rest/exchange"); + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange"); assertNotNull("Exchanges cannot be null", exchanges); assertTrue("Unexpected number of exchanges", exchanges.size() >= EXPECTED_HOSTS.length * EXPECTED_EXCHANGES.length); for (Map<String, Object> exchange : exchanges) @@ -42,12 +42,12 @@ public class ExchangeRestTest extends QpidRestTestCase public void testGetHostExchanges() throws Exception { - List<Map<String, Object>> exchanges = getJsonAsList("/rest/exchange/test"); + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange/test"); assertNotNull("Users cannot be null", exchanges); assertEquals("Unexpected number of exchanges", 6, EXPECTED_EXCHANGES.length); for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = find(Exchange.NAME, exchangeName, exchanges); + Map<String, Object> exchange = getRestTestHelper().find(Exchange.NAME, exchangeName, exchanges); assertExchange(exchangeName, exchange); } } @@ -56,7 +56,7 @@ public class ExchangeRestTest extends QpidRestTestCase { for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = getJsonAsSingletonList("/rest/exchange/test/" + Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + URLDecoder.decode(exchangeName, "UTF-8")); assertExchange(exchangeName, exchange); } @@ -79,7 +79,7 @@ public class ExchangeRestTest extends QpidRestTestCase List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> binding = find(Binding.NAME, queueName, bindings); + Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding); } } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupProviderRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupProviderRestTest.java new file mode 100644 index 0000000000..c2eefec395 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupProviderRestTest.java @@ -0,0 +1,160 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.UUIDGenerator; + +public class GroupProviderRestTest extends QpidRestTestCase +{ + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + public void testGet() throws Exception + { + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/groupprovider"); + assertNotNull("Providers details cannot be null", providerDetails); + assertEquals("Unexpected number of providers", 1, providerDetails.size()); + for (Map<String, Object> provider : providerDetails) + { + assertProvider(FILE_GROUP_MANAGER, provider); + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + + provider.get(GroupProvider.NAME)); + assertNotNull("Cannot load data for " + provider.get(GroupProvider.NAME), data); + assertProvider(FILE_GROUP_MANAGER, data); + } + } + + public void testCreateNewGroup() throws Exception + { + String groupName = "newGroup"; + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 1); + + getRestTestHelper().createGroup(groupName, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 2); + } + + public void testRemoveGroup() throws Exception + { + String groupName = "myGroup"; + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 1); + + getRestTestHelper().removeGroup(groupName, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 0); + } + + + private void assertProvider(String type, Map<String, Object> provider) + { + Asserts.assertAttributesPresent(provider, GroupProvider.AVAILABLE_ATTRIBUTES, + GroupProvider.CREATED, GroupProvider.UPDATED, GroupProvider.DESCRIPTION, + GroupProvider.TIME_TO_LIVE); + assertEquals("Unexpected value of provider attribute " + GroupProvider.STATE, State.ACTIVE.name(), + provider.get(GroupProvider.STATE)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.LIFETIME_POLICY, + LifetimePolicy.PERMANENT.name(), provider.get(GroupProvider.LIFETIME_POLICY)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.DURABLE, Boolean.TRUE, + provider.get(GroupProvider.DURABLE)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.TYPE, type, + provider.get(GroupProvider.TYPE)); + + final String name = (String) provider.get(GroupProvider.NAME); + assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, type, + name); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) provider.get("groups"); + assertNotNull("Groups were not found", groups); + assertEquals("Unexpected number of groups", 1, groups.size()); + for (Map<String, Object> group : groups) + { + + final String groupName = (String) group.get(Group.NAME); + assertNotNull("Attribute " + Group.NAME, groupName); + + assertNotNull("Attribute " + Group.ID, group.get(Group.ID)); + assertEquals("Attribute " + Group.ID, UUIDGenerator.generateGroupUUID(name, groupName).toString(), group.get(Group.ID)); + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put("myGroup.users", "guest"); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupRestTest.java new file mode 100644 index 0000000000..5430cce6dc --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupRestTest.java @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.server.model.GroupMember; + +public class GroupRestTest extends QpidRestTestCase +{ + private static final String GROUP_NAME = "myGroup"; + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private static final String EXISTING_MEMBER = "user1"; + private static final String NEW_MEMBER = "user2"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + public void testGet() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + List<Map<String, Object>> groupmembers = (List<Map<String, Object>>) group.get("groupmembers"); + assertEquals(1, groupmembers.size()); + + Map<String, Object> member1 = groupmembers.get(0); + assertEquals(EXISTING_MEMBER, (String)member1.get(GroupMember.NAME)); + } + + public void testCreateNewMemberOfGroup() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER); + + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 2); + } + + public void testRemoveMemberFromGroup() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, GROUP_NAME, EXISTING_MEMBER); + + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 0); + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(GROUP_NAME + ".users", EXISTING_MEMBER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java index c64fd6e1da..34b25e2e40 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java @@ -27,10 +27,10 @@ public class LogRecordsRestTest extends QpidRestTestCase { public void testGet() throws Exception { - List<Map<String, Object>> logs = getJsonAsList("/rest/logrecords"); + List<Map<String, Object>> logs = getRestTestHelper().getJsonAsList("/rest/logrecords"); assertNotNull("Logs data cannot be null", logs); assertTrue("Logs are not found", logs.size() > 0); - Map<String, Object> record = find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs); + Map<String, Object> record = getRestTestHelper().find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs); assertNotNull("BRK-1004 message is not found", record); assertNotNull("Message id cannot be null", record.get("id")); diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java index 492df43957..a4efcc9456 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java @@ -85,7 +85,7 @@ public class MessagesRestTest extends QpidRestTestCase public void testGet() throws Exception { String queueName = getTestQueueName(); - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); int position = 0; @@ -111,7 +111,7 @@ public class MessagesRestTest extends QpidRestTestCase // get message IDs List<Long> ids = getMesssageIds(queueName); - Map<String, Object> message = getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0)); + Map<String, Object> message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0)); assertMessageAttributes(message); assertMessageAttributeValues(message, true); @@ -121,7 +121,7 @@ public class MessagesRestTest extends QpidRestTestCase assertEquals("Unexpected message header", 0, headers.get("index")); Long lastMessageId = ids.get(ids.size() - 1); - message = getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId); + message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId); assertMessageAttributes(message); assertEquals("Unexpected message attribute mimeType", "application/octet-stream", message.get("mimeType")); assertEquals("Unexpected message attribute size", 4, message.get("size")); @@ -132,10 +132,10 @@ public class MessagesRestTest extends QpidRestTestCase assertEquals("Unexpected message header", "value", bytesMessageHeader.get("test")); // get content - HttpURLConnection connection = openManagementConection("/rest/message-content/test/" + queueName + "/" + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message-content/test/" + queueName + "/" + lastMessageId, "GET"); connection.connect(); - byte[] data = readConnectionInputStream(connection); + byte[] data = getRestTestHelper().readConnectionInputStream(connection); assertTrue("Unexpected message", Arrays.equals(messageBytes, data)); } @@ -159,38 +159,38 @@ public class MessagesRestTest extends QpidRestTestCase } // move messages - HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST"); Map<String, Object> messagesData = new HashMap<String, Object>(); messagesData.put("messages", movedMessageIds); messagesData.put("destinationQueue", queueName2); messagesData.put("move", Boolean.TRUE); - writeJsonRequest(connection, messagesData); + getRestTestHelper().writeJsonRequest(connection, messagesData); assertEquals("Unexpected response code", 200, connection.getResponseCode()); // check messages on target queue - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName2); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size()); for (Long id : movedMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } // check messages on original queue - messages = getJsonAsList("/rest/message/test/" + queueName); + messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", ids.size(), messages.size()); for (Long id : ids) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } for (Long id : movedMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertNull("Moved message " + id + " is found on original queue", message); } } @@ -214,37 +214,37 @@ public class MessagesRestTest extends QpidRestTestCase } // copy messages - HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST"); Map<String, Object> messagesData = new HashMap<String, Object>(); messagesData.put("messages", copyMessageIds); messagesData.put("destinationQueue", queueName2); - writeJsonRequest(connection, messagesData); + getRestTestHelper().writeJsonRequest(connection, messagesData); assertEquals("Unexpected response code", 200, connection.getResponseCode()); // check messages on target queue - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName2); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size()); for (Long id : copyMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } // check messages on original queue - messages = getJsonAsList("/rest/message/test/" + queueName); + messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); for (Long id : ids) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } for (Long id : copyMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } } @@ -272,30 +272,30 @@ public class MessagesRestTest extends QpidRestTestCase } // delete messages - HttpURLConnection connection = openManagementConection( + HttpURLConnection connection = getRestTestHelper().openManagementConnection( "/rest/message/test/" + queueName + "?" + queryString.toString(), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); // check messages on queue - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", ids.size(), messages.size()); for (Long id : ids) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } for (Long id : deleteMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertNull("Message with id " + id + " was not deleted", message); } } private List<Long> getMesssageIds(String queueName) throws IOException, JsonParseException, JsonMappingException { - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); List<Long> ids = new ArrayList<Long>(); for (Map<String, Object> message : messages) { diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java index 739ef5c737..ea897881a9 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java @@ -30,14 +30,14 @@ public class PortRestTest extends QpidRestTestCase { public void testGet() throws Exception { - List<Map<String, Object>> ports = getJsonAsList("/rest/port/"); + List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/"); assertNotNull("Port data cannot be null", ports); assertEquals("Unexpected number of ports", 2, ports.size()); - int[] expectedPorts = { getPort(), getHttpPort() }; + int[] expectedPorts = { getPort(), getRestTestHelper().getHttpPort() }; for (int port : expectedPorts) { String portName = "0.0.0.0:" + port; - Map<String, Object> portData = find(Port.NAME, portName, ports); + Map<String, Object> portData = getRestTestHelper().find(Port.NAME, portName, ports); assertNotNull("Port " + portName + " is not found", portData); Asserts.assertPortAttributes(portData); } @@ -45,14 +45,14 @@ public class PortRestTest extends QpidRestTestCase public void testGetPort() throws Exception { - List<Map<String, Object>> ports = getJsonAsList("/rest/port/"); + List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/"); assertNotNull("Ports data cannot be null", ports); assertEquals("Unexpected number of ports", 2, ports.size()); for (Map<String, Object> portMap : ports) { String portName = (String) portMap.get(Port.NAME); assertNotNull("Port name attribute is not found", portName); - Map<String, Object> portData = getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8")); + Map<String, Object> portData = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8")); assertNotNull("Port " + portName + " is not found", portData); Asserts.assertPortAttributes(portData); } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java index e83341de80..958e68ab70 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java @@ -20,226 +20,50 @@ */ package org.apache.qpid.server.management.plugin.servlet.rest; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; public class QpidRestTestCase extends QpidBrokerTestCase { - private static final Logger LOGGER = Logger.getLogger(QpidRestTestCase.class); - public static final String[] EXPECTED_HOSTS = { "development", "test", "localhost" }; public static final String[] EXPECTED_QUEUES = { "queue", "ping" }; public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct", "amq.topic", "qpid.management", "<<default>>" }; - private int _httpPort; - private String _hostName; - private List<HttpURLConnection> _httpConnections; + private RestTestHelper _restTestHelper = new RestTestHelper(findFreePort()); @Override public void setUp() throws Exception { - _httpConnections = new ArrayList<HttpURLConnection>(); - _hostName = InetAddress.getLocalHost().getHostName(); - _httpPort = findFreePort(); customizeConfiguration(); super.setUp(); - - } - - protected void customizeConfiguration() throws ConfigurationException, IOException - { - setConfigurationProperty("management.enabled", "false"); - setConfigurationProperty("management.http.enabled", "true"); - setConfigurationProperty("management.https.enabled", "false"); - setConfigurationProperty("management.http.port", Integer.toString(_httpPort)); - } - - public void teearDown() throws Exception - { - for (HttpURLConnection connection : _httpConnections) - { - try - { - connection.disconnect(); - } - catch (Exception e) - { - // ignore - } - } - super.tearDown(); - } - - protected int getHttpPort() - { - return _httpPort; - } - - protected String getHostName() - { - return _hostName; - } - - protected String getProtocol() - { - return "http"; - } - - protected String getManagementURL() - { - return getProtocol() + "://" + getHostName() + ":" + getHttpPort(); - } - - protected URL getManagementURL(String path) throws MalformedURLException - { - return new URL(getManagementURL() + path); - } - - protected HttpURLConnection openManagementConection(String path) throws IOException - { - URL url = getManagementURL(path); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - return httpCon; - } - - protected HttpURLConnection openManagementConection(String path, String method) throws IOException - { - HttpURLConnection httpCon = openManagementConection(path); - httpCon.setRequestMethod(method); - return httpCon; } - protected List<Map<String, Object>> readJsonResponseAsList(HttpURLConnection connection) throws IOException, - JsonParseException, JsonMappingException - { - byte[] data = readConnectionInputStream(connection); - - ObjectMapper mapper = new ObjectMapper(); - - TypeReference<List<LinkedHashMap<String, Object>>> typeReference = new TypeReference<List<LinkedHashMap<String, Object>>>() - { - }; - List<Map<String, Object>> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); - return providedObject; - } - - protected Map<String, Object> readJsonResponseAsMap(HttpURLConnection connection) throws IOException, - JsonParseException, JsonMappingException - { - byte[] data = readConnectionInputStream(connection); - - ObjectMapper mapper = new ObjectMapper(); - - TypeReference<LinkedHashMap<String, Object>> typeReference = new TypeReference<LinkedHashMap<String, Object>>() - { - }; - Map<String, Object> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); - return providedObject; - } - - protected byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException - { - InputStream is = connection.getInputStream(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int len = -1; - while ((len = is.read(buffer)) != -1) - { - baos.write(buffer, 0, len); - } - if (LOGGER.isTraceEnabled()) - { - LOGGER.trace("RESPONSE:" + new String(baos.toByteArray())); - } - return baos.toByteArray(); - } - - protected void writeJsonRequest(HttpURLConnection connection, Map<String, Object> data) throws JsonGenerationException, - JsonMappingException, IOException - { - ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(connection.getOutputStream(), data); - } - - protected Map<String, Object> find(String name, Object value, List<Map<String, Object>> data) + @Override + protected void tearDown() throws Exception { - for (Map<String, Object> map : data) + try { - Object mapValue = map.get(name); - if (value.equals(mapValue)) - { - return map; - } + super.tearDown(); } - return null; - } - - protected Map<String, Object> find(Map<String, Object> searchAttributes, List<Map<String, Object>> data) - { - for (Map<String, Object> map : data) + finally { - boolean equals = true; - for (Map.Entry<String, Object> entry : searchAttributes.entrySet()) - { - Object mapValue = map.get(entry.getKey()); - if (!entry.getValue().equals(mapValue)) - { - equals = false; - break; - } - } - if (equals) - { - return map; - } + getRestTestHelper().tearDown(); } - return null; } - protected Map<String, Object> getJsonAsSingletonList(String path) throws IOException - { - List<Map<String, Object>> response = getJsonAsList(path); - - assertNotNull("Response cannot be null", response); - assertEquals("Unexpected response", 1, response.size()); - return response.get(0); - } - - protected List<Map<String, Object>> getJsonAsList(String path) throws IOException, JsonParseException, - JsonMappingException + protected void customizeConfiguration() throws ConfigurationException, IOException { - HttpURLConnection connection = openManagementConection(path, "GET"); - connection.connect(); - List<Map<String, Object>> response = readJsonResponseAsList(connection); - return response; + setConfigurationProperty("management.enabled", "false"); + setConfigurationProperty("management.http.enabled", "true"); + setConfigurationProperty("management.https.enabled", "false"); + setConfigurationProperty("management.http.port", Integer.toString(_restTestHelper.getHttpPort())); } - protected Map<String, Object> getJsonAsMap(String path) throws IOException + public RestTestHelper getRestTestHelper() { - HttpURLConnection connection = openManagementConection(path, "GET"); - connection.connect(); - Map<String, Object> response = readJsonResponseAsMap(connection); - return response; + return _restTestHelper; } } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java index 5f11b3fb1d..d7732af688 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java @@ -80,7 +80,7 @@ public class QueueRestTest extends QpidRestTestCase public void testGetVirtualHostQueues() throws Exception { String queueName = getTestQueueName(); - List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test"); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test"); assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size()); String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1]; System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length); @@ -88,7 +88,7 @@ public class QueueRestTest extends QpidRestTestCase for (String name : expectedQueues) { - Map<String, Object> queueDetails = find(Queue.NAME, name, queues); + Map<String, Object> queueDetails = getRestTestHelper().find(Queue.NAME, name, queues); Asserts.assertQueue(name, "standard", queueDetails); @SuppressWarnings("unchecked") @@ -96,8 +96,8 @@ public class QueueRestTest extends QpidRestTestCase assertNotNull("Queue bindings are not found", bindings); assertEquals("Unexpected number of bindings", 2, bindings.size()); - Map<String, Object> defaultExchangeBinding = find(Binding.EXCHANGE, "<<default>>", bindings); - Map<String, Object> directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings); + Map<String, Object> defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<<default>>", bindings); + Map<String, Object> directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings); Asserts.assertBinding(name, "<<default>>", defaultExchangeBinding); Asserts.assertBinding(name, "amq.direct", directExchangeBinding); } @@ -106,7 +106,7 @@ public class QueueRestTest extends QpidRestTestCase public void testGetByName() throws Exception { String queueName = getTestQueueName(); - Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); Asserts.assertQueue(queueName, "standard", queueDetails); assertStatistics(queueDetails); @@ -115,8 +115,8 @@ public class QueueRestTest extends QpidRestTestCase assertNotNull("Queue bindings are not found", bindings); assertEquals("Unexpected number of bindings", 2, bindings.size()); - Map<String, Object> defaultExchangeBinding = find(Binding.EXCHANGE, "<<default>>", bindings); - Map<String, Object> directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings); + Map<String, Object> defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<<default>>", bindings); + Map<String, Object> directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings); Asserts.assertBinding(queueName, "<<default>>", defaultExchangeBinding); Asserts.assertBinding(queueName, "amq.direct", directExchangeBinding); @@ -138,7 +138,7 @@ public class QueueRestTest extends QpidRestTestCase createBinding(bindingName, exchanges[i], queueName); } - Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); Asserts.assertQueue(queueName, "standard", queueDetails); @SuppressWarnings("unchecked") @@ -152,14 +152,14 @@ public class QueueRestTest extends QpidRestTestCase for (int i = 0; i < exchanges.length; i++) { searchAttributes.put(Binding.EXCHANGE, exchanges[i]); - Map<String, Object> binding = find(searchAttributes, bindings); + Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); Asserts.assertBinding(bindingName, queueName, exchanges[i], binding); } } private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException { - HttpURLConnection connection = openManagementConection( + HttpURLConnection connection = getRestTestHelper().openManagementConnection( "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName, "PUT"); @@ -168,7 +168,7 @@ public class QueueRestTest extends QpidRestTestCase bindingData.put(Binding.EXCHANGE, exchangeName); bindingData.put(Binding.QUEUE, queueName); - writeJsonRequest(connection, bindingData); + getRestTestHelper().writeJsonRequest(connection, bindingData); assertEquals("Unexpected response code", 201, connection.getResponseCode()); connection.disconnect(); diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestTestHelper.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestTestHelper.java new file mode 100644 index 0000000000..8a323c0639 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestTestHelper.java @@ -0,0 +1,417 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; +import javax.servlet.http.HttpServletResponse; + +import junit.framework.Assert; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; + +public class RestTestHelper +{ + private static final Logger LOGGER = Logger.getLogger(RestTestHelper.class); + + private int _httpPort; + + private boolean _useSsl; + + private String _username; + + private String _password; + + private File _passwdFile; + + public RestTestHelper(int httpPort) + { + _httpPort = httpPort; + } + + public int getHttpPort() + { + return _httpPort; + } + + private String getHostName() + { + return "localhost"; + } + + private String getProtocol() + { + return _useSsl ? "https" : "http"; + } + + public String getManagementURL() + { + return getProtocol() + "://" + getHostName() + ":" + getHttpPort(); + } + + public URL getManagementURL(String path) throws MalformedURLException + { + return new URL(getManagementURL() + path); + } + + public HttpURLConnection openManagementConnection(String path, String method) throws IOException + { + URL url = getManagementURL(path); + HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); + if(_useSsl) + { + ((HttpsURLConnection) httpCon).setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); + } + if(_username != null) + { + String encoded = new String(new Base64().encode((_username + ":" + _password).getBytes())); + httpCon.setRequestProperty("Authorization", "Basic " + encoded); + } + httpCon.setDoOutput(true); + httpCon.setRequestMethod(method); + return httpCon; + } + + public List<Map<String, Object>> readJsonResponseAsList(HttpURLConnection connection) throws IOException, + JsonParseException, JsonMappingException + { + byte[] data = readConnectionInputStream(connection); + + ObjectMapper mapper = new ObjectMapper(); + + TypeReference<List<LinkedHashMap<String, Object>>> typeReference = new TypeReference<List<LinkedHashMap<String, Object>>>() + { + }; + List<Map<String, Object>> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); + return providedObject; + } + + public Map<String, Object> readJsonResponseAsMap(HttpURLConnection connection) throws IOException, + JsonParseException, JsonMappingException + { + byte[] data = readConnectionInputStream(connection); + + ObjectMapper mapper = new ObjectMapper(); + + TypeReference<LinkedHashMap<String, Object>> typeReference = new TypeReference<LinkedHashMap<String, Object>>() + { + }; + Map<String, Object> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); + return providedObject; + } + + public byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException + { + InputStream is = connection.getInputStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = -1; + while ((len = is.read(buffer)) != -1) + { + baos.write(buffer, 0, len); + } + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("RESPONSE:" + new String(baos.toByteArray())); + } + return baos.toByteArray(); + } + + public void writeJsonRequest(HttpURLConnection connection, Map<String, Object> data) throws JsonGenerationException, + JsonMappingException, IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(connection.getOutputStream(), data); + } + + public Map<String, Object> find(String name, Object value, List<Map<String, Object>> data) + { + for (Map<String, Object> map : data) + { + Object mapValue = map.get(name); + if (value.equals(mapValue)) + { + return map; + } + } + return null; + } + + public Map<String, Object> find(Map<String, Object> searchAttributes, List<Map<String, Object>> data) + { + for (Map<String, Object> map : data) + { + boolean equals = true; + for (Map.Entry<String, Object> entry : searchAttributes.entrySet()) + { + Object mapValue = map.get(entry.getKey()); + if (!entry.getValue().equals(mapValue)) + { + equals = false; + break; + } + } + if (equals) + { + return map; + } + } + return null; + } + + public Map<String, Object> getJsonAsSingletonList(String path) throws IOException + { + List<Map<String, Object>> response = getJsonAsList(path); + + Assert.assertNotNull("Response cannot be null", response); + Assert.assertEquals("Unexpected response", 1, response.size()); + return response.get(0); + } + + public List<Map<String, Object>> getJsonAsList(String path) throws IOException, JsonParseException, + JsonMappingException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + List<Map<String, Object>> response = readJsonResponseAsList(connection); + return response; + } + + public Map<String, Object> getJsonAsMap(String path) throws IOException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + Map<String, Object> response = readJsonResponseAsMap(connection); + return response; + } + + public void createNewGroupMember(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" + URLDecoder.decode(memberName, "UTF-8"), + "PUT"); + + Map<String, Object> groupMemberData = new HashMap<String, Object>(); + // TODO add type + writeJsonRequest(connection, groupMemberData); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void createNewGroupMember(String groupProviderName, String groupName, String memberName) throws IOException + { + createNewGroupMember(groupProviderName, groupName, memberName, HttpServletResponse.SC_CREATED); + } + + public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" + URLDecoder.decode(memberName, "UTF-8"), + "DELETE"); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName) throws IOException + { + removeMemberFromGroup(groupProviderName, groupName, memberName, HttpServletResponse.SC_OK); + } + + public void assertNumberOfGroupMembers(Map<String, Object> data, int expectedNumberOfGroupMembers) + { + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groupmembers"); + if (groups == null) + { + groups = Collections.emptyList(); + } + + Assert.assertEquals("Unexpected number of group members", expectedNumberOfGroupMembers, groups.size()); + } + + public void createGroup(String groupName, String groupProviderName) throws IOException + { + createGroup(groupName, groupProviderName, HttpServletResponse.SC_CREATED); + } + + public void createGroup(String groupName, String groupProviderName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"), + "PUT"); + + Map<String, Object> groupData = new HashMap<String, Object>(); + writeJsonRequest(connection, groupData); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void createOrUpdateUser(String username, String password) throws IOException + { + createOrUpdateUser(username, password, HttpServletResponse.SC_CREATED); + } + + public void createOrUpdateUser(String username, String password, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager/" + username, "PUT"); + + Map<String, Object> data = new HashMap<String, Object>(); + data.put("password", password); + writeJsonRequest(connection, data); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void removeGroup(String groupName, String groupProviderName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"), + "DELETE"); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeGroup(String groupName, String groupProviderName) throws IOException + { + removeGroup(groupName, groupProviderName, HttpServletResponse.SC_OK); + } + + public void removeUserById(String id) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager?id=" + id, "DELETE"); + Assert.assertEquals("Unexpected response code", HttpServletResponse.SC_OK, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeUser(String username, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager/" + username, "DELETE"); + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeUser(String username) throws IOException + { + removeUser(username, HttpServletResponse.SC_OK); + } + + public void assertNumberOfGroups(Map<String, Object> data, int expectedNumberOfGroups) + { + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups"); + if (groups == null) + { + groups = Collections.emptyList(); + } + Assert.assertEquals("Unexpected number of groups", expectedNumberOfGroups, groups.size()); + } + + public void setUseSsl(boolean useSsl) + { + _useSsl = useSsl; + } + + public void setUsernameAndPassword(String username, String password) + { + _username = username; + _password = password; + } + + /** + * Create password file that follows the convention username=password, which is deleted by {@link #tearDown()} + */ + public void configureTemporaryPasswordFile(QpidBrokerTestCase testCase, String... users) throws ConfigurationException, IOException + { + _passwdFile = createTemporaryPasswdFile(users); + + testCase.setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.name", "passwordFile"); + testCase.setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.value", _passwdFile.getAbsolutePath()); + } + + public void tearDown() + { + if (_passwdFile != null) + { + if (_passwdFile.exists()) + { + _passwdFile.delete(); + } + } + } + + private File createTemporaryPasswdFile(String[] users) throws IOException + { + BufferedWriter writer = null; + try + { + File testFile = File.createTempFile(this.getClass().getName(),"tmp"); + testFile.deleteOnExit(); + + writer = new BufferedWriter(new FileWriter(testFile)); + for (int i = 0; i < users.length; i++) + { + String username = users[i]; + writer.write(username + ":" + username); + writer.newLine(); + } + + return testFile; + + } + finally + { + if (writer != null) + { + writer.close(); + } + } + } +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java index b504c9fa60..d65b06e6a6 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java @@ -27,7 +27,7 @@ public class SaslRestTest extends QpidRestTestCase { public void testGet() throws Exception { - Map<String, Object> saslData = getJsonAsMap("/rest/sasl"); + Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/rest/sasl"); assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms")); @SuppressWarnings("unchecked") diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java index b01e1d44b8..c72dcfc8ab 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java @@ -28,7 +28,7 @@ public class StructureRestTest extends QpidRestTestCase public void testGet() throws Exception { - Map<String, Object> structure = getJsonAsMap("/rest/structure"); + Map<String, Object> structure = getRestTestHelper().getJsonAsMap("/rest/structure"); assertNotNull("Structure data cannot be null", structure); assertNode(structure, "Broker"); @@ -46,7 +46,7 @@ public class StructureRestTest extends QpidRestTestCase for (String hostName : EXPECTED_HOSTS) { - Map<String, Object> host = find("name", hostName, virtualhosts); + Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); assertNotNull("Host " + hostName + " is not found ", host); assertNode(host, hostName); @@ -55,7 +55,7 @@ public class StructureRestTest extends QpidRestTestCase assertNotNull("Host " + hostName + " queues are not found ", queues); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> queue = find("name", queueName, queues); + Map<String, Object> queue = getRestTestHelper().find("name", queueName, queues); assertNotNull(hostName + " queue " + queueName + " is not found ", queue); assertNode(queue, queueName); @@ -73,7 +73,7 @@ public class StructureRestTest extends QpidRestTestCase assertNotNull("Host " + hostName + " exchanges are not found ", exchanges); for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = find("name", exchangeName, exchanges); + Map<String, Object> exchange = getRestTestHelper().find("name", exchangeName, exchanges); assertNotNull("Exchange " + exchangeName + " is not found ", exchange); assertNode(exchange, exchangeName); if ("amq.direct".equalsIgnoreCase(exchangeName) || "<<default>>".equalsIgnoreCase(exchangeName)) @@ -83,7 +83,7 @@ public class StructureRestTest extends QpidRestTestCase assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> binding = find("name", queueName, bindings); + Map<String, Object> binding = getRestTestHelper().find("name", queueName, bindings); assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding); assertNode(binding, queueName); } @@ -97,11 +97,11 @@ public class StructureRestTest extends QpidRestTestCase assertNode(aliases.get(0), hostName); } - int[] expectedPorts = { getPort(), getHttpPort() }; + int[] expectedPorts = { getPort(), getRestTestHelper().getHttpPort() }; for (int port : expectedPorts) { String portName = "0.0.0.0:" + port; - Map<String, Object> portData = find("name", portName, ports); + Map<String, Object> portData = getRestTestHelper().find("name", portName, ports); assertNotNull("Port " + portName + " is not found ", portData); assertNode(portData, portName); } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java index e56fa27e21..037d26a7bd 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.management.plugin.servlet.rest; -import java.net.HttpURLConnection; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -29,9 +27,17 @@ import org.apache.qpid.server.model.User; public class UserRestTest extends QpidRestTestCase { + @Override + public void setUp() throws Exception + { + getRestTestHelper().configureTemporaryPasswordFile(this, "user1", "user2"); + + super.setUp(); // do this last because it starts the broker, using the modified config + } + public void testGet() throws Exception { - List<Map<String, Object>> users = getJsonAsList("/rest/user"); + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user"); assertNotNull("Users cannot be null", users); assertTrue("Unexpected number of users", users.size() > 1); for (Map<String, Object> user : users) @@ -42,7 +48,7 @@ public class UserRestTest extends QpidRestTestCase public void testGetUserByName() throws Exception { - List<Map<String, Object>> users = getJsonAsList("/rest/user"); + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user"); assertNotNull("Users cannot be null", users); assertTrue("Unexpected number of users", users.size() > 1); for (Map<String, Object> user : users) @@ -50,7 +56,7 @@ public class UserRestTest extends QpidRestTestCase assertNotNull("Attribute " + User.ID, user.get(User.ID)); String userName = (String) user.get(User.NAME); assertNotNull("Attribute " + User.NAME, userName); - Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); assertUser(userDetails); assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); @@ -60,19 +66,9 @@ public class UserRestTest extends QpidRestTestCase public void testPut() throws Exception { String userName = getTestName(); - HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName, "PUT"); - - Map<String, Object> userData = new HashMap<String, Object>(); - userData.put(User.NAME, userName); - userData.put(User.PASSWORD, userName); + getRestTestHelper().createOrUpdateUser(userName, "newPassword"); - writeJsonRequest(connection, userData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - - connection.disconnect(); - - Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); assertUser(userDetails); assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); @@ -80,27 +76,16 @@ public class UserRestTest extends QpidRestTestCase public void testDelete() throws Exception { - // add user String userName = getTestName(); - HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName, "PUT"); - - Map<String, Object> userData = new HashMap<String, Object>(); - userData.put(User.NAME, userName); - userData.put(User.PASSWORD, userName); + getRestTestHelper().createOrUpdateUser(userName, "newPassword"); - writeJsonRequest(connection, userData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - connection.disconnect(); - - Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); String id = (String) userDetails.get(User.ID); - connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager?id=" + id, "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> users = getJsonAsList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); + getRestTestHelper().removeUserById(id); + + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); assertEquals("User should be deleted", 0, users.size()); } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java index 17f1aaaf7b..4bd936a948 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java @@ -46,12 +46,12 @@ public class VirtualHostRestTest extends QpidRestTestCase public void testGet() throws Exception { - List<Map<String, Object>> hosts = getJsonAsList("/rest/virtualhost/"); + List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/"); assertNotNull("Hosts data cannot be null", hosts); assertEquals("Unexpected number of hosts", 3, hosts.size()); for (String hostName : EXPECTED_HOSTS) { - Map<String, Object> host = find("name", hostName, hosts); + Map<String, Object> host = getRestTestHelper().find("name", hostName, hosts); Asserts.assertVirtualHost(hostName, host); } } @@ -62,7 +62,7 @@ public class VirtualHostRestTest extends QpidRestTestCase _connection = (AMQConnection) getConnection(); _connection.createSession(true, Session.SESSION_TRANSACTED); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); Asserts.assertVirtualHost("test", hostDetails); @SuppressWarnings("unchecked") @@ -74,18 +74,18 @@ public class VirtualHostRestTest extends QpidRestTestCase @SuppressWarnings("unchecked") List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE); assertEquals("Unexpected number of exchanges", 6, exchanges.size()); - Asserts.assertDurableExchange("amq.fanout", "fanout", find(Exchange.NAME, "amq.fanout", exchanges)); - Asserts.assertDurableExchange("qpid.management", "management", find(Exchange.NAME, "qpid.management", exchanges)); - Asserts.assertDurableExchange("amq.topic", "topic", find(Exchange.NAME, "amq.topic", exchanges)); - Asserts.assertDurableExchange("amq.direct", "direct", find(Exchange.NAME, "amq.direct", exchanges)); - Asserts.assertDurableExchange("amq.match", "headers", find(Exchange.NAME, "amq.match", exchanges)); - Asserts.assertDurableExchange("<<default>>", "direct", find(Exchange.NAME, "<<default>>", exchanges)); + Asserts.assertDurableExchange("amq.fanout", "fanout", getRestTestHelper().find(Exchange.NAME, "amq.fanout", exchanges)); + Asserts.assertDurableExchange("qpid.management", "management", getRestTestHelper().find(Exchange.NAME, "qpid.management", exchanges)); + Asserts.assertDurableExchange("amq.topic", "topic", getRestTestHelper().find(Exchange.NAME, "amq.topic", exchanges)); + Asserts.assertDurableExchange("amq.direct", "direct", getRestTestHelper().find(Exchange.NAME, "amq.direct", exchanges)); + Asserts.assertDurableExchange("amq.match", "headers", getRestTestHelper().find(Exchange.NAME, "amq.match", exchanges)); + Asserts.assertDurableExchange("<<default>>", "direct", getRestTestHelper().find(Exchange.NAME, "<<default>>", exchanges)); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE); assertEquals("Unexpected number of queues", 2, queues.size()); - Map<String, Object> queue = find(Queue.NAME, "queue", queues); - Map<String, Object> ping = find(Queue.NAME, "ping", queues); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, "queue", queues); + Map<String, Object> ping = getRestTestHelper().find(Queue.NAME, "ping", queues); Asserts.assertQueue("queue", "standard", queue); Asserts.assertQueue("ping", "standard", ping); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE)); @@ -116,14 +116,14 @@ public class VirtualHostRestTest extends QpidRestTestCase lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> standardQueue = find(Queue.NAME, queueName + "-standard" , queues); - Map<String, Object> sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues); - Map<String, Object> priorityQueue = find(Queue.NAME, queueName + "-priority" , queues); - Map<String, Object> lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues); + Map<String, Object> standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues); + Map<String, Object> sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues); Asserts.assertQueue(queueName + "-standard", "standard", standardQueue); Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue); @@ -149,14 +149,14 @@ public class VirtualHostRestTest extends QpidRestTestCase createExchange(exchangeName + "-headers", "headers"); createExchange(exchangeName + "-fanout", "fanout"); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - Map<String, Object> directExchange = find(Queue.NAME, exchangeName + "-direct" , exchanges); - Map<String, Object> topicExchange = find(Queue.NAME, exchangeName + "-topic" , exchanges); - Map<String, Object> headersExchange = find(Queue.NAME, exchangeName + "-headers" , exchanges); - Map<String, Object> fanoutExchange = find(Queue.NAME, exchangeName + "-fanout" , exchanges); + Map<String, Object> directExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-direct" , exchanges); + Map<String, Object> topicExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-topic" , exchanges); + Map<String, Object> headersExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-headers" , exchanges); + Map<String, Object> fanoutExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-fanout" , exchanges); Asserts.assertDurableExchange(exchangeName + "-direct", "direct", directExchange); Asserts.assertDurableExchange(exchangeName + "-topic", "topic", topicExchange); @@ -175,11 +175,11 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName()+ "-lvq"; createQueue(queueName, "lvq", null); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> lvqQueue = find(Queue.NAME, queueName , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); Asserts.assertQueue(queueName , "lvq", lvqQueue); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); @@ -192,11 +192,11 @@ public class VirtualHostRestTest extends QpidRestTestCase int responseCode = tryCreateQueue(queueName, "sorted", null); assertEquals("Unexpected response code", 409, responseCode); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> testQueue = find(Queue.NAME, queueName , queues); + Map<String, Object> testQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); assertNull("Sorted queue without a key was created ", testQueue); } @@ -206,11 +206,11 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName()+ "-priority"; createQueue(queueName, "priority", null); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> priorityQueue = find(Queue.NAME, queueName , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); Asserts.assertQueue(queueName , "priority", priorityQueue); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE)); @@ -222,11 +222,11 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName(); createQueue(queueName, null, null); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> queue = find(Queue.NAME, queueName , queues); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); Asserts.assertQueue(queueName , "standard", queue); } @@ -237,11 +237,11 @@ public class VirtualHostRestTest extends QpidRestTestCase int responseCode = tryCreateQueue(queueName, "unsupported", null); assertEquals("Unexpected response code", 409, responseCode); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> queue = find(Queue.NAME, queueName , queues); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); assertNull("Queue of unsupported type was created", queue); } @@ -251,10 +251,10 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName(); createQueue(queueName, null, null); - HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); assertEquals("Queue should be deleted", 0, queues.size()); } @@ -262,12 +262,12 @@ public class VirtualHostRestTest extends QpidRestTestCase { String queueName = getTestQueueName(); createQueue(queueName, null, null); - Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); - HttpURLConnection connection = openManagementConection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); assertEquals("Queue should be deleted", 0, queues.size()); } @@ -276,10 +276,10 @@ public class VirtualHostRestTest extends QpidRestTestCase String exchangeName = getTestName(); createExchange(exchangeName, "direct"); - HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); assertEquals("Exchange should be deleted", 0, queues.size()); } @@ -287,12 +287,12 @@ public class VirtualHostRestTest extends QpidRestTestCase { String exchangeName = getTestName(); createExchange(exchangeName, "direct"); - Map<String, Object> echangeDetails = getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); + Map<String, Object> echangeDetails = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); - HttpURLConnection connection = openManagementConection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); assertEquals("Exchange should be deleted", 0, queues.size()); } @@ -326,14 +326,14 @@ public class VirtualHostRestTest extends QpidRestTestCase lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> standardQueue = find(Queue.NAME, queueName + "-standard" , queues); - Map<String, Object> sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues); - Map<String, Object> priorityQueue = find(Queue.NAME, queueName + "-priority" , queues); - Map<String, Object> lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues); + Map<String, Object> standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues); + Map<String, Object> sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues); attributes.put(Queue.DURABLE, Boolean.TRUE); Asserts.assertQueue(queueName + "-standard", "standard", standardQueue, attributes); @@ -355,25 +355,25 @@ public class VirtualHostRestTest extends QpidRestTestCase attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); //verify the starting state - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - assertNull("queue should not have already been present", find(Queue.NAME, queueName , queues)); - assertNull("queue should not have already been present", find(Queue.NAME, queueName + "_DLQ" , queues)); - assertNull("exchange should not have already been present", find(Exchange.NAME, queueName + "_DLE" , exchanges)); + assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName , queues)); + assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues)); + assertNull("exchange should not have already been present", getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges)); //create the queue createQueue(queueName, "standard", attributes); //verify the new queue, as well as the DLQueue and DLExchange have been created - hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - Map<String, Object> queue = find(Queue.NAME, queueName , queues); - Map<String, Object> dlqQueue = find(Queue.NAME, queueName + "_DLQ" , queues); - Map<String, Object> dlExchange = find(Exchange.NAME, queueName + "_DLE" , exchanges); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); + Map<String, Object> dlqQueue = getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues); + Map<String, Object> dlExchange = getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges); assertNotNull("queue should not have been present", queue); assertNotNull("queue should not have been present", dlqQueue); assertNotNull("exchange should not have been present", dlExchange); @@ -388,14 +388,14 @@ public class VirtualHostRestTest extends QpidRestTestCase private void createExchange(String exchangeName, String exchangeType) throws IOException { - HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "PUT"); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Exchange.NAME, exchangeName); queueData.put(Exchange.DURABLE, Boolean.TRUE); queueData.put(Exchange.TYPE, exchangeType); - writeJsonRequest(connection, queueData); + getRestTestHelper().writeJsonRequest(connection, queueData); assertEquals("Unexpected response code", 201, connection.getResponseCode()); connection.disconnect(); @@ -411,7 +411,7 @@ public class VirtualHostRestTest extends QpidRestTestCase private int tryCreateQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException, JsonGenerationException, JsonMappingException { - HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "PUT"); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Queue.NAME, queueName); @@ -425,7 +425,7 @@ public class VirtualHostRestTest extends QpidRestTestCase queueData.putAll(attributes); } - writeJsonRequest(connection, queueData); + getRestTestHelper().writeJsonRequest(connection, queueData); int responseCode = connection.getResponseCode(); connection.disconnect(); return responseCode; diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java new file mode 100644 index 0000000000..f9f9fbfef0 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java @@ -0,0 +1,187 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.qpid.systest.rest.acl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.servlet.rest.QpidRestTestCase; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; + +public class GroupRestACLTest extends QpidRestTestCase +{ + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + + private static final String ALLOWED_GROUP = "allowedGroup"; + private static final String DENIED_GROUP = "deniedGroup"; + private static final String OTHER_GROUP = "otherGroup"; + + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String OTHER_USER = "admin"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + //DONT call super.setUp(), the tests will start the broker after configuring it + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(ALLOWED_GROUP + ".users", ALLOWED_USER); + props.put(DENIED_GROUP + ".users", DENIED_USER); + props.put(OTHER_GROUP + ".users", OTHER_USER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } + + public void testCreateGroup() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " CREATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().createGroup("newGroup", FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 4); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + //TODO: the expected response code needs changed when we overhaul the brokers error handling + getRestTestHelper().createGroup("anotherNewGroup", FILE_GROUP_MANAGER, HttpServletResponse.SC_CONFLICT); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 4); + } + + public void testDeleteGroup() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " DELETE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + //TODO: the expected response code needs changed when we overhaul the brokers error handling + getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER, HttpServletResponse.SC_CONFLICT); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 2); + } + + public void testUpdateGroupAddMember() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember", HttpServletResponse.SC_CONFLICT); + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember"); + assertNumberOfGroupMembers(OTHER_GROUP, 2); + } + + public void testUpdateGroupDeleteMember() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER, HttpServletResponse.SC_CONFLICT); + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER); + assertNumberOfGroupMembers(OTHER_GROUP, 0); + } + + private void assertNumberOfGroupMembers(String groupName, int expectedNumberOfMembers) throws IOException + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/" + groupName); + getRestTestHelper().assertNumberOfGroupMembers(group, expectedNumberOfMembers); + } +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java new file mode 100644 index 0000000000..514d1bd781 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.qpid.systest.rest.acl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.servlet.rest.QpidRestTestCase; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; + +public class UserRestACLTest extends QpidRestTestCase +{ + private static final String ALLOWED_GROUP = "allowedGroup"; + private static final String DENIED_GROUP = "deniedGroup"; + private static final String OTHER_GROUP = "otherGroup"; + + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String OTHER_USER = "other"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER); + + //DONT call super.setUp(), the tests will start the broker after configuring it + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(ALLOWED_GROUP + ".users", ALLOWED_USER); + props.put(DENIED_GROUP + ".users", DENIED_USER); + props.put(OTHER_GROUP + ".users", OTHER_USER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } + + public void testAddUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE USER", + "ACL DENY-LOG " + DENIED_GROUP + " CREATE USER"); + + //Start the broker with the custom config + super.setUp(); + + String newUser = "newUser"; + String password = "password"; + + assertUserDoesNotExist(newUser); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + getRestTestHelper().createOrUpdateUser(newUser, password, HttpServletResponse.SC_CONFLICT); + assertUserDoesNotExist(newUser); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createOrUpdateUser(newUser, password); + assertUserExists(newUser); + } + + public void testDeleteUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE USER", + "ACL DENY-LOG " + DENIED_GROUP + " DELETE USER"); + + //Start the broker with the custom config + super.setUp(); + + assertUserExists(OTHER_USER); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + getRestTestHelper().removeUser(OTHER_USER, HttpServletResponse.SC_CONFLICT); + assertUserExists(OTHER_USER); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().removeUser(OTHER_USER); + assertUserDoesNotExist(OTHER_USER); + } + + public void testUpdateUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE USER", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE USER"); + + //Start the broker with the custom config + super.setUp(); + + String newPassword = "newPassword"; + + checkPassword(OTHER_USER, OTHER_USER, true); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_CONFLICT); + + checkPassword(OTHER_USER, newPassword, false); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_OK); // expect SC_OK rather than the default SC_CREATED + + checkPassword(OTHER_USER, newPassword, true); + checkPassword(OTHER_USER, OTHER_USER, false); + } + + private void checkPassword(String username, String password, boolean passwordExpectedToBeCorrect) throws IOException + { + getRestTestHelper().setUsernameAndPassword(username, password); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager/", "GET"); + + boolean passwordIsCorrect = connection.getResponseCode() == HttpServletResponse.SC_OK; + + connection.disconnect(); + + assertEquals(passwordExpectedToBeCorrect, passwordIsCorrect); + } + + private void assertUserDoesNotExist(String newUser) throws JsonParseException, JsonMappingException, IOException + { + String path = "/rest/user/PrincipalDatabaseAuthenticationManager/" + newUser; + List<Map<String, Object>> userDetailsList = getRestTestHelper().getJsonAsList(path); + assertTrue(userDetailsList.isEmpty()); + } + + private void assertUserExists(String username) throws IOException + { + String path = "/rest/user/PrincipalDatabaseAuthenticationManager/" + username; + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList(path); + + assertEquals( + "User returned by " + path + " should have name=" + username + ". The returned JSON was: " + userDetails, + username, + userDetails.get("name")); + } +} |
