Skip to content
Snippets Groups Projects
Commit 0ab722e5 authored by Dustin Jenkins's avatar Dustin Jenkins
Browse files

Story 1734: Added listing of users.

parent 659bf4e8
No related branches found
No related tags found
No related merge requests found
Showing
with 369 additions and 130 deletions
...@@ -80,6 +80,7 @@ import ca.nrc.cadc.net.TransientException; ...@@ -80,6 +80,7 @@ import ca.nrc.cadc.net.TransientException;
import com.unboundid.ldap.sdk.DN; import com.unboundid.ldap.sdk.DN;
public interface UserPersistence<T extends Principal> public interface UserPersistence<T extends Principal>
{ {
/** /**
......
...@@ -128,7 +128,7 @@ public class LdapConfig ...@@ -128,7 +128,7 @@ public class LdapConfig
public static LdapConfig getLdapConfig(final String ldapProperties) public static LdapConfig getLdapConfig(final String ldapProperties)
{ {
logger.debug("Reading LDAP properties from: " + ldapProperties); logger.info("Reading LDAP properties from: " + ldapProperties);
PropertiesReader pr = new PropertiesReader(ldapProperties); PropertiesReader pr = new PropertiesReader(ldapProperties);
MultiValuedProperties config = pr.getAllProperties(); MultiValuedProperties config = pr.getAllProperties();
......
...@@ -69,19 +69,18 @@ ...@@ -69,19 +69,18 @@
package ca.nrc.cadc.ac.server.web.users; package ca.nrc.cadc.ac.server.web.users;
import java.io.Writer;
import java.util.Collection;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.ac.server.UserPersistence;
public class GetUserNamesAction extends UsersAction
public class GetUsersAction extends UsersAction
{ {
private static final Logger log = Logger.getLogger(GetUserNamesAction.class); private static final Logger log = Logger.getLogger(GetUsersAction.class);
GetUserNamesAction(UserLogInfo logInfo) GetUsersAction(UserLogInfo logInfo)
{ {
super(logInfo); super(logInfo);
} }
...@@ -89,23 +88,9 @@ public class GetUserNamesAction extends UsersAction ...@@ -89,23 +88,9 @@ public class GetUserNamesAction extends UsersAction
public Object run() public Object run()
throws Exception throws Exception
{ {
UserPersistence userPersistence = getUserPersistence(); final UserPersistence userPersistence = getUserPersistence();
Collection<String> users = userPersistence.getUserNames();
log.debug("Found " + users.size() + " user names"); writeUsers(userPersistence.getUserNames());
response.setContentType("text/plain");
log.debug("Set content-type to text/plain");
Writer writer = response.getWriter();
boolean start = true;
for (final String user : users)
{
if (!start)
{
writer.write("\r\n");
}
writer.write(user);
start = false;
}
return null; return null;
} }
} }
...@@ -75,6 +75,7 @@ import java.security.AccessControlException; ...@@ -75,6 +75,7 @@ import java.security.AccessControlException;
import java.security.Principal; import java.security.Principal;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.Collection;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -251,42 +252,33 @@ public abstract class UsersAction ...@@ -251,42 +252,33 @@ public abstract class UsersAction
} }
/** /**
* Read a user from the HTTP Request's stream. * Write a user to the response's writer.
* *
* @param inputStream The Input Stream to read from. * @param user The user object to marshall and write out.
* @return User instance. * @throws IOException Any writing errors.
* @throws IOException Any reading error(s)
*/ */
protected final User<Principal> readUser( protected final <T extends Principal> void writeUser(final User<T> user)
final InputStream inputStream) throws IOException throws IOException
{ {
final User<Principal> user; response.setContentType(acceptedContentType);
final Writer writer = response.getWriter();
if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE))
{ {
user = ca.nrc.cadc.ac.xml.UserReader.read(inputStream); ca.nrc.cadc.ac.xml.UserWriter.write(user, writer);
} }
else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) else if (acceptedContentType.equals(JSON_CONTENT_TYPE))
{ {
user = ca.nrc.cadc.ac.json.UserReader.read(inputStream); ca.nrc.cadc.ac.json.UserWriter.write(user, writer);
}
else
{
// Should never happen.
throw new IOException("Unknown content being asked for: "
+ acceptedContentType);
} }
return user;
} }
/** /**
* Write a user to the response's writer. * Write out a list of users as this Action's specified content type.
* *
* @param user The user object to marshall and write out. * @param users The Collection of user entries.
* @throws IOException Any writing errors.
*/ */
protected final <T extends Principal> void writeUser(final User<T> user) protected final void writeUsers(final Collection<String> users)
throws IOException throws IOException
{ {
response.setContentType(acceptedContentType); response.setContentType(acceptedContentType);
...@@ -294,11 +286,11 @@ public abstract class UsersAction ...@@ -294,11 +286,11 @@ public abstract class UsersAction
if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE))
{ {
ca.nrc.cadc.ac.xml.UserWriter.write(user, writer); ca.nrc.cadc.ac.xml.UsersWriter.write(users, writer);
} }
else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) else if (acceptedContentType.equals(JSON_CONTENT_TYPE))
{ {
ca.nrc.cadc.ac.json.UserWriter.write(user, writer); ca.nrc.cadc.ac.json.UsersWriter.write(users, writer);
} }
} }
} }
...@@ -124,7 +124,7 @@ public class UsersActionFactory ...@@ -124,7 +124,7 @@ public class UsersActionFactory
{ {
if (method.equals("GET")) if (method.equals("GET"))
{ {
action = new GetUserNamesAction(logInfo); action = new GetUsersAction(logInfo);
} }
else if (method.equals("PUT")) else if (method.equals("PUT"))
{ {
......
/*
************************************************************************
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2014. (c) 2014.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
* All rights reserved Tous droits réservés
*
* NRC disclaims any warranties, Le CNRC dénie toute garantie
* expressed, implied, or énoncée, implicite ou légale,
* statutory, of any kind with de quelque nature que ce
* respect to the software, soit, concernant le logiciel,
* including without limitation y compris sans restriction
* any warranty of merchantability toute garantie de valeur
* or fitness for a particular marchande ou de pertinence
* purpose. NRC shall not be pour un usage particulier.
* liable in any event for any Le CNRC ne pourra en aucun cas
* damages, whether direct or être tenu responsable de tout
* indirect, special or general, dommage, direct ou indirect,
* consequential or incidental, particulier ou général,
* arising from the use of the accessoire ou fortuit, résultant
* software. Neither the name de l'utilisation du logiciel. Ni
* of the National Research le nom du Conseil National de
* Council of Canada nor the Recherches du Canada ni les noms
* names of its contributors may de ses participants ne peuvent
* be used to endorse or promote être utilisés pour approuver ou
* products derived from this promouvoir les produits dérivés
* software without specific prior de ce logiciel sans autorisation
* written permission. préalable et particulière
* par écrit.
*
* This file is part of the Ce fichier fait partie du projet
* OpenCADC project. OpenCADC.
*
* OpenCADC is free software: OpenCADC est un logiciel libre ;
* you can redistribute it and/or vous pouvez le redistribuer ou le
* modify it under the terms of modifier suivant les termes de
* the GNU Affero General Public la “GNU Affero General Public
* License as published by the License” telle que publiée
* Free Software Foundation, par la Free Software Foundation
* either version 3 of the : soit la version 3 de cette
* License, or (at your option) licence, soit (à votre gré)
* any later version. toute version ultérieure.
*
* OpenCADC is distributed in the OpenCADC est distribué
* hope that it will be useful, dans l’espoir qu’il vous
* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
* without even the implied GARANTIE : sans même la garantie
* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
* General Public License for Générale Publique GNU Affero
* more details. pour plus de détails.
*
* You should have received Vous devriez avoir reçu une
* a copy of the GNU Affero copie de la Licence Générale
* General Public License along Publique GNU Affero avec
* with OpenCADC. If not, see OpenCADC ; si ce n’est
* <http://www.gnu.org/licenses/>. pas le cas, consultez :
* <http://www.gnu.org/licenses/>.
*
* $Revision: 4 $
*
************************************************************************
*/
package ca.nrc.cadc.ac.server.web.users;
import ca.nrc.cadc.ac.server.UserPersistence;
import ca.nrc.cadc.auth.HttpPrincipal;
import org.apache.log4j.Level;
import org.json.JSONArray;
import ca.nrc.cadc.util.Log4jInit;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import static org.easymock.EasyMock.*;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.skyscreamer.jsonassert.JSONAssert;
/**
*
* @author adriand
*/
public class GetUsersActionTest
{
@BeforeClass
public static void setUpClass()
{
Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO);
}
@Test
@SuppressWarnings("unchecked")
public void testWriteUsersJSON() throws Exception
{
final HttpServletResponse mockResponse =
createMock(HttpServletResponse.class);
final UserPersistence<HttpPrincipal> mockUserPersistence =
createMock(UserPersistence.class);
final Collection<String> userEntries = new ArrayList<String>();
for (int i = 1; i <= 13; i++)
{
userEntries.add("USER_" + i);
}
final GetUsersAction testSubject = new GetUsersAction(null)
{
@Override
UserPersistence<HttpPrincipal> getUserPersistence()
{
return mockUserPersistence;
}
};
testSubject.setAcceptedContentType(UsersAction.JSON_CONTENT_TYPE);
final Writer writer = new StringWriter();
final PrintWriter printWriter = new PrintWriter(writer);
expect(mockUserPersistence.getUserNames()).andReturn(
userEntries).once();
expect(mockResponse.getWriter()).andReturn(printWriter).once();
mockResponse.setContentType("application/json");
expectLastCall().once();
replay(mockResponse, mockUserPersistence);
testSubject.doAction(null, mockResponse);
final JSONArray expected =
new JSONArray("['USER_1','USER_2','USER_3','USER_4','USER_5','USER_6','USER_7','USER_8','USER_9','USER_10','USER_11','USER_12','USER_13']");
final JSONArray result = new JSONArray(writer.toString());
JSONAssert.assertEquals(expected, result, true);
verify(mockResponse, mockUserPersistence);
}
@Test
@SuppressWarnings("unchecked")
public void testWriteUsersXML() throws Exception
{
final HttpServletResponse mockResponse =
createMock(HttpServletResponse.class);
final UserPersistence<HttpPrincipal> mockUserPersistence =
createMock(UserPersistence.class);
final Collection<String> userEntries = new ArrayList<String>();
for (int i = 1; i <= 13; i++)
{
userEntries.add("USER_" + i);
}
final GetUsersAction testSubject = new GetUsersAction(null)
{
@Override
UserPersistence<HttpPrincipal> getUserPersistence()
{
return mockUserPersistence;
}
};
final Writer writer = new StringWriter();
final PrintWriter printWriter = new PrintWriter(writer);
expect(mockUserPersistence.getUserNames()).andReturn(
userEntries).once();
expect(mockResponse.getWriter()).andReturn(printWriter).once();
mockResponse.setContentType("text/xml");
expectLastCall().once();
replay(mockResponse, mockUserPersistence);
testSubject.doAction(null, mockResponse);
final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" +
"<users>\r\n" +
" <USER_1 />\r\n" +
" <USER_2 />\r\n" +
" <USER_3 />\r\n" +
" <USER_4 />\r\n" +
" <USER_5 />\r\n" +
" <USER_6 />\r\n" +
" <USER_7 />\r\n" +
" <USER_8 />\r\n" +
" <USER_9 />\r\n" +
" <USER_10 />\r\n" +
" <USER_11 />\r\n" +
" <USER_12 />\r\n" +
" <USER_13 />\r\n" +
"</users>\r\n";
final String result = writer.toString();
assertEquals("Wrong XML", expected, result);
verify(mockResponse, mockUserPersistence);
}
}
...@@ -67,7 +67,6 @@ ...@@ -67,7 +67,6 @@
package ca.nrc.cadc.ac.server.web.users; package ca.nrc.cadc.ac.server.web.users;
import ca.nrc.cadc.ac.server.web.RemoveUserMemberAction;
import ca.nrc.cadc.util.Log4jInit; import ca.nrc.cadc.util.Log4jInit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Level; import org.apache.log4j.Level;
...@@ -160,7 +159,7 @@ public class UserActionFactoryTest ...@@ -160,7 +159,7 @@ public class UserActionFactoryTest
EasyMock.replay(request); EasyMock.replay(request);
UsersAction action = UsersActionFactory.getUsersAction(request, null); UsersAction action = UsersActionFactory.getUsersAction(request, null);
EasyMock.verify(request); EasyMock.verify(request);
Assert.assertTrue("Wrong action", action instanceof GetUserNamesAction); Assert.assertTrue("Wrong action", action instanceof GetUsersAction);
} }
catch (Throwable t) catch (Throwable t)
{ {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
******************* CANADIAN ASTRONOMY DATA CENTRE ******************* ******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
* *
* (c) 2014. (c) 2014. * (c) 2015. (c) 2015.
* Government of Canada Gouvernement du Canada * Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches * National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
...@@ -62,105 +62,53 @@ ...@@ -62,105 +62,53 @@
* <http://www.gnu.org/licenses/>. pas le cas, consultez : * <http://www.gnu.org/licenses/>. pas le cas, consultez :
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
* *
* $Revision: 4 $
* *
************************************************************************ ************************************************************************
*/ */
package ca.nrc.cadc.ac.server.web.users;
import static org.junit.Assert.fail; package ca.nrc.cadc.ac.json;
import java.io.PrintWriter; import org.json.JSONException;
import java.security.Principal; import org.json.JSONWriter;
import java.util.ArrayList;
import java.util.Collection;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Level; import java.io.IOException;
import org.apache.log4j.Logger; import java.io.Writer;
import org.easymock.EasyMock; import java.util.Collection;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import ca.nrc.cadc.ac.server.GroupPersistence;
import ca.nrc.cadc.ac.server.UserPersistence;
import ca.nrc.cadc.ac.server.web.GetGroupNamesAction;
import ca.nrc.cadc.ac.server.web.GroupLogInfo;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.util.Log4jInit;
import ca.nrc.cadc.uws.server.SyncOutput;
/** /**
* * Class to write out, as JSON, a list of user entries.
* @author adriand
*/ */
public class GetUserIDsActionTest public class UsersWriter
{ {
private final static Logger log = Logger.getLogger(GetUserIDsActionTest.class); public static void write(final Collection<String> users,
final Writer writer) throws IOException
@BeforeClass
public static void setUpClass()
{ {
Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); final JSONWriter jsonWriter = new JSONWriter(writer);
}
@Test
@Ignore
public void testRun() throws Exception
{
/*
try try
{ {
Collection<HttpPrincipal> userIDs = new ArrayList<HttpPrincipal>(); jsonWriter.array();
userIDs.add(new HttpPrincipal("foo"));
userIDs.add(new HttpPrincipal("bar"));
final UserPersistence mockPersistence = EasyMock.createMock(UserPersistence.class);
EasyMock.expect(mockPersistence.getCadcIDs()).andReturn(userIDs).once();
final PrintWriter mockWriter = EasyMock.createMock(PrintWriter.class);
mockWriter.write("foo", 0, 3);
EasyMock.expectLastCall();
mockWriter.write(44);
EasyMock.expectLastCall();
mockWriter.write("bar", 0, 3);
EasyMock.expectLastCall();
mockWriter.write("\n");
EasyMock.expectLastCall();
final SyncOutput mockSyncOutput =
EasyMock.createMock(SyncOutput.class);
mockSyncOutput.setHeader("Content-Type", "text/csv"); for (final String s : users)
final HttpServletResponse mockResponse = EasyMock.createMock(HttpServletResponse.class);
mockResponse.setContentType("text/csv");
EasyMock.expectLastCall();
EasyMock.expect(mockResponse.getWriter()).andReturn(mockWriter).once();
UserLogInfo mockLog = EasyMock.createMock(UserLogInfo.class);
EasyMock.replay(mockPersistence, mockWriter, mockResponse, mockLog);
GetUserIDsAction action = new GetUserIDsAction(mockLog)
{ {
@Override jsonWriter.value(s);
<T extends Principal> UserPersistence<T> getUserPersistence() }
{
return mockPersistence;
};
};
action.run();
} }
catch (Throwable t) catch (JSONException e)
{ {
log.error(t.getMessage(), t); throw new IOException(e);
fail("unexpected error: " + t.getMessage()); }
finally
{
try
{
jsonWriter.endArray();
}
catch (JSONException e)
{
throw new IOException(e);
}
} }
*/
} }
} }
/*
************************************************************************
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2015. (c) 2015.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
* All rights reserved Tous droits réservés
*
* NRC disclaims any warranties, Le CNRC dénie toute garantie
* expressed, implied, or énoncée, implicite ou légale,
* statutory, of any kind with de quelque nature que ce
* respect to the software, soit, concernant le logiciel,
* including without limitation y compris sans restriction
* any warranty of merchantability toute garantie de valeur
* or fitness for a particular marchande ou de pertinence
* purpose. NRC shall not be pour un usage particulier.
* liable in any event for any Le CNRC ne pourra en aucun cas
* damages, whether direct or être tenu responsable de tout
* indirect, special or general, dommage, direct ou indirect,
* consequential or incidental, particulier ou général,
* arising from the use of the accessoire ou fortuit, résultant
* software. Neither the name de l'utilisation du logiciel. Ni
* of the National Research le nom du Conseil National de
* Council of Canada nor the Recherches du Canada ni les noms
* names of its contributors may de ses participants ne peuvent
* be used to endorse or promote être utilisés pour approuver ou
* products derived from this promouvoir les produits dérivés
* software without specific prior de ce logiciel sans autorisation
* written permission. préalable et particulière
* par écrit.
*
* This file is part of the Ce fichier fait partie du projet
* OpenCADC project. OpenCADC.
*
* OpenCADC is free software: OpenCADC est un logiciel libre ;
* you can redistribute it and/or vous pouvez le redistribuer ou le
* modify it under the terms of modifier suivant les termes de
* the GNU Affero General Public la “GNU Affero General Public
* License as published by the License” telle que publiée
* Free Software Foundation, par la Free Software Foundation
* either version 3 of the : soit la version 3 de cette
* License, or (at your option) licence, soit (à votre gré)
* any later version. toute version ultérieure.
*
* OpenCADC is distributed in the OpenCADC est distribué
* hope that it will be useful, dans l’espoir qu’il vous
* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
* without even the implied GARANTIE : sans même la garantie
* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
* General Public License for Générale Publique GNU Affero
* more details. pour plus de détails.
*
* You should have received Vous devriez avoir reçu une
* a copy of the GNU Affero copie de la Licence Générale
* General Public License along Publique GNU Affero avec
* with OpenCADC. If not, see OpenCADC ; si ce n’est
* <http://www.gnu.org/licenses/>. pas le cas, consultez :
* <http://www.gnu.org/licenses/>.
*
*
************************************************************************
*/
package ca.nrc.cadc.ac.xml;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
public class UsersWriter
{
/**
* Write the Collection of String entries as XML.
*
* @param users The Collection of User strings.
* @param writer The Writer to output to.
* @throws IOException Any writing errors.
*/
public static void write(final Collection<String> users,
final Writer writer) throws IOException
{
// Create the root users Element.
final Element usersElement = new Element("users");
for (final String s : users)
{
final Element userEntryElement = new Element(s);
usersElement.addContent(userEntryElement);
}
final XMLOutputter output = new XMLOutputter();
output.setFormat(Format.getPrettyFormat());
output.output(new Document(usersElement), writer);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment