Skip to content
Snippets Groups Projects
Commit d1ebc41c authored by Brian Major's avatar Brian Major
Browse files

s1885 - added ability for privileged user to permanently delete a user

parent 22e2c986
No related branches found
No related tags found
No related merge requests found
Showing
with 99 additions and 33 deletions
...@@ -238,6 +238,19 @@ public interface UserPersistence ...@@ -238,6 +238,19 @@ public interface UserPersistence
throws UserNotFoundException, TransientException, throws UserNotFoundException, TransientException,
AccessControlException; AccessControlException;
/**
* Deactivate the user with the specified Principal from the active users tree.
*
* @param userID A Principal of the User.
*
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
void deactivateUser(Principal userID)
throws UserNotFoundException, TransientException,
AccessControlException;
/** /**
* Delete the user with the specified Principal from the pending users tree. * Delete the user with the specified Principal from the pending users tree.
* *
......
...@@ -1069,11 +1069,11 @@ public class LdapUserDAO extends LdapDAO ...@@ -1069,11 +1069,11 @@ public class LdapUserDAO extends LdapDAO
* @throws TransientException If an temporary, unexpected problem occurred. * @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted. * @throws AccessControlException If the operation is not permitted.
*/ */
public void deleteUser(final Principal userID) public void deleteUser(final Principal userID, boolean markDelete)
throws UserNotFoundException, TransientException, throws UserNotFoundException, TransientException,
AccessControlException AccessControlException
{ {
deleteUser(userID, config.getUsersDN(), true); deleteUser(userID, config.getUsersDN(), markDelete);
} }
/** /**
......
...@@ -402,7 +402,7 @@ public class LdapUserPersistence extends LdapPersistence implements UserPersiste ...@@ -402,7 +402,7 @@ public class LdapUserPersistence extends LdapPersistence implements UserPersiste
* @throws TransientException If an temporary, unexpected problem occurred. * @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted. * @throws AccessControlException If the operation is not permitted.
*/ */
public void deleteUser(Principal userID) public void deactivateUser(Principal userID)
throws UserNotFoundException, TransientException, throws UserNotFoundException, TransientException,
AccessControlException AccessControlException
{ {
...@@ -415,7 +415,36 @@ public class LdapUserPersistence extends LdapPersistence implements UserPersiste ...@@ -415,7 +415,36 @@ public class LdapUserPersistence extends LdapPersistence implements UserPersiste
try try
{ {
userDAO = getLdapUserDao(conns); userDAO = getLdapUserDao(conns);
userDAO.deleteUser(userID); userDAO.deleteUser(userID, true);
}
finally
{
conns.releaseConnections();
}
}
/**
* Delete the user specified by userID.
*
* @param userID The userID.
*
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public void deleteUser(Principal userID)
throws UserNotFoundException, TransientException,
AccessControlException
{
// admin API: permission checks done in action layer
// and in ACIs.
LdapUserDAO userDAO = null;
LdapConnections conns = new LdapConnections(this);
try
{
userDAO = getLdapUserDao(conns);
userDAO.deleteUser(userID, false);
} }
finally finally
{ {
......
...@@ -84,12 +84,12 @@ import javax.servlet.http.HttpServlet; ...@@ -84,12 +84,12 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import ca.nrc.cadc.ac.server.web.users.CreateUserAction;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.server.PluginFactory; import ca.nrc.cadc.ac.server.PluginFactory;
import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.ac.server.UserPersistence;
import ca.nrc.cadc.ac.server.web.users.AbstractUserAction; import ca.nrc.cadc.ac.server.web.users.AbstractUserAction;
import ca.nrc.cadc.ac.server.web.users.CreateUserAction;
import ca.nrc.cadc.ac.server.web.users.GetUserAction; import ca.nrc.cadc.ac.server.web.users.GetUserAction;
import ca.nrc.cadc.ac.server.web.users.UserActionFactory; import ca.nrc.cadc.ac.server.web.users.UserActionFactory;
import ca.nrc.cadc.ac.server.web.users.UserLogInfo; import ca.nrc.cadc.ac.server.web.users.UserLogInfo;
...@@ -186,6 +186,17 @@ public class UserServlet extends HttpServlet ...@@ -186,6 +186,17 @@ public class UserServlet extends HttpServlet
Subject subject; Subject subject;
Subject privilegedSubject = getPrivilegedSubject(request); Subject privilegedSubject = getPrivilegedSubject(request);
log.debug("privileged subject: " + privilegedSubject); log.debug("privileged subject: " + privilegedSubject);
if (privilegedSubject != null)
{
action.setIsPrivilegedUser(true);
action.setPrivilegedSubject(true);
logInfo.setSubject(privilegedSubject);
}
else
{
action.setIsPrivilegedUser(false);
action.setPrivilegedSubject(false);
}
// If the calling subject is not a PrivilegedSubject, // If the calling subject is not a PrivilegedSubject,
// AND it is a PUT request, throw an AccessControlException // AND it is a PUT request, throw an AccessControlException
...@@ -194,7 +205,6 @@ public class UserServlet extends HttpServlet ...@@ -194,7 +205,6 @@ public class UserServlet extends HttpServlet
profiler.checkpoint("check non-privileged user"); profiler.checkpoint("check non-privileged user");
if (privilegedSubject == null) if (privilegedSubject == null)
{ {
action.setPrivilegedSubject(false);
subject = AuthenticationUtil.getSubject(request); subject = AuthenticationUtil.getSubject(request);
logInfo.setSubject(subject); logInfo.setSubject(subject);
log.debug("augmented subject: " + subject); log.debug("augmented subject: " + subject);
...@@ -202,7 +212,6 @@ public class UserServlet extends HttpServlet ...@@ -202,7 +212,6 @@ public class UserServlet extends HttpServlet
} }
else else
{ {
action.setPrivilegedSubject(true);
log.debug("subject not augmented: " + privilegedSubject); log.debug("subject not augmented: " + privilegedSubject);
subject = privilegedSubject; subject = privilegedSubject;
logInfo.setSubject(privilegedSubject); logInfo.setSubject(privilegedSubject);
...@@ -214,11 +223,8 @@ public class UserServlet extends HttpServlet ...@@ -214,11 +223,8 @@ public class UserServlet extends HttpServlet
// AND it is a GET request, do not augment the subject. // AND it is a GET request, do not augment the subject.
else if (action instanceof GetUserAction && privilegedSubject != null) else if (action instanceof GetUserAction && privilegedSubject != null)
{ {
profiler.checkpoint("check privileged user");
subject = Subject.getSubject(AccessController.getContext()); subject = Subject.getSubject(AccessController.getContext());
log.debug("subject not augmented: " + subject); log.debug("subject not augmented: " + subject);
action.setAugmentUser(true);
logInfo.setSubject(privilegedSubject);
profiler.checkpoint("set privileged user"); profiler.checkpoint("set privileged user");
} }
else else
......
...@@ -72,27 +72,23 @@ import java.io.IOException; ...@@ -72,27 +72,23 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Writer; import java.io.Writer;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.security.Principal;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.Collection; import java.util.Collection;
import ca.nrc.cadc.ac.WriterException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.ReaderException; import ca.nrc.cadc.ac.ReaderException;
import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserAlreadyExistsException; import ca.nrc.cadc.ac.UserAlreadyExistsException;
import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.UserRequest; import ca.nrc.cadc.ac.WriterException;
import ca.nrc.cadc.ac.json.JsonUserListWriter; import ca.nrc.cadc.ac.json.JsonUserListWriter;
import ca.nrc.cadc.ac.json.JsonUserReader; import ca.nrc.cadc.ac.json.JsonUserReader;
import ca.nrc.cadc.ac.json.JsonUserRequestReader;
import ca.nrc.cadc.ac.json.JsonUserWriter; import ca.nrc.cadc.ac.json.JsonUserWriter;
import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.ac.server.UserPersistence;
import ca.nrc.cadc.ac.server.web.SyncOutput; import ca.nrc.cadc.ac.server.web.SyncOutput;
import ca.nrc.cadc.ac.xml.UserListWriter; import ca.nrc.cadc.ac.xml.UserListWriter;
import ca.nrc.cadc.ac.xml.UserReader; import ca.nrc.cadc.ac.xml.UserReader;
import ca.nrc.cadc.ac.xml.UserRequestReader;
import ca.nrc.cadc.ac.xml.UserWriter; import ca.nrc.cadc.ac.xml.UserWriter;
import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.net.TransientException;
import ca.nrc.cadc.profiler.Profiler; import ca.nrc.cadc.profiler.Profiler;
...@@ -104,7 +100,7 @@ public abstract class AbstractUserAction implements PrivilegedExceptionAction<Ob ...@@ -104,7 +100,7 @@ public abstract class AbstractUserAction implements PrivilegedExceptionAction<Ob
public static final String JSON_CONTENT_TYPE = "application/json"; public static final String JSON_CONTENT_TYPE = "application/json";
private Profiler profiler = new Profiler(AbstractUserAction.class); private Profiler profiler = new Profiler(AbstractUserAction.class);
protected boolean isAugmentUser; protected boolean isPrivilegedUser;
protected boolean isPrivilegedSubject; protected boolean isPrivilegedSubject;
protected UserLogInfo logInfo; protected UserLogInfo logInfo;
protected SyncOutput syncOut; protected SyncOutput syncOut;
...@@ -114,19 +110,19 @@ public abstract class AbstractUserAction implements PrivilegedExceptionAction<Ob ...@@ -114,19 +110,19 @@ public abstract class AbstractUserAction implements PrivilegedExceptionAction<Ob
AbstractUserAction() AbstractUserAction()
{ {
this.isAugmentUser = false; this.isPrivilegedUser = false;
} }
public abstract void doAction() throws Exception; public abstract void doAction() throws Exception;
public void setAugmentUser(final boolean isAugmentUser) public void setIsPrivilegedUser(boolean isPrivilegedUser)
{ {
this.isAugmentUser = isAugmentUser; this.isPrivilegedUser = isPrivilegedUser;
} }
public boolean isAugmentUser() public boolean isPrivilegedUser()
{ {
return this.isAugmentUser; return this.isPrivilegedUser;
} }
public void setPrivilegedSubject(final boolean isPrivilegedSubject) public void setPrivilegedSubject(final boolean isPrivilegedSubject)
......
...@@ -68,23 +68,36 @@ ...@@ -68,23 +68,36 @@
*/ */
package ca.nrc.cadc.ac.server.web.users; package ca.nrc.cadc.ac.server.web.users;
import ca.nrc.cadc.ac.server.UserPersistence; import java.security.AccessControlException;
import java.security.Principal; import java.security.Principal;
public class DeleteUserAction extends AbstractUserAction public class DeleteUserAction extends AbstractUserAction
{ {
private final Principal userID; private final Principal userID;
private boolean markAsDeleted;
DeleteUserAction(Principal userID) DeleteUserAction(Principal userID, boolean markAsDeleted)
{ {
super(); super();
this.userID = userID; this.userID = userID;
this.markAsDeleted = markAsDeleted;
} }
public void doAction() throws Exception public void doAction() throws Exception
{ {
if (markAsDeleted)
{
userPersistence.deactivateUser(userID);
}
else
{
// only the privileged user can do real deletes
if (!super.isPrivilegedSubject)
{
throw new AccessControlException("Forbidden");
}
userPersistence.deleteUser(userID); userPersistence.deleteUser(userID);
} }
}
} }
...@@ -113,7 +113,7 @@ public class GetUserAction extends AbstractUserAction ...@@ -113,7 +113,7 @@ public class GetUserAction extends AbstractUserAction
* If the calling Subject user is the notAugmentedX500User, AND it is * If the calling Subject user is the notAugmentedX500User, AND it is
* a GET, call the userDAO to get the User with all identities. * a GET, call the userDAO to get the User with all identities.
*/ */
if (isAugmentUser()) if (isPrivilegedUser())
{ {
log.debug("getting augmented user " + principal.getName()); log.debug("getting augmented user " + principal.getName());
user = userPersistence.getAugmentedUser(principal); user = userPersistence.getAugmentedUser(principal);
......
...@@ -203,7 +203,13 @@ public abstract class UserActionFactory ...@@ -203,7 +203,13 @@ public abstract class UserActionFactory
{ {
String userID = NetUtil.decode(segments[0]); String userID = NetUtil.decode(segments[0]);
Principal p = getIdentity(userID, request.getParameter("idType")); Principal p = getIdentity(userID, request.getParameter("idType"));
action = new DeleteUserAction(p); String hardDelete = request.getParameter("hard");
boolean markAsDeleted = true;
if (hardDelete != null && hardDelete.equalsIgnoreCase(Boolean.TRUE.toString()))
{
markAsDeleted = false;
}
action = new DeleteUserAction(p, markAsDeleted);
} }
if (action != null) if (action != null)
......
...@@ -84,12 +84,12 @@ import java.util.Collection; ...@@ -84,12 +84,12 @@ import java.util.Collection;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import ca.nrc.cadc.ac.UserAlreadyExistsException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.junit.Test; import org.junit.Test;
import ca.nrc.cadc.ac.PersonalDetails; import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserAlreadyExistsException;
import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.UserRequest; import ca.nrc.cadc.ac.UserRequest;
import ca.nrc.cadc.auth.DNPrincipal; import ca.nrc.cadc.auth.DNPrincipal;
...@@ -600,7 +600,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest ...@@ -600,7 +600,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest
userDAO.addUserRequest(userRequest); userDAO.addUserRequest(userRequest);
userDAO.approveUserRequest(userID); userDAO.approveUserRequest(userID);
userDAO.deleteUser(userID); userDAO.deleteUser(userID, false);
return null; return null;
} }
...@@ -777,7 +777,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest ...@@ -777,7 +777,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest
} }
// delete the user // delete the user
userDAO.deleteUser(testUser.getHttpPrincipal()); userDAO.deleteUser(testUser.getHttpPrincipal(), false);
// login as deleted user // login as deleted user
try try
...@@ -1042,7 +1042,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest ...@@ -1042,7 +1042,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest
try try
{ {
final LdapUserDAO userDAO = getUserDAO(); final LdapUserDAO userDAO = getUserDAO();
userDAO.deleteUser(userID); userDAO.deleteUser(userID, false);
return null; return null;
} }
......
...@@ -266,7 +266,7 @@ public class GetUserActionTest ...@@ -266,7 +266,7 @@ public class GetUserActionTest
final HttpPrincipal userID = new HttpPrincipal("CADCtest"); final HttpPrincipal userID = new HttpPrincipal("CADCtest");
final GetUserAction testSubject = new GetUserAction(userID, null); final GetUserAction testSubject = new GetUserAction(userID, null);
testSubject.userPersistence = mockUserPersistence; testSubject.userPersistence = mockUserPersistence;
testSubject.setAugmentUser(true); testSubject.setIsPrivilegedUser(true);
final NumericPrincipal numericPrincipal = new NumericPrincipal(UUID.randomUUID()); final NumericPrincipal numericPrincipal = new NumericPrincipal(UUID.randomUUID());
final X500Principal x500Principal = new X500Principal("cn=foo,o=bar"); final X500Principal x500Principal = new X500Principal("cn=foo,o=bar");
......
...@@ -67,14 +67,16 @@ ...@@ -67,14 +67,16 @@
package ca.nrc.cadc.ac.server.web.users; package ca.nrc.cadc.ac.server.web.users;
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;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.easymock.EasyMock; import org.easymock.EasyMock;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import ca.nrc.cadc.util.Log4jInit;
public class UserActionFactoryTest public class UserActionFactoryTest
{ {
...@@ -113,6 +115,7 @@ public class UserActionFactoryTest ...@@ -113,6 +115,7 @@ public class UserActionFactoryTest
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getPathInfo()).andReturn("userName"); EasyMock.expect(request.getPathInfo()).andReturn("userName");
EasyMock.expect(request.getParameter("idType")).andReturn("sessionID"); EasyMock.expect(request.getParameter("idType")).andReturn("sessionID");
EasyMock.expect(request.getParameter("hard")).andReturn(null);
EasyMock.replay(request); EasyMock.replay(request);
AbstractUserAction action = UserActionFactory.httpDeleteFactory().createAction(request); AbstractUserAction action = UserActionFactory.httpDeleteFactory().createAction(request);
EasyMock.verify(request); EasyMock.verify(request);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment