Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Diamantis Tziotzios 2023-12-04 18:26:31 +02:00
commit a72c7001f9
12 changed files with 171 additions and 61 deletions

View File

@ -34,7 +34,8 @@ public class AuditableAction {
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 Dmp_RemoveUser = new EventId(5007, "Dmp_RemoveUser");
public static final EventId Description_Query = new EventId(6000, "Description_Query");
public static final EventId Description_Lookup = new EventId(6001, "Description_Lookup");
public static final EventId Description_Persist = new EventId(6002, "Description_Persist");

View File

@ -25,12 +25,13 @@ public class DmpEntity implements DataEntity<DmpEntity, UUID> {
public static final String _id = "id";
@Column(name = "label")
@Column(name = "label", length = DescriptionEntity._labelLength, nullable = false)
private String label;
public static final String _label = "label";
public static final int _labelLength = 250;
@Column(name = "version")
@Column(name = "version", nullable = false)
private Short version;
public static final String _version = "version";
@ -41,38 +42,38 @@ public class DmpEntity implements DataEntity<DmpEntity, UUID> {
public static final String _versionStatus = "versionStatus";
@Column(name = "status")
@Column(name = "status", nullable = false)
@Convert(converter = DmpStatusConverter.class)
private DmpStatus status;
public static final String _status = "status";
@Column(name = "properties", nullable = false)
@Column(name = "properties", nullable = true)
private String properties;
public static final String _properties = "properties";
@Column(name = "group_id", columnDefinition = "BINARY(16)")
@Column(name = "group_id", nullable = false)
private UUID groupId;
public static final String _groupId = "groupId";
@Column(name = "description", nullable = false)
@Column(name = "description", nullable = true)
private String description;
public static final String _description = "description";
@Column(name = "created_at")
@Column(name = "created_at", nullable = false)
private Instant createdAt;
public static final String _createdAt = "createdAt";
@Column(name = "updated_at")
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
public static final String _updatedAt = "updatedAt";
@Column(name = "is_active")
@Column(name = "is_active", nullable = false)
@Convert(converter = IsActiveConverter.class)
private IsActive isActive;
@ -83,28 +84,28 @@ public class DmpEntity implements DataEntity<DmpEntity, UUID> {
public static final String _finalizedAt = "finalizedAt";
@Column(name = "creator")
@Column(name = "creator", nullable = false)
private UUID creatorId;
public static final String _creatorId = "creatorId";
@Column(name = "access_type", nullable = false)
@Column(name = "access_type", nullable = true)
@Convert(converter = DmpAccessTypeNullableConverter.class)
private DmpAccessType accessType;
public static final String _accessType = "accessType";
@Column(name = "blueprint")
@Column(name = "blueprint", nullable = false)
private UUID blueprintId;
public static final String _blueprintId = "blueprintId";
@Column(name = "language", nullable = false)
@Column(name = "language", nullable = true)
private String language;
public static final String _language = "language";
@Column(name = "public_after", nullable = false)
@Column(name = "public_after", nullable = true)
private Instant publicAfter;
public static final String _publicAfter = "publicAfter";

View File

@ -2,33 +2,54 @@ package eu.eudat.model.persist;
import eu.eudat.commons.enums.DmpAccessType;
import eu.eudat.commons.enums.DmpStatus;
import eu.eudat.commons.validation.FieldNotNullIfOtherSet;
import eu.eudat.commons.validation.ValidEnum;
import eu.eudat.commons.validation.ValidId;
import eu.eudat.data.DescriptionEntity;
import eu.eudat.data.DmpEntity;
import eu.eudat.model.persist.dmpproperties.DmpPropertiesPersist;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.util.List;
import java.util.UUID;
@FieldNotNullIfOtherSet(message = "{validation.hashempty}")
public class DmpPersist {
@ValidId(message = "{validation.invalidid}")
private UUID id;
@NotNull(message = "{validation.empty}")
@NotEmpty(message = "{validation.empty}")
@Size(max = DmpEntity._labelLength, message = "{validation.largerthanmax}")
private String label;
@ValidEnum(message = "{validation.empty}")
private DmpStatus status;
@NotNull(message = "{validation.empty}")
private DmpPropertiesPersist properties;
private String description;
private String language;
@NotNull(message = "{validation.empty}")
@ValidId(message = "{validation.invalidid}")
private UUID blueprint;
private DmpAccessType accessType;
@NotNull(message = "{validation.empty}")
@Valid
private List<DmpReferencePersist> references;
@NotNull(message = "{validation.empty}")
@Valid
private List<DmpDescriptionTemplatePersist> descriptionTemplates;
private String hash;

View File

@ -0,0 +1,57 @@
package eu.eudat.model.persist;
import eu.eudat.commons.enums.DmpAccessType;
import eu.eudat.commons.enums.DmpStatus;
import eu.eudat.commons.enums.DmpUserRole;
import eu.eudat.commons.validation.FieldNotNullIfOtherSet;
import eu.eudat.commons.validation.ValidEnum;
import eu.eudat.commons.validation.ValidId;
import eu.eudat.data.DmpEntity;
import eu.eudat.model.persist.dmpproperties.DmpPropertiesPersist;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.util.List;
import java.util.UUID;
public class DmpUserRemovePersist {
@NotNull(message = "{validation.empty}")
@ValidId(message = "{validation.invalidid}")
private UUID id;
@NotNull(message = "{validation.empty}")
@ValidId(message = "{validation.invalidid}")
private UUID dmpId;
@NotNull(message = "{validation.empty}")
@ValidEnum(message = "{validation.empty}")
private DmpUserRole role;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getDmpId() {
return dmpId;
}
public void setDmpId(UUID dmpId) {
this.dmpId = dmpId;
}
public DmpUserRole getRole() {
return role;
}
public void setRole(DmpUserRole role) {
this.role = role;
}
}

View File

@ -258,11 +258,11 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
}
if (this.dmpDescriptionTemplateQuery != null) {
QueryContext<DmpDescriptionTemplateEntity, UUID> subQuery = this.applySubQuery(this.dmpDescriptionTemplateQuery, queryContext, UUID.class, DmpDescriptionTemplate._id);
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpDescriptionTemplateId)).value(subQuery));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpDescriptionTemplateId)).value(subQuery.Query));
}
if (this.dmpQuery != null) {
QueryContext<DmpEntity, UUID> subQuery = this.applySubQuery(this.dmpQuery, queryContext, UUID.class, Dmp._id);
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpId)).value(subQuery));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpId)).value(subQuery.Query));
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);

View File

@ -289,7 +289,7 @@ public class DmpQuery extends QueryBase<DmpEntity> {
if (this.dmpDescriptionTemplateQuery != null) {
QueryContext<DmpDescriptionTemplateEntity, UUID> subQuery = this.applySubQuery(this.dmpDescriptionTemplateQuery, queryContext, UUID.class, DmpDescriptionTemplate._dmp);
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpDescriptionTemplateId)).value(subQuery));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._dmpDescriptionTemplateId)).value(subQuery.Query));
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);

View File

@ -5,8 +5,10 @@ import eu.eudat.authorization.Permission;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.data.*;
import eu.eudat.model.DmpDescriptionTemplate;
import eu.eudat.model.User;
import eu.eudat.model.PublicUser;
import eu.eudat.model.UserRole;
import eu.eudat.query.utils.BuildSubQueryInput;
import eu.eudat.query.utils.QueryUtilsService;
import gr.cite.commons.web.authz.service.AuthorizationService;
@ -194,9 +196,8 @@ public class UserQuery extends QueryBase<UserEntity> {
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(userContactInfoSubquery));
}
if (this.userRoleQuery != null) {
Subquery<UserRoleEntity> subQuery = queryContext.Query.subquery(this.userRoleQuery.entityClass());
this.applySubQuery(this.userRoleQuery, queryContext.CriteriaBuilder, subQuery);
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(subQuery));
QueryContext<UserRoleEntity, UUID> subQuery = this.applySubQuery(this.userRoleQuery, queryContext, UUID.class, UserRole._user);
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(subQuery.Query));
}

View File

@ -175,6 +175,7 @@ public class UserRoleQuery extends QueryBase<UserRoleEntity> {
if (item.match(UserRole._id)) return UserRoleEntity._id;
else if (item.match(UserRole._role)) return UserRoleEntity._role;
else if (item.prefix(UserRole._user)) return UserRoleEntity._userId;
else if (item.match(UserRole._user)) return UserRoleEntity._userId;
else if (item.match(UserRole._createdAt) ) return UserRoleEntity._createdAt;
else return null;
}

View File

@ -30,7 +30,7 @@ public class DmpLookup extends Lookup {
private List<Integer> versions;
private DmpDescriptionTemplateQuery dmpDescriptionTemplateSubQuery;
private DmpDescriptionTemplateLookup dmpDescriptionTemplateSubQuery;
public String getLike() {
return like;
@ -96,11 +96,11 @@ public class DmpLookup extends Lookup {
this.versionStatuses = versionStatuses;
}
public DmpDescriptionTemplateQuery getDmpDescriptionTemplateSubQuery() {
public DmpDescriptionTemplateLookup getDmpDescriptionTemplateSubQuery() {
return dmpDescriptionTemplateSubQuery;
}
public void setDmpDescriptionTemplateSubQuery(DmpDescriptionTemplateQuery dmpDescriptionTemplateSubQuery) {
public void setDmpDescriptionTemplateSubQuery(DmpDescriptionTemplateLookup dmpDescriptionTemplateSubQuery) {
this.dmpDescriptionTemplateSubQuery = dmpDescriptionTemplateSubQuery;
}
@ -114,7 +114,7 @@ public class DmpLookup extends Lookup {
if (this.statuses != null) query.statuses(this.statuses);
if (this.versions != null) query.versions(this.versions);
if (this.versionStatuses != null) query.versionStatuses(this.versionStatuses);
if (this.dmpDescriptionTemplateSubQuery != null) query.dmpDescriptionTemplateSubQuery(this.dmpDescriptionTemplateSubQuery);
if (this.dmpDescriptionTemplateSubQuery != null) query.dmpDescriptionTemplateSubQuery(this.dmpDescriptionTemplateSubQuery.enrich(queryFactory));
this.enrichCommon(query);

View File

@ -3,10 +3,8 @@ 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 eu.eudat.model.DmpUser;
import eu.eudat.model.persist.*;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
@ -36,7 +34,8 @@ 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;
List<DmpUser> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fields) throws InvalidApplicationException;
Dmp removeUser(DmpUserRemovePersist model, FieldSet fields) throws InvalidApplicationException;
ResponseEntity<byte[]> export(UUID id, DmpExportType exportType);

View File

@ -18,8 +18,10 @@ import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.event.DmpTouchedEvent;
import eu.eudat.event.EventBroker;
import eu.eudat.model.Dmp;
import eu.eudat.model.DmpUser;
import eu.eudat.model.Reference;
import eu.eudat.model.builder.DmpBuilder;
import eu.eudat.model.builder.DmpUserBuilder;
import eu.eudat.model.deleter.*;
import eu.eudat.model.persist.*;
import eu.eudat.model.persist.dmpproperties.DmpBlueprintValuePersist;
@ -319,7 +321,7 @@ public class DmpServiceImpl implements DmpService {
}
@Override
public List<DmpUserEntity> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fieldSet) throws InvalidApplicationException {
public List<DmpUser> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fieldSet) throws InvalidApplicationException {
this.authorizationService.authorizeForce(Permission.AssignDmpUsers);
List<DmpUserEntity> existingUsers = this.queryFactory.query(DmpUserQuery.class)
@ -327,32 +329,50 @@ public class DmpServiceImpl implements DmpService {
.isActives(IsActive.Active)
.collect();
List<UUID> updatedCreatedIds = new ArrayList<>();
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.setUserId(dmpUser.getUser());
newUser.setRole(dmpUser.getRole());
newUser.setCreatedAt(Instant.now());
newUser.setUpdatedAt(Instant.now());
newUser.setIsActive(IsActive.Active);
this.entityManager.persist(newUser);
DmpUserEntity dmpUserEntity = existingUsers.stream().filter(x-> x.getDmp().equals(dmp) && x.getUserId().equals(dmpUser.getUser()) && x.getRole().equals(dmpUser.getRole())).findFirst().orElse(null);
if (dmpUserEntity == null){
dmpUserEntity = new DmpUserEntity();
dmpUserEntity.setId(UUID.randomUUID());
dmpUserEntity.setDmp(dmp);
dmpUserEntity.setUserId(dmpUser.getUser());
dmpUserEntity.setRole(dmpUser.getRole());
dmpUserEntity.setCreatedAt(Instant.now());
dmpUserEntity.setUpdatedAt(Instant.now());
dmpUserEntity.setIsActive(IsActive.Active);
this.entityManager.persist(dmpUserEntity);
}
updatedCreatedIds.add(dmpUserEntity.getUserId());
}
//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);
List<DmpUserEntity> toDelete = existingUsers.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
if (!toDelete.isEmpty()) this.deleterFactory.deleter(DmpUserDeleter.class).delete(toDelete);
this.entityManager.flush();
return this.queryFactory.query(DmpUserQuery.class)
List<DmpUserEntity> persisted = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(dmp)
.isActives(IsActive.Active)
.collect();
return this.builderFactory.builder(DmpUserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fieldSet, DmpUser._id, DmpUser._hash), persisted);
}
@Override
public Dmp removeUser(DmpUserRemovePersist model, FieldSet fields) throws InvalidApplicationException {
this.authorizationService.authorizeForce(Permission.AssignDmpUsers);
DmpEntity 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()));
List<DmpUserEntity> existingUsers = this.queryFactory.query(DmpUserQuery.class)
.dmpIds(model.getDmpId()).ids(model.getId()).userRoles(model.getRole())
.collect();
if (!existingUsers.isEmpty()) this.deleterFactory.deleter(DmpUserDeleter.class).delete(existingUsers);
this.entityManager.flush();
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
}
@Override
@ -582,14 +602,13 @@ public class DmpServiceImpl implements DmpService {
return data;
}
private boolean checkUserRoleIfExists(List<DmpUserEntity> dmpUserEntities, UUID dmp, UUID user, DmpUserRole role) {
private DmpUserEntity checkUserRoleIfExists(List<DmpUserEntity> dmpUserEntities, UUID dmp, UUID user, DmpUserRole role) {
for (DmpUserEntity dmpUser : dmpUserEntities) {
if (dmpUser.getDmp().equals(dmp) && dmpUser.getUserId().equals(user) && dmpUser.getRole() == role) {
dmpUserEntities.remove(dmpUser);
return true;
return dmpUser;
};
}
return false;
return null;
}
}

View File

@ -10,10 +10,7 @@ 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.persist.*;
import eu.eudat.model.result.QueryResult;
import eu.eudat.query.DmpQuery;
import eu.eudat.query.lookup.DmpLookup;
@ -173,16 +170,29 @@ public class DmpController {
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);
List<DmpUser> 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)
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<>(persisted);
}
return new QueryResult<>(models);
@PostMapping("remove-user")
@Transactional
public QueryResult<Dmp> removeUser(@MyValidate @RequestBody DmpUserRemovePersist model, FieldSet fieldSet) throws InvalidApplicationException {
logger.debug(new MapLogEntry("remove user from dmp").And("model", model).And("fieldSet", fieldSet));
Dmp persisted = this.dmpService.removeUser(model, fieldSet);
this.auditService.track(AuditableAction.Dmp_RemoveUser, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return new QueryResult<>(persisted);
}
@GetMapping("{id}/export/{type}")