75451: Show custom error message when removing last user from workflow group

This commit is contained in:
Bruno Roemers
2021-01-05 14:48:36 +01:00
parent 250c87dc16
commit c878293b99
5 changed files with 67 additions and 4 deletions

View File

@@ -283,9 +283,7 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
for (Group group: workFlowGroups) { for (Group group: workFlowGroups) {
List<EPerson> ePeople = groupService.allMembers(context, group); List<EPerson> ePeople = groupService.allMembers(context, group);
if (ePeople.size() == 1 && ePeople.contains(ePerson)) { if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
throw new IllegalStateException( throw new EmptyWorkflowGroupException(ePerson.getID(), group.getID());
"Refused to delete user " + ePerson.getID() + " because it the only member of the workflow group"
+ group.getID() + ". Delete the tasks and group first if you want to remove this user.");
} }
} }
// check for presence of eperson in tables that // check for presence of eperson in tables that

View File

@@ -0,0 +1,24 @@
package org.dspace.eperson;
import java.util.UUID;
/**
* <p>This exception class is used to distinguish the following condition:
* EPerson cannot be deleted because that would lead to one (or more)
* workflow groups being empty.</p>
*
* <p>The message of this exception can be disclosed in the REST response to
* provide more granular feedback to the user.</p>
*
* @author Bruno Roemers (bruno.roemers at atmire.com)
*/
public class EmptyWorkflowGroupException extends IllegalStateException {
public EmptyWorkflowGroupException(UUID ePersonId, UUID groupId) {
super(String.format(
"Refused to delete user %s because it is the only member of the workflow group %s. " +
"Delete the tasks and group first if you want to remove this user.", ePersonId, groupId
));
}
}

View File

@@ -98,6 +98,14 @@ public class DSpaceApiExceptionControllerAdvice extends ResponseEntityExceptionH
HttpStatus.UNPROCESSABLE_ENTITY.value()); HttpStatus.UNPROCESSABLE_ENTITY.value());
} }
@ExceptionHandler(RESTEmptyWorkflowGroupException.class)
protected void handleEmptyWorkflowGroupException(HttpServletRequest request, HttpServletResponse response,
Exception ex) throws IOException {
sendErrorResponse(
request, response, null, ex.getLocalizedMessage(), HttpStatus.UNPROCESSABLE_ENTITY.value()
);
}
@ExceptionHandler(QueryMethodParameterConversionException.class) @ExceptionHandler(QueryMethodParameterConversionException.class)
protected void ParameterConversionException(HttpServletRequest request, HttpServletResponse response, Exception ex) protected void ParameterConversionException(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws IOException { throws IOException {

View File

@@ -0,0 +1,29 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.exception;
/**
* <p>Extend {@link UnprocessableEntityException} to provide a specific error message
* in the REST response. The error message is added to the response in
* {@link DSpaceApiExceptionControllerAdvice#handleEmptyWorkflowGroupException}.</p>
*
* <p>Note there is a similarly named error in the DSpace API module.</p>
*
* @author Bruno Roemers (bruno.roemers at atmire.com)
*/
public class RESTEmptyWorkflowGroupException extends UnprocessableEntityException {
public RESTEmptyWorkflowGroupException(String message, Throwable cause) {
super(message, cause);
}
public RESTEmptyWorkflowGroupException(String message) {
super(message);
}
}

View File

@@ -22,6 +22,7 @@ import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.authorization.AuthorizationFeatureService; import org.dspace.app.rest.authorization.AuthorizationFeatureService;
import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.exception.RESTEmptyWorkflowGroupException;
import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.EPersonRest; import org.dspace.app.rest.model.EPersonRest;
import org.dspace.app.rest.model.MetadataRest; import org.dspace.app.rest.model.MetadataRest;
@@ -34,6 +35,7 @@ import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.service.SiteService; import org.dspace.content.service.SiteService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.EmptyWorkflowGroupException;
import org.dspace.eperson.RegistrationData; import org.dspace.eperson.RegistrationData;
import org.dspace.eperson.service.AccountService; import org.dspace.eperson.service.AccountService;
import org.dspace.eperson.service.EPersonService; import org.dspace.eperson.service.EPersonService;
@@ -313,6 +315,8 @@ public class EPersonRestRepository extends DSpaceObjectRestRepository<EPerson, E
es.delete(context, eperson); es.delete(context, eperson);
} catch (SQLException | IOException e) { } catch (SQLException | IOException e) {
throw new RuntimeException(e.getMessage(), e); throw new RuntimeException(e.getMessage(), e);
} catch (EmptyWorkflowGroupException e) {
throw new RESTEmptyWorkflowGroupException(e.getLocalizedMessage(), e);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
throw new UnprocessableEntityException(e.getMessage(), e); throw new UnprocessableEntityException(e.getMessage(), e);
} }