diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java index 8d780a999c8300c129cdc388be51e8dbc2501db2..ede2cd250f4aaf0a6839cd6b84f0b22ad6f67a53 100755 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/UserPersistence.java @@ -238,6 +238,19 @@ public interface UserPersistence throws UserNotFoundException, TransientException, 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. * diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java index 698899a1fe2ef4ed3576e0c7fc2fffdefd276cc1..f857f1be5c6307741074ab1e27d8910b913e6731 100755 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java @@ -1069,11 +1069,11 @@ public class LdapUserDAO extends LdapDAO * @throws TransientException If an temporary, unexpected problem occurred. * @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, AccessControlException { - deleteUser(userID, config.getUsersDN(), true); + deleteUser(userID, config.getUsersDN(), markDelete); } /** diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java index 8711e52ee445883a2a49171d89f75b903cfe519b..c24c02c121884e1cfc021b67dae9fe98acdca90e 100755 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserPersistence.java @@ -402,7 +402,7 @@ public class LdapUserPersistence extends LdapPersistence implements UserPersiste * @throws TransientException If an temporary, unexpected problem occurred. * @throws AccessControlException If the operation is not permitted. */ - public void deleteUser(Principal userID) + public void deactivateUser(Principal userID) throws UserNotFoundException, TransientException, AccessControlException { @@ -415,7 +415,36 @@ public class LdapUserPersistence extends LdapPersistence implements UserPersiste try { 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 { diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/UserServlet.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/UserServlet.java index 931a1db38617edcdd61538d904d1097230808bc2..7f212ab3fdbdac02303a4c993092152251afa22a 100644 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/UserServlet.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/UserServlet.java @@ -84,12 +84,12 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import ca.nrc.cadc.ac.server.web.users.CreateUserAction; import org.apache.log4j.Logger; import ca.nrc.cadc.ac.server.PluginFactory; import ca.nrc.cadc.ac.server.UserPersistence; 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.UserActionFactory; import ca.nrc.cadc.ac.server.web.users.UserLogInfo; @@ -186,6 +186,17 @@ public class UserServlet extends HttpServlet Subject subject; Subject privilegedSubject = getPrivilegedSubject(request); 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, // AND it is a PUT request, throw an AccessControlException @@ -194,7 +205,6 @@ public class UserServlet extends HttpServlet profiler.checkpoint("check non-privileged user"); if (privilegedSubject == null) { - action.setPrivilegedSubject(false); subject = AuthenticationUtil.getSubject(request); logInfo.setSubject(subject); log.debug("augmented subject: " + subject); @@ -202,7 +212,6 @@ public class UserServlet extends HttpServlet } else { - action.setPrivilegedSubject(true); log.debug("subject not augmented: " + privilegedSubject); subject = privilegedSubject; logInfo.setSubject(privilegedSubject); @@ -214,11 +223,8 @@ public class UserServlet extends HttpServlet // AND it is a GET request, do not augment the subject. else if (action instanceof GetUserAction && privilegedSubject != null) { - profiler.checkpoint("check privileged user"); subject = Subject.getSubject(AccessController.getContext()); log.debug("subject not augmented: " + subject); - action.setAugmentUser(true); - logInfo.setSubject(privilegedSubject); profiler.checkpoint("set privileged user"); } else diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java index b582a04b7ca31a4faadfcdfd8fd299bb31c93b46..c8a007aee7930201e2e5f379e447a91d410fd290 100644 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/AbstractUserAction.java @@ -72,27 +72,23 @@ import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.security.AccessControlException; -import java.security.Principal; import java.security.PrivilegedExceptionAction; import java.util.Collection; -import ca.nrc.cadc.ac.WriterException; import org.apache.log4j.Logger; import ca.nrc.cadc.ac.ReaderException; import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserAlreadyExistsException; 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.JsonUserReader; -import ca.nrc.cadc.ac.json.JsonUserRequestReader; import ca.nrc.cadc.ac.json.JsonUserWriter; import ca.nrc.cadc.ac.server.UserPersistence; import ca.nrc.cadc.ac.server.web.SyncOutput; import ca.nrc.cadc.ac.xml.UserListWriter; 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.net.TransientException; import ca.nrc.cadc.profiler.Profiler; @@ -104,7 +100,7 @@ public abstract class AbstractUserAction implements PrivilegedExceptionAction<Ob public static final String JSON_CONTENT_TYPE = "application/json"; private Profiler profiler = new Profiler(AbstractUserAction.class); - protected boolean isAugmentUser; + protected boolean isPrivilegedUser; protected boolean isPrivilegedSubject; protected UserLogInfo logInfo; protected SyncOutput syncOut; @@ -114,19 +110,19 @@ public abstract class AbstractUserAction implements PrivilegedExceptionAction<Ob AbstractUserAction() { - this.isAugmentUser = false; + this.isPrivilegedUser = false; } 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) diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java index 7bd80ebedc199d1ba090fd5d2da28698ea063543..1c220f78af2a8d2f58b863251a68c10ad7f2fbe1 100644 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/DeleteUserAction.java @@ -68,23 +68,36 @@ */ package ca.nrc.cadc.ac.server.web.users; -import ca.nrc.cadc.ac.server.UserPersistence; - +import java.security.AccessControlException; import java.security.Principal; public class DeleteUserAction extends AbstractUserAction { private final Principal userID; + private boolean markAsDeleted; - DeleteUserAction(Principal userID) + DeleteUserAction(Principal userID, boolean markAsDeleted) { super(); this.userID = userID; + this.markAsDeleted = markAsDeleted; } public void doAction() throws Exception { - userPersistence.deleteUser(userID); + if (markAsDeleted) + { + userPersistence.deactivateUser(userID); + } + else + { + // only the privileged user can do real deletes + if (!super.isPrivilegedSubject) + { + throw new AccessControlException("Forbidden"); + } + userPersistence.deleteUser(userID); + } } } diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java index 58a96e7af40974cd78aa51075bbf0f49d33e7c9f..d9e9feb8979b44cfba0ac231ca313a650dd0db6a 100644 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java @@ -113,7 +113,7 @@ public class GetUserAction extends AbstractUserAction * If the calling Subject user is the notAugmentedX500User, AND it is * a GET, call the userDAO to get the User with all identities. */ - if (isAugmentUser()) + if (isPrivilegedUser()) { log.debug("getting augmented user " + principal.getName()); user = userPersistence.getAugmentedUser(principal); diff --git a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java index dc3cdc2505a64ed00c55caa4ade24a5ebd6cc35c..e2a8f7ac45e09d7e52610c5cf91c8d51eb36d6c9 100644 --- a/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java +++ b/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UserActionFactory.java @@ -203,7 +203,13 @@ public abstract class UserActionFactory { String userID = NetUtil.decode(segments[0]); 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) diff --git a/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java b/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java index a2dcbe2a82df8d6d3b772b35a187f01acbb71dc1..bf3d3c484057c4ef897ce1e03c79d1e5887106cb 100644 --- a/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java +++ b/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java @@ -84,12 +84,12 @@ import java.util.Collection; import javax.security.auth.Subject; import javax.security.auth.x500.X500Principal; -import ca.nrc.cadc.ac.UserAlreadyExistsException; import org.apache.log4j.Logger; import org.junit.Test; import ca.nrc.cadc.ac.PersonalDetails; import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserAlreadyExistsException; import ca.nrc.cadc.ac.UserNotFoundException; import ca.nrc.cadc.ac.UserRequest; import ca.nrc.cadc.auth.DNPrincipal; @@ -600,7 +600,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest userDAO.addUserRequest(userRequest); userDAO.approveUserRequest(userID); - userDAO.deleteUser(userID); + userDAO.deleteUser(userID, false); return null; } @@ -777,7 +777,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest } // delete the user - userDAO.deleteUser(testUser.getHttpPrincipal()); + userDAO.deleteUser(testUser.getHttpPrincipal(), false); // login as deleted user try @@ -1042,7 +1042,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest try { final LdapUserDAO userDAO = getUserDAO(); - userDAO.deleteUser(userID); + userDAO.deleteUser(userID, false); return null; } diff --git a/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java b/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java index 1eed5e782e2f96dc550678a87c67c9764cfa87d3..70493c2d9b528b93a7c9158bfd36947b1c15c251 100644 --- a/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java +++ b/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserActionTest.java @@ -266,7 +266,7 @@ public class GetUserActionTest final HttpPrincipal userID = new HttpPrincipal("CADCtest"); final GetUserAction testSubject = new GetUserAction(userID, null); testSubject.userPersistence = mockUserPersistence; - testSubject.setAugmentUser(true); + testSubject.setIsPrivilegedUser(true); final NumericPrincipal numericPrincipal = new NumericPrincipal(UUID.randomUUID()); final X500Principal x500Principal = new X500Principal("cn=foo,o=bar"); diff --git a/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java b/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java index 2f3ae849c27cb8387fc781c6ecb15e0d1d03ebb8..a705944eb520913f48b6135d09629181dbdb6ec5 100644 --- a/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java +++ b/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UserActionFactoryTest.java @@ -67,14 +67,16 @@ package ca.nrc.cadc.ac.server.web.users; -import ca.nrc.cadc.util.Log4jInit; import javax.servlet.http.HttpServletRequest; + import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.junit.Assert; import org.junit.Test; +import ca.nrc.cadc.util.Log4jInit; + public class UserActionFactoryTest { @@ -113,6 +115,7 @@ public class UserActionFactoryTest HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); EasyMock.expect(request.getPathInfo()).andReturn("userName"); EasyMock.expect(request.getParameter("idType")).andReturn("sessionID"); + EasyMock.expect(request.getParameter("hard")).andReturn(null); EasyMock.replay(request); AbstractUserAction action = UserActionFactory.httpDeleteFactory().createAction(request); EasyMock.verify(request);