Adding dmp user association, adding finalization status check on persist workflow

This commit is contained in:
Thomas Georgios Giannos 2023-11-13 16:46:35 +02:00
parent ff35ad6aab
commit 5edaf1c74e
8 changed files with 135 additions and 34 deletions

View File

@ -33,6 +33,7 @@ public class AuditableAction {
public static final EventId Dmp_Delete = new EventId(5003, "Dmp_Delete");
public static final EventId Dmp_Clone = new EventId(5004, "Dmp_Clone");
public static final EventId Dmp_PersistNewVersion = new EventId(5005, "Dmp_PersistNewVersion");
public static final EventId Dmp_Assign_Users = new EventId(5006, "Dmp_Assign_Users");
public static final EventId Description_Query = new EventId(6000, "Description_Query");
public static final EventId Description_Lookup = new EventId(6001, "Description_Lookup");

View File

@ -52,6 +52,9 @@ public final class Permission {
public static String DeleteDmp = "DeleteDmp";
public static String CloneDmp = "CloneDmp";
public static String CreateNewVersionDmp = "CreateNewVersionDmp";
public static String ExportDmp = "ExportDmp";
public static String FinalizeDmp = "FinalizeDmp";
public static String AssignDmpUsers = "AssignDmpUsers";
//DmpBlueprint
public static String BrowseDmpBlueprint = "BrowseDmpBlueprint";

View File

@ -0,0 +1,28 @@
package eu.eudat.model.persist;
import eu.eudat.commons.enums.DmpUserRole;
import java.util.UUID;
public class DmpUserPersist {
private UUID user;
private DmpUserRole role;
public UUID getUser() {
return user;
}
public void setUser(UUID user) {
this.user = user;
}
public DmpUserRole getRole() {
return role;
}
public void setRole(DmpUserRole role) {
this.role = role;
}
}

View File

@ -8,22 +8,14 @@ public class QueryResult<M> {
public QueryResult() {
}
public QueryResult(List<M> items, long count, long countOverride) {
this.items = items;
this.count = count;
this.countOverride = countOverride;
}
public QueryResult(List<M> items, long count) {
this.items = items;
this.count = count;
this.countOverride = 0;
}
public QueryResult(M item) {
this.items = List.of(item);
this.count = 1;
this.countOverride = 0;
}
public QueryResult(List<M> items) {
@ -38,8 +30,6 @@ public class QueryResult<M> {
private long count;
private long countOverride;
public List<M> getItems() {
return items;
}
@ -56,14 +46,6 @@ public class QueryResult<M> {
this.count = count;
}
public long getCountOverride() {
return countOverride;
}
public void setCountOverride(long countOverride) {
this.countOverride = countOverride;
}
public static QueryResult<?> empty() {
return new QueryResult<>(new ArrayList<>(), 0L);
}

View File

@ -1,9 +1,11 @@
package eu.eudat.service.dmp;
import com.fasterxml.jackson.core.JsonProcessingException;
import eu.eudat.data.DmpUserEntity;
import eu.eudat.model.Dmp;
import eu.eudat.model.persist.CloneDmpPersist;
import eu.eudat.model.persist.DmpPersist;
import eu.eudat.model.persist.DmpUserPersist;
import eu.eudat.model.persist.NewVersionDmpPersist;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
@ -15,6 +17,7 @@ import jakarta.xml.bind.JAXBException;
import javax.management.InvalidApplicationException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.util.List;
import java.util.UUID;
public interface DmpService {
@ -27,4 +30,6 @@ public interface DmpService {
Dmp buildClone(CloneDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException;
List<DmpUserEntity> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fields) throws InvalidApplicationException;
}

View File

@ -17,13 +17,12 @@ import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.event.DmpTouchedEvent;
import eu.eudat.event.EventBroker;
import eu.eudat.model.Dmp;
import eu.eudat.model.DmpReference;
import eu.eudat.model.DmpUser;
import eu.eudat.model.Reference;
import eu.eudat.model.builder.DmpBuilder;
import eu.eudat.model.deleter.DmpDeleter;
import eu.eudat.model.deleter.DmpDescriptionTemplateDeleter;
import eu.eudat.model.deleter.DmpReferenceDeleter;
import eu.eudat.model.deleter.DmpUserDeleter;
import eu.eudat.model.persist.*;
import eu.eudat.model.persist.referencedefinition.DefinitionPersist;
import eu.eudat.model.persist.referencedefinition.FieldPersist;
@ -121,8 +120,6 @@ public class DmpServiceImpl implements DmpService {
}
public Dmp persist(DmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException {
logger.debug(new MapLogEntry("persisting data dmp").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.EditDmp);
DmpEntity data = this.patchAndSave(model);
@ -146,8 +143,6 @@ public class DmpServiceImpl implements DmpService {
@Override
public Dmp createNewVersion(NewVersionDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException {
logger.debug(new MapLogEntry("persisting data dmp (new version)").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.CreateNewVersionDmp);
DmpEntity oldDmpEntity = this.entityManager.find(DmpEntity.class, model.getId());
@ -239,8 +234,6 @@ public class DmpServiceImpl implements DmpService {
@Override
public Dmp buildClone(CloneDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException {
logger.debug(new MapLogEntry("cloning dmp").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.CloneDmp);
DmpEntity existingDmpEntity = this.queryFactory.query(DmpQuery.class).authorize(AuthorizationFlags.OwnerOrPermissionOrMemberOrPublic).ids(model.getId()).firstAs(fields);
@ -319,6 +312,37 @@ public class DmpServiceImpl implements DmpService {
return this.builderFactory.builder(DmpBuilder.class).build(fields, resultingDmpEntity);
}
@Override
public List<DmpUserEntity> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fieldSet) throws InvalidApplicationException {
this.authorizationService.authorizeForce(Permission.AssignDmpUsers);
List<DmpUserEntity> existingUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(dmp).collect();
for (DmpUserPersist dmpUser : model) {
if (checkUserRoleIfExists(existingUsers, dmp, dmpUser.getUser(), dmpUser.getRole()))
continue;
DmpUserEntity newUser = new DmpUserEntity();
newUser.setId(UUID.randomUUID());
newUser.setDmp(dmp);
newUser.setUser(dmpUser.getUser());
newUser.setRole(dmpUser.getRole());
newUser.setCreatedAt(Instant.now());
newUser.setUpdatedAt(Instant.now());
newUser.setIsActive(IsActive.Active);
this.entityManager.persist(newUser);
}
//If there are still dmp user associations here this means that they were not included in the persist model, so they have to be deleted
if (!existingUsers.isEmpty())
this.deleterFactory.deleter(DmpUserDeleter.class).delete(existingUsers);
this.entityManager.flush();
return this.queryFactory.query(DmpUserQuery.class).dmpIds().collect();
}
private DmpEntity patchAndSave(DmpPersist model) throws JsonProcessingException, InvalidApplicationException {
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
@ -328,7 +352,11 @@ public class DmpServiceImpl implements DmpService {
data = this.entityManager.find(DmpEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (model.getStatus() != null && model.getStatus() == DmpStatus.Finalized && data.getStatus() != DmpStatus.Finalized) {
this.authorizationService.authorizeForce(Permission.FinalizeDmp);
data.setStatus(model.getStatus());
data.setFinalizedAt(Instant.now());
}
} else {
data = new DmpEntity();
data.setId(UUID.randomUUID());
@ -492,4 +520,14 @@ public class DmpServiceImpl implements DmpService {
return data;
}
private boolean checkUserRoleIfExists(List<DmpUserEntity> dmpUserEntities, UUID dmp, UUID user, DmpUserRole role) {
for (DmpUserEntity dmpUser : dmpUserEntities) {
if (dmpUser.getDmp().equals(dmp) && dmpUser.getUser().equals(user) && dmpUser.getRole() == role) {
dmpUserEntities.remove(dmpUser);
return true;
};
}
return false;
}
}

View File

@ -4,11 +4,15 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import eu.eudat.audit.AuditableAction;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.data.DmpEntity;
import eu.eudat.data.DmpUserEntity;
import eu.eudat.model.Dmp;
import eu.eudat.model.DmpUser;
import eu.eudat.model.builder.DmpBuilder;
import eu.eudat.model.builder.DmpUserBuilder;
import eu.eudat.model.censorship.DmpCensor;
import eu.eudat.model.persist.CloneDmpPersist;
import eu.eudat.model.persist.DmpPersist;
import eu.eudat.model.persist.DmpUserPersist;
import eu.eudat.model.persist.NewVersionDmpPersist;
import eu.eudat.model.result.QueryResult;
import eu.eudat.query.DmpQuery;
@ -110,6 +114,7 @@ public class DmpController {
@Transactional
public Dmp Persist(@MyValidate @RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException {
logger.debug(new MapLogEntry("persisting" + Dmp.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
Dmp persisted = this.dmpService.persist(model, fieldSet);
this.auditService.track(AuditableAction.Dmp_Persist, Map.ofEntries(
@ -150,6 +155,7 @@ public class DmpController {
@Transactional
public Dmp createNewVersion(@MyValidate @RequestBody NewVersionDmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, JAXBException, JsonProcessingException, TransformerException, InvalidApplicationException, ParserConfigurationException {
logger.debug(new MapLogEntry("persisting" + NewVersionDmpPersist.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
Dmp persisted = this.dmpService.createNewVersion(model, fieldSet);
this.auditService.track(AuditableAction.Dmp_PersistNewVersion, Map.ofEntries(
@ -160,4 +166,21 @@ public class DmpController {
return persisted;
}
@PostMapping("{id}/assign-users")
@Transactional
public QueryResult<DmpUser> assignUsers(@PathVariable("id") UUID id, @MyValidate @RequestBody List<DmpUserPersist> model, FieldSet fieldSet) throws InvalidApplicationException {
logger.debug(new MapLogEntry("assigning users to dmp").And("model", model).And("fieldSet", fieldSet));
List<DmpUserEntity> persisted = this.dmpService.assignUsers(id, model, fieldSet);
this.auditService.track(AuditableAction.Dmp_Assign_Users, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
List<DmpUser> models = this.builderFactory.builder(DmpUserBuilder.class).build(fieldSet, persisted);
return new QueryResult<>(models);
}
}

View File

@ -263,6 +263,27 @@ permissions:
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
ExportDmp:
roles:
- Admin
claims: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
FinalizeDmp:
roles:
- Admin
claims: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
AssignDmpUsers:
roles:
- Admin
claims: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
# DmpBlueprint
BrowseDmpBlueprint:
roles: