Skip to content

Commit

Permalink
Merge branch 'develop' into 6634-primefaces8
Browse files Browse the repository at this point in the history
  • Loading branch information
sekmiller committed Apr 1, 2020
2 parents 0d69f3b + b4f5bdf commit efd356a
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 22 deletions.
15 changes: 15 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2806,6 +2806,21 @@ Make User a SuperUser
Toggles superuser mode on the ``AuthenticatedUser`` whose ``identifier`` (without the ``@`` sign) is passed. ::
POST http://$SERVER/api/admin/superuser/$identifier
Delete a User
~~~~~~~~~~~~~
Deletes an ``AuthenticatedUser`` whose ``identifier`` (without the ``@`` sign) is passed. ::
DELETE http://$SERVER/api/admin/authenticatedUsers/$identifier
Deletes an ``AuthenticatedUser`` whose ``id`` is passed. ::
DELETE http://$SERVER/api/admin/authenticatedUsers/id/$id
Note: If the user has performed certain actions such as creating or contributing to a Dataset or downloading a file they cannot be deleted.
List Role Assignments of a Role Assignee
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import edu.harvard.iq.dataverse.DataverseRoleServiceBean;
import edu.harvard.iq.dataverse.DataverseServiceBean;
import edu.harvard.iq.dataverse.DvObject;
import edu.harvard.iq.dataverse.DvObjectServiceBean;
import edu.harvard.iq.dataverse.EjbDataverseEngine;
import edu.harvard.iq.dataverse.GuestbookResponseServiceBean;
import edu.harvard.iq.dataverse.MapLayerMetadataServiceBean;
import edu.harvard.iq.dataverse.MetadataBlock;
import edu.harvard.iq.dataverse.MetadataBlockServiceBean;
Expand Down Expand Up @@ -238,6 +240,12 @@ String getWrappedMessageWhenJson() {

@EJB
MetricsServiceBean metricsSvc;

@EJB
DvObjectServiceBean dvObjSvc;

@EJB
GuestbookResponseServiceBean gbRespSvc;

@PersistenceContext(unitName = "VDCNet-ejbPU")
protected EntityManager em;
Expand Down
68 changes: 48 additions & 20 deletions src/main/java/edu/harvard/iq/dataverse/api/Admin.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
import edu.harvard.iq.dataverse.authorization.AuthTestDataServiceBean;
import edu.harvard.iq.dataverse.authorization.RoleAssignee;
import edu.harvard.iq.dataverse.authorization.UserRecordIdentifier;
import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.dataset.DatasetThumbnail;
import edu.harvard.iq.dataverse.dataset.DatasetUtil;
Expand Down Expand Up @@ -136,6 +137,11 @@ public class Admin extends AbstractApiBean {
GroupServiceBean groupService;
@EJB
SettingsServiceBean settingsService;
@EJB
DatasetVersionServiceBean datasetVersionService;
@EJB
ExplicitGroupServiceBean explicitGroupService;


// Make the session available
@Inject
Expand Down Expand Up @@ -324,18 +330,48 @@ public Response getAuthenticatedUser(@PathParam("identifier") String identifier)
return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found.");
}

@DELETE
@Path("authenticatedUsers/{identifier}/")
public Response deleteAuthenticatedUser(@PathParam("identifier") String identifier) {
AuthenticatedUser user = authSvc.getAuthenticatedUser(identifier);
if (user != null) {
authSvc.deleteAuthenticatedUser(user.getId());
return ok("AuthenticatedUser " + identifier + " deleted. ");
}
return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found.");
}
@DELETE
@Path("authenticatedUsers/{identifier}/")
public Response deleteAuthenticatedUser(@PathParam("identifier") String identifier) {
AuthenticatedUser user = authSvc.getAuthenticatedUser(identifier);
if (user != null) {
return deleteAuthenticatedUser(user);
}
return error(Response.Status.BAD_REQUEST, "User " + identifier + " not found.");
}

@DELETE
@Path("authenticatedUsers/id/{id}/")
public Response deleteAuthenticatedUserById(@PathParam("id") Long id) {
AuthenticatedUser user = authSvc.findByID(id);
if (user != null) {
return deleteAuthenticatedUser(user);
}
return error(Response.Status.BAD_REQUEST, "User " + id + " not found.");
}

private Response deleteAuthenticatedUser(AuthenticatedUser au) {

//getDeleteUserErrorMessages does all of the tests to see
//if the user is 'deletable' if it returns an empty string the user
//can be safely deleted.

String errorMessages = authSvc.getDeleteUserErrorMessages(au);

if (!errorMessages.isEmpty()) {
return badRequest(errorMessages);
}

//if the user is deletable we will delete access requests and group membership
// many-to-many relationships that couldn't be cascade deleted
authSvc.removeAuthentictedUserItems(au);

authSvc.deleteAuthenticatedUser(au.getId());
return ok("AuthenticatedUser " + au.getIdentifier() + " deleted. ");

}



@POST
@Path("publishDataverseAsCreator/{id}")
Expand Down Expand Up @@ -811,16 +847,8 @@ public Response builtin2oauth(String content) {
return ok(response);
}

@DELETE
@Path("authenticatedUsers/id/{id}/")
public Response deleteAuthenticatedUserById(@PathParam("id") Long id) {
AuthenticatedUser user = authSvc.findByID(id);
if (user != null) {
authSvc.deleteAuthenticatedUser(user.getId());
return ok("AuthenticatedUser " + id + " deleted. ");
}
return error(Response.Status.BAD_REQUEST, "User " + id + " not found.");
}



@Path("roles")
@POST
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package edu.harvard.iq.dataverse.authorization;

import edu.harvard.iq.dataverse.DatasetVersionServiceBean;
import edu.harvard.iq.dataverse.DvObjectServiceBean;
import edu.harvard.iq.dataverse.GuestbookResponseServiceBean;
import edu.harvard.iq.dataverse.RoleAssigneeServiceBean;
import edu.harvard.iq.dataverse.UserNotificationServiceBean;
import edu.harvard.iq.dataverse.UserServiceBean;
import edu.harvard.iq.dataverse.authorization.providers.oauth2.oidc.OIDCAuthenticationProviderFactory;
Expand All @@ -9,6 +13,8 @@
import edu.harvard.iq.dataverse.authorization.exceptions.AuthenticationFailedException;
import edu.harvard.iq.dataverse.authorization.exceptions.AuthenticationProviderFactoryNotFoundException;
import edu.harvard.iq.dataverse.authorization.exceptions.AuthorizationSetupException;
import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroup;
import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean;
import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderFactory;
import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderRow;
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinAuthenticationProvider;
Expand All @@ -26,9 +32,12 @@
import edu.harvard.iq.dataverse.confirmemail.ConfirmEmailServiceBean;
import edu.harvard.iq.dataverse.passwordreset.PasswordResetData;
import edu.harvard.iq.dataverse.passwordreset.PasswordResetServiceBean;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean;
import edu.harvard.iq.dataverse.workflows.WorkflowComment;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
Expand All @@ -40,6 +49,7 @@
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.EJBException;
Expand Down Expand Up @@ -102,6 +112,21 @@ public class AuthenticationServiceBean {

@EJB
PasswordValidatorServiceBean passwordValidatorService;

@EJB
DvObjectServiceBean dvObjSvc;

@EJB
RoleAssigneeServiceBean roleAssigneeSvc;

@EJB
GuestbookResponseServiceBean gbRespSvc;

@EJB
DatasetVersionServiceBean datasetVersionService;

@EJB
ExplicitGroupServiceBean explicitGroupService;

@PersistenceContext(unitName = "VDCNet-ejbPU")
private EntityManager em;
Expand Down Expand Up @@ -511,6 +536,68 @@ public AuthenticatedUser lookupUser( String apiToken ) {
return tkn.getAuthenticatedUser();
}

/*
getDeleteUserErrorMessages( AuthenticatedUser au )
method which checks for reasons that a user may not be deleted
-has created dvObjects
-has roles
-has guestbook records
An empty string is returned if the user is 'deletable'
*/

public String getDeleteUserErrorMessages(AuthenticatedUser au) {
String retVal = "";
List<String> reasons= new ArrayList();
if (!dvObjSvc.findByAuthenticatedUserId(au).isEmpty()) {
reasons.add(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.dvobjects"));
}

if (!roleAssigneeSvc.getAssignmentsFor(au.getIdentifier()).isEmpty()) {
reasons.add(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.roleAssignments"));
}

if (!gbRespSvc.findByAuthenticatedUserId(au).isEmpty()) {
reasons.add( BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.gbResps"));
}

if (!datasetVersionService.getDatasetVersionUsersByAuthenticatedUser(au).isEmpty()) {
reasons.add(BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.versionUser"));
}

if (!reasons.isEmpty()) {
retVal = BundleUtil.getStringFromBundle("admin.api.deleteUser.failure.prefix", Arrays.asList(au.getIdentifier()));
retVal += " " + reasons.stream().collect(Collectors.joining("; ")) + ".";
}



return retVal;
}

public void removeAuthentictedUserItems(AuthenticatedUser au){
/* if the user has pending access requests, is the member of a group or
we will delete them here
*/

deletePendingAccessRequests(au);


if (!explicitGroupService.findGroups(au).isEmpty()) {
for(ExplicitGroup explicitGroup: explicitGroupService.findGroups(au)){
explicitGroup.removeByRoleAssgineeIdentifier(au.getIdentifier());
}
}

}

private void deletePendingAccessRequests(AuthenticatedUser au){

em.createNativeQuery("delete from fileaccessrequests where authenticated_user_id = "+au.getId()).executeUpdate();

}


public AuthenticatedUser save( AuthenticatedUser user ) {
em.persist(user);
em.flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import edu.harvard.iq.dataverse.Cart;
import edu.harvard.iq.dataverse.DatasetLock;
import edu.harvard.iq.dataverse.UserNotification;
import edu.harvard.iq.dataverse.ValidateEmail;
import edu.harvard.iq.dataverse.authorization.AccessRequest;
import edu.harvard.iq.dataverse.authorization.AuthenticatedUserDisplayInfo;
import edu.harvard.iq.dataverse.authorization.AuthenticatedUserLookup;
import edu.harvard.iq.dataverse.userdata.UserUtil;
import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.OrcidOAuth2AP;
import edu.harvard.iq.dataverse.util.BundleUtil;
import static edu.harvard.iq.dataverse.util.StringUtil.nonEmpty;
import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder;
import edu.harvard.iq.dataverse.worldmapauth.WorldMapToken;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
Expand Down Expand Up @@ -124,6 +127,40 @@ public String getIdentifier() {
return IDENTIFIER_PREFIX + userIdentifier;
}

@OneToMany(mappedBy = "dataverseUser", cascade={CascadeType.REMOVE})
private List<WorldMapToken> worldMapTokens;

public List<WorldMapToken> getWorldMapTokens() {
return worldMapTokens;
}

public void setWorldMapTokens(List<WorldMapToken> worldMapTokens) {
this.worldMapTokens = worldMapTokens;
}

@OneToMany(mappedBy = "user", cascade={CascadeType.REMOVE})
private List<UserNotification> notifications;

public List<UserNotification> getUserNotifications() {
return notifications;
}

public void setUserNotifications(List<UserNotification> notifications) {
this.notifications = notifications;
}

@OneToMany(mappedBy = "requestor", cascade={CascadeType.REMOVE})
private List<UserNotification> requests;

public List<UserNotification> getUserRequests() {
return requests;
}

public void setUserRequestss(List<UserNotification> requests) {
this.requests = requests;
}


@OneToMany(mappedBy = "user", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
private List<DatasetLock> datasetLocks;

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2222,6 +2222,14 @@ admin.api.migrateHDL.failure.must.be.hdl.dataset=Dataset was not registered as a
admin.api.migrateHDL.success=Dataset migrate HDL registration complete. Dataset re-registered successfully.
admin.api.migrateHDL.failure=Failed to migrate Dataset Handle id: {0}
admin.api.migrateHDL.failureWithException=Failed to migrate Dataset Handle id: {0} Unexpected exception: {1}
admin.api.deleteUser.failure.prefix=Could not delete Authenticated User {0} because
admin.api.deleteUser.failure.dvobjects= the user has created Dataverse object(s)
admin.api.deleteUser.failure.gbResps= the user is associated with file download (Guestbook Response) record(s)
admin.api.deleteUser.failure.roleAssignments=the user is associated with role assignment record(s)
admin.api.deleteUser.failure.versionUser=the user has contributed to dataset version(s)
admin.api.deleteUser.failure.groupMember=the user is a member of Explicit Group(s)
admin.api.deleteUser.failure.pendingRequests=the user has pending File Access Request(s)
admin.api.deleteUser.success=Authenticated User {0} deleted.

#Datasets.java
datasets.api.updatePIDMetadata.failure.dataset.must.be.released=Modify Registration Metadata must be run on a published dataset.
Expand Down
Loading

0 comments on commit efd356a

Please sign in to comment.