description use storage file
This commit is contained in:
parent
fd974d3ee4
commit
f7dc3e5a32
|
@ -48,6 +48,9 @@ public class AuditableAction {
|
||||||
public static final EventId Description_PublicQuery = new EventId(6004, "Description_PublicQuery");
|
public static final EventId Description_PublicQuery = new EventId(6004, "Description_PublicQuery");
|
||||||
public static final EventId Description_PublicLookup = new EventId(6005, "Description_PublicLookup");
|
public static final EventId Description_PublicLookup = new EventId(6005, "Description_PublicLookup");
|
||||||
public static final EventId Description_PersistStatus = new EventId(6006, "Description_PersistStatus");
|
public static final EventId Description_PersistStatus = new EventId(6006, "Description_PersistStatus");
|
||||||
|
public static final EventId Description_UploadFieldFiles = new EventId(6007, "Description_UploadFieldFiles");
|
||||||
|
public static final EventId Description_GetFieldFile = new EventId(6008, "Description_GetFieldFile");
|
||||||
|
|
||||||
|
|
||||||
public static final EventId Reference_Query = new EventId(7000, "Reference_Query");
|
public static final EventId Reference_Query = new EventId(7000, "Reference_Query");
|
||||||
public static final EventId Reference_Lookup = new EventId(7001, "Reference_Lookup");
|
public static final EventId Reference_Lookup = new EventId(7001, "Reference_Lookup");
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package eu.eudat.model.persist;
|
||||||
|
|
||||||
|
import eu.eudat.commons.validation.BaseValidator;
|
||||||
|
import eu.eudat.convention.ConventionService;
|
||||||
|
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
||||||
|
import gr.cite.tools.validation.specification.Specification;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class DescriptionFieldFilePersist {
|
||||||
|
|
||||||
|
private UUID descriptionTemplateId;
|
||||||
|
|
||||||
|
public static final String _descriptionTemplateId = "descriptionTemplateId";
|
||||||
|
|
||||||
|
private String fieldId;
|
||||||
|
|
||||||
|
public static final String _fieldId = "fieldId";
|
||||||
|
|
||||||
|
public UUID getDescriptionTemplateId() {
|
||||||
|
return descriptionTemplateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescriptionTemplateId(UUID descriptionTemplateId) {
|
||||||
|
this.descriptionTemplateId = descriptionTemplateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldId() {
|
||||||
|
return fieldId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldId(String fieldId) {
|
||||||
|
this.fieldId = fieldId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component(PersistValidator.ValidatorName)
|
||||||
|
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public static class PersistValidator extends BaseValidator<DescriptionFieldFilePersist> {
|
||||||
|
|
||||||
|
public static final String ValidatorName = "DescriptionFieldFilePersistValidator";
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
protected PersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
|
||||||
|
super(conventionService, errors);
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<DescriptionFieldFilePersist> modelClass() {
|
||||||
|
return DescriptionFieldFilePersist.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Specification> specifications(DescriptionFieldFilePersist item) {
|
||||||
|
return Arrays.asList(
|
||||||
|
this.spec()
|
||||||
|
.must(() -> this.isValidGuid(item.getDescriptionTemplateId()))
|
||||||
|
.failOn(DescriptionFieldFilePersist._descriptionTemplateId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionFieldFilePersist._descriptionTemplateId}, LocaleContextHolder.getLocale())),
|
||||||
|
this.spec()
|
||||||
|
.must(() -> !this.isEmpty(item.getFieldId()))
|
||||||
|
.failOn(DescriptionFieldFilePersist._fieldId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionFieldFilePersist._fieldId}, LocaleContextHolder.getLocale()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package eu.eudat.service.description;
|
package eu.eudat.service.description;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import eu.eudat.data.StorageFileEntity;
|
||||||
import eu.eudat.model.Description;
|
import eu.eudat.model.Description;
|
||||||
|
import eu.eudat.model.StorageFile;
|
||||||
|
import eu.eudat.model.persist.DescriptionFieldFilePersist;
|
||||||
import eu.eudat.model.persist.DescriptionPersist;
|
import eu.eudat.model.persist.DescriptionPersist;
|
||||||
import eu.eudat.model.persist.DescriptionStatusPersist;
|
import eu.eudat.model.persist.DescriptionStatusPersist;
|
||||||
import gr.cite.tools.exception.MyApplicationException;
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
@ -10,6 +12,7 @@ import gr.cite.tools.exception.MyNotFoundException;
|
||||||
import gr.cite.tools.exception.MyValidationException;
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -26,5 +29,6 @@ public interface DescriptionService {
|
||||||
|
|
||||||
ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException;
|
ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException;
|
||||||
|
|
||||||
|
StorageFile uploadFieldFile(DescriptionFieldFilePersist model, MultipartFile file, FieldSet fields) throws IOException;
|
||||||
|
StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.eudat.commons.scope.user.UserScope;
|
||||||
import eu.eudat.commons.types.description.*;
|
import eu.eudat.commons.types.description.*;
|
||||||
import eu.eudat.commons.types.descriptionreference.DescriptionReferenceDataEntity;
|
import eu.eudat.commons.types.descriptionreference.DescriptionReferenceDataEntity;
|
||||||
import eu.eudat.commons.types.descriptiontemplate.FieldSetEntity;
|
import eu.eudat.commons.types.descriptiontemplate.FieldSetEntity;
|
||||||
import eu.eudat.commons.types.dmpreference.DmpReferenceDataEntity;
|
import eu.eudat.commons.types.descriptiontemplate.fielddata.UploadDataEntity;
|
||||||
import eu.eudat.commons.types.notification.*;
|
import eu.eudat.commons.types.notification.*;
|
||||||
import eu.eudat.commons.types.reference.DefinitionEntity;
|
import eu.eudat.commons.types.reference.DefinitionEntity;
|
||||||
import eu.eudat.configurations.notification.NotificationProperties;
|
import eu.eudat.configurations.notification.NotificationProperties;
|
||||||
|
@ -23,35 +23,33 @@ import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
||||||
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
||||||
import eu.eudat.model.*;
|
import eu.eudat.model.*;
|
||||||
import eu.eudat.model.builder.DescriptionBuilder;
|
import eu.eudat.model.builder.DescriptionBuilder;
|
||||||
|
import eu.eudat.model.builder.StorageFileBuilder;
|
||||||
import eu.eudat.model.deleter.DescriptionDeleter;
|
import eu.eudat.model.deleter.DescriptionDeleter;
|
||||||
import eu.eudat.model.deleter.DescriptionReferenceDeleter;
|
import eu.eudat.model.deleter.DescriptionReferenceDeleter;
|
||||||
import eu.eudat.model.deleter.DescriptionTagDeleter;
|
import eu.eudat.model.deleter.DescriptionTagDeleter;
|
||||||
import eu.eudat.model.file.FileEnvelope;
|
import eu.eudat.model.file.FileEnvelope;
|
||||||
import eu.eudat.model.persist.DescriptionPersist;
|
import eu.eudat.model.persist.*;
|
||||||
import eu.eudat.model.persist.DescriptionReferencePersist;
|
|
||||||
import eu.eudat.model.persist.DescriptionStatusPersist;
|
|
||||||
import eu.eudat.model.persist.ReferencePersist;
|
|
||||||
import eu.eudat.model.persist.descriptionproperties.*;
|
import eu.eudat.model.persist.descriptionproperties.*;
|
||||||
import eu.eudat.model.persist.descriptionreference.DescriptionReferenceDataPersist;
|
import eu.eudat.model.persist.descriptionreference.DescriptionReferenceDataPersist;
|
||||||
import eu.eudat.model.persist.dmpreference.DmpReferenceDataPersist;
|
|
||||||
import eu.eudat.model.persist.referencedefinition.DefinitionPersist;
|
import eu.eudat.model.persist.referencedefinition.DefinitionPersist;
|
||||||
import eu.eudat.query.*;
|
import eu.eudat.query.*;
|
||||||
import eu.eudat.service.elastic.ElasticService;
|
import eu.eudat.service.elastic.ElasticService;
|
||||||
|
import eu.eudat.service.storage.StorageFileProperties;
|
||||||
|
import eu.eudat.service.storage.StorageFileService;
|
||||||
import eu.eudat.service.transformer.FileTransformerService;
|
import eu.eudat.service.transformer.FileTransformerService;
|
||||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
import gr.cite.tools.data.deleter.DeleterFactory;
|
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||||
import gr.cite.tools.data.query.Ordering;
|
import gr.cite.tools.data.query.Ordering;
|
||||||
import gr.cite.tools.data.query.QueryFactory;
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
import gr.cite.tools.exception.MyApplicationException;
|
import gr.cite.tools.exception.*;
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
|
||||||
import gr.cite.tools.exception.MyNotFoundException;
|
|
||||||
import gr.cite.tools.exception.MyValidationException;
|
|
||||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
import gr.cite.tools.logging.LoggerService;
|
import gr.cite.tools.logging.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
|
import gr.cite.tools.validation.ValidatorFactory;
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -62,10 +60,14 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.unit.DataSize;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -74,52 +76,41 @@ import java.util.stream.Collectors;
|
||||||
public class DescriptionServiceImpl implements DescriptionService {
|
public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionServiceImpl.class));
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionServiceImpl.class));
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
|
||||||
private final AuthorizationService authorizationService;
|
private final AuthorizationService authorizationService;
|
||||||
|
|
||||||
private final DeleterFactory deleterFactory;
|
private final DeleterFactory deleterFactory;
|
||||||
|
|
||||||
private final BuilderFactory builderFactory;
|
private final BuilderFactory builderFactory;
|
||||||
|
|
||||||
private final ConventionService conventionService;
|
private final ConventionService conventionService;
|
||||||
|
|
||||||
private final ErrorThesaurusProperties errors;
|
private final ErrorThesaurusProperties errors;
|
||||||
|
|
||||||
private final MessageSource messageSource;
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
private final EventBroker eventBroker;
|
private final EventBroker eventBroker;
|
||||||
|
|
||||||
private final QueryFactory queryFactory;
|
private final QueryFactory queryFactory;
|
||||||
|
|
||||||
private final JsonHandlingService jsonHandlingService;
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
private final UserScope userScope;
|
private final UserScope userScope;
|
||||||
private final XmlHandlingService xmlHandlingService;
|
private final XmlHandlingService xmlHandlingService;
|
||||||
private final FileTransformerService fileTransformerService;
|
private final FileTransformerService fileTransformerService;
|
||||||
|
|
||||||
private final NotifyIntegrationEventHandler eventHandler;
|
private final NotifyIntegrationEventHandler eventHandler;
|
||||||
|
|
||||||
private final NotificationProperties notificationProperties;
|
private final NotificationProperties notificationProperties;
|
||||||
|
|
||||||
private final ElasticService elasticService;
|
private final ElasticService elasticService;
|
||||||
|
private final ValidatorFactory validatorFactory;
|
||||||
|
private final StorageFileProperties storageFileConfig;
|
||||||
|
private final StorageFileService storageFileService;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DescriptionServiceImpl(
|
public DescriptionServiceImpl(
|
||||||
EntityManager entityManager,
|
EntityManager entityManager,
|
||||||
AuthorizationService authorizationService,
|
AuthorizationService authorizationService,
|
||||||
DeleterFactory deleterFactory,
|
DeleterFactory deleterFactory,
|
||||||
BuilderFactory builderFactory,
|
BuilderFactory builderFactory,
|
||||||
ConventionService conventionService,
|
ConventionService conventionService,
|
||||||
ErrorThesaurusProperties errors,
|
ErrorThesaurusProperties errors,
|
||||||
MessageSource messageSource,
|
MessageSource messageSource,
|
||||||
EventBroker eventBroker,
|
EventBroker eventBroker,
|
||||||
QueryFactory queryFactory,
|
QueryFactory queryFactory,
|
||||||
JsonHandlingService jsonHandlingService,
|
JsonHandlingService jsonHandlingService,
|
||||||
UserScope userScope,
|
UserScope userScope,
|
||||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService) {
|
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
@ -136,6 +127,9 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
this.notificationProperties = notificationProperties;
|
this.notificationProperties = notificationProperties;
|
||||||
this.fileTransformerService = fileTransformerService;
|
this.fileTransformerService = fileTransformerService;
|
||||||
this.elasticService = elasticService;
|
this.elasticService = elasticService;
|
||||||
|
this.validatorFactory = validatorFactory;
|
||||||
|
this.storageFileConfig = storageFileConfig;
|
||||||
|
this.storageFileService = storageFileService;
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Persist
|
//region Persist
|
||||||
|
@ -405,7 +399,15 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
FieldEntity data = new FieldEntity();
|
FieldEntity data = new FieldEntity();
|
||||||
if (persist == null) return data;
|
if (persist == null) return data;
|
||||||
|
|
||||||
if (FieldType.isTextType(fieldType)) data.setTextValue(persist.getTextValue());
|
if (FieldType.isTextType(fieldType)) {
|
||||||
|
if (FieldType.UPLOAD.equals(fieldType)){
|
||||||
|
StorageFile storageFile = this.storageFileService.copyToStorage(UUID.fromString(persist.getTextValue()), StorageType.Main, true, new BaseFieldSet().ensure(StorageFile._id));
|
||||||
|
this.storageFileService.updatePurgeAt(storageFile.getId(), null);
|
||||||
|
data.setTextValue(storageFile.getId().toString());
|
||||||
|
} else {
|
||||||
|
data.setTextValue(persist.getTextValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue());
|
else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue());
|
||||||
else if (FieldType.isTextListType(fieldType)) data.setTextListValue(persist.getTextListValue());
|
else if (FieldType.isTextListType(fieldType)) data.setTextListValue(persist.getTextListValue());
|
||||||
else if (FieldType.isExternalIdentifierType(fieldType) && persist.getExternalIdentifier() != null) data.setExternalIdentifier(this.buildExternalIdentifierEntity(persist.getExternalIdentifier()));
|
else if (FieldType.isExternalIdentifierType(fieldType) && persist.getExternalIdentifier() != null) data.setExternalIdentifier(this.buildExternalIdentifierEntity(persist.getExternalIdentifier()));
|
||||||
|
@ -702,14 +704,78 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException {
|
public ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
String type = exportType;
|
|
||||||
|
|
||||||
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(id, type);
|
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(id, exportType);
|
||||||
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
|
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
|
||||||
byte[] data = Files.readAllBytes(fileEnvelope.getFile().toPath());
|
byte[] data = Files.readAllBytes(fileEnvelope.getFile().toPath());
|
||||||
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||||
return new ResponseEntity<>(data, headers, HttpStatus.OK);
|
return new ResponseEntity<>(data, headers, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StorageFile uploadFieldFile(DescriptionFieldFilePersist model, MultipartFile file, FieldSet fields) throws IOException {
|
||||||
|
this.authorizationService.authorizeForce(Permission.EditDescription);
|
||||||
|
|
||||||
|
DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).ids(model.getDescriptionTemplateId()).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).first();
|
||||||
|
if (descriptionTemplate == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
eu.eudat.commons.types.descriptiontemplate.DefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(eu.eudat.commons.types.descriptiontemplate.DefinitionEntity.class, descriptionTemplate.getDefinition());
|
||||||
|
if (definition == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDescriptionTemplateId(), eu.eudat.commons.types.descriptiontemplate.DefinitionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
eu.eudat.commons.types.descriptiontemplate.FieldEntity fieldEntity = definition.getFieldById(model.getFieldId()).stream().filter(x -> x != null && x.getData() != null && x.getData().getFieldType().equals(FieldType.UPLOAD)).findFirst().orElse(null);
|
||||||
|
if (fieldEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getFieldId(), eu.eudat.commons.types.descriptiontemplate.FieldEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
UploadDataEntity uploadDataEntity = (UploadDataEntity)fieldEntity.getData();
|
||||||
|
if (DataSize.ofBytes(file.getSize()).equals(DataSize.ofMegabytes(uploadDataEntity.getMaxFileSizeInMB()))) {
|
||||||
|
throw new MyValidationException("The uploaded file is too large");
|
||||||
|
}
|
||||||
|
if(!this.conventionService.isListNullOrEmpty(uploadDataEntity.getTypes())) {
|
||||||
|
boolean isContentTypeAccepted = false;
|
||||||
|
for (UploadDataEntity.UploadDataOptionEntity option: uploadDataEntity.getTypes()) {
|
||||||
|
if(Objects.equals(file.getContentType(), option.getValue())) {
|
||||||
|
isContentTypeAccepted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isContentTypeAccepted){
|
||||||
|
throw new MyValidationException("The uploaded file has an unaccepted type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StorageFilePersist storageFilePersist = new StorageFilePersist();
|
||||||
|
storageFilePersist.setName(FilenameUtils.removeExtension(file.getName()));
|
||||||
|
storageFilePersist.setExtension(FilenameUtils.getExtension(file.getName()));
|
||||||
|
storageFilePersist.setMimeType(URLConnection.guessContentTypeFromName(file.getName()));
|
||||||
|
storageFilePersist.setOwnerId(this.userScope.getUserIdSafe());
|
||||||
|
storageFilePersist.setStorageType(StorageType.Temp);
|
||||||
|
storageFilePersist.setLifetime(Duration.ofSeconds(this.storageFileConfig.getTempStoreLifetimeSeconds()));
|
||||||
|
this.validatorFactory.validator(StorageFilePersist.StorageFilePersistValidator.class).validateForce(storageFilePersist);
|
||||||
|
return this.storageFileService.persistBytes(storageFilePersist, file.getBytes(), BaseFieldSet.build(fields, StorageFile._id, StorageFile._name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId) {
|
||||||
|
this.authorizationService.authorizeForce(Permission.BrowseDescription);
|
||||||
|
DescriptionEntity descriptionEntity = this.queryFactory.query(DescriptionQuery.class).isActive(IsActive.Active).ids(descriptionId).first();
|
||||||
|
if (descriptionEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
DmpDescriptionTemplateEntity dmpDescriptionTemplateEntity = this.queryFactory.query(DmpDescriptionTemplateQuery.class).ids(descriptionEntity.getDmpDescriptionTemplateId()).isActive(IsActive.Active).first();
|
||||||
|
if (dmpDescriptionTemplateEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionEntity.getDmpDescriptionTemplateId(), DmpDescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
DmpEntity dmpEntity = this.queryFactory.query(DmpQuery.class).ids(dmpDescriptionTemplateEntity.getDmpId()).isActive(IsActive.Active).first();
|
||||||
|
if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{dmpDescriptionTemplateEntity.getDmpId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
if (!dmpEntity.getAccessType().equals(DmpAccessType.Public))
|
||||||
|
{
|
||||||
|
boolean isDmpUser = this.queryFactory.query(DmpUserQuery.class).dmpIds(dmpEntity.getId()).userIds(this.userScope.getUserIdSafe()).isActives(IsActive.Active).count() > 0;
|
||||||
|
if (!isDmpUser) throw new MyUnauthorizedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageFileEntity storageFile = this.queryFactory.query(StorageFileQuery.class).ids(storageFileId).first();
|
||||||
|
if (storageFile == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{storageFileId, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
return storageFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ import java.util.UUID;
|
||||||
public interface StorageFileService extends ApplicationListener<ApplicationReadyEvent> {
|
public interface StorageFileService extends ApplicationListener<ApplicationReadyEvent> {
|
||||||
StorageFile persistBytes(StorageFilePersist model, byte[] payload, FieldSet fields) throws IOException;
|
StorageFile persistBytes(StorageFilePersist model, byte[] payload, FieldSet fields) throws IOException;
|
||||||
StorageFile persistString(StorageFilePersist model, String payload, FieldSet fields, Charset charset) throws IOException;
|
StorageFile persistString(StorageFilePersist model, String payload, FieldSet fields, Charset charset) throws IOException;
|
||||||
boolean moveToStorage(UUID fileId, StorageType storageType);
|
StorageFile moveToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields);
|
||||||
boolean copyToStorage(UUID fileId, StorageType storageType);
|
StorageFile copyToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields);
|
||||||
|
|
||||||
boolean exists(UUID fileId);
|
boolean exists(UUID fileId);
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class StorageFileServiceImpl implements StorageFileService {
|
||||||
|
|
||||||
this.entityManager.persist(storageFile);
|
this.entityManager.persist(storageFile);
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
return this.builderFactory.builder(StorageFileBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Description._id), storageFile);
|
return this.builderFactory.builder(StorageFileBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, StorageFile._id), storageFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -104,6 +104,7 @@ public class StorageFileServiceImpl implements StorageFileService {
|
||||||
private StorageFileEntity buildDataEntry(StorageFilePersist model) {
|
private StorageFileEntity buildDataEntry(StorageFilePersist model) {
|
||||||
|
|
||||||
StorageFileEntity data = new StorageFileEntity();
|
StorageFileEntity data = new StorageFileEntity();
|
||||||
|
data.setId(UUID.randomUUID());
|
||||||
data.setFileRef(UUID.randomUUID().toString().replaceAll("-", "").toLowerCase(Locale.ROOT));
|
data.setFileRef(UUID.randomUUID().toString().replaceAll("-", "").toLowerCase(Locale.ROOT));
|
||||||
data.setName(model.getName());
|
data.setName(model.getName());
|
||||||
data.setOwnerId(model.getOwnerId());
|
data.setOwnerId(model.getOwnerId());
|
||||||
|
@ -117,42 +118,74 @@ public class StorageFileServiceImpl implements StorageFileService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean moveToStorage(UUID fileId, StorageType storageType) {
|
public StorageFile moveToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields) {
|
||||||
try {
|
try {
|
||||||
StorageFileEntity storageFile = this.entityManager.find(StorageFileEntity.class, fileId);
|
StorageFileEntity storageFile = this.entityManager.find(StorageFileEntity.class, fileId);
|
||||||
if (storageFile == null) return false;
|
if (storageFile == null) return null;
|
||||||
|
|
||||||
this.authorizeForce(storageFile, StorageFilePermission.Read);
|
this.authorizeForce(storageFile, StorageFilePermission.Read);
|
||||||
|
|
||||||
File file = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
File file = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
||||||
if (!file.exists()) return false;
|
if (!file.exists()) return null;
|
||||||
|
|
||||||
File destinationFile = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
File destinationFile = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
||||||
|
if (file.exists() && !replaceDestination) return null;
|
||||||
|
|
||||||
boolean fileCopied = FileCopyUtils.copy(file, destinationFile) > 0;
|
boolean fileCopied = FileCopyUtils.copy(file, destinationFile) > 0;
|
||||||
if (!fileCopied) return false;
|
if (!fileCopied) return null;
|
||||||
return file.delete();
|
|
||||||
|
storageFile.setStorageType(storageType);
|
||||||
|
|
||||||
|
this.entityManager.merge(storageFile);
|
||||||
|
|
||||||
|
file.delete();
|
||||||
|
|
||||||
|
this.entityManager.merge(storageFile);
|
||||||
|
return this.builderFactory.builder(StorageFileBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, StorageFile._id), storageFile);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
logger.warn("problem reading byte content of storage file " + fileId, ex);
|
logger.warn("problem reading byte content of storage file " + fileId, ex);
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean copyToStorage(UUID fileId, StorageType storageType) {
|
public StorageFile copyToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields) {
|
||||||
try {
|
try {
|
||||||
StorageFileEntity storageFile = this.entityManager.find(StorageFileEntity.class, fileId);
|
StorageFileEntity storageFile = this.entityManager.find(StorageFileEntity.class, fileId);
|
||||||
if (storageFile == null) return false;
|
if (storageFile == null) return null;
|
||||||
|
|
||||||
this.authorizeForce(storageFile, StorageFilePermission.Read);
|
this.authorizeForce(storageFile, StorageFilePermission.Read);
|
||||||
|
|
||||||
File file = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
File file = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
||||||
if (!file.exists()) return false;
|
if (!file.exists()) return null;
|
||||||
|
|
||||||
|
File destinationFile = new File(this.filePath(storageFile.getFileRef(), storageType));
|
||||||
|
if (file.exists() && !replaceDestination) return null;
|
||||||
|
|
||||||
|
boolean fileCopied = FileCopyUtils.copy(file, destinationFile) > 0;
|
||||||
|
if (!fileCopied) return null;
|
||||||
|
|
||||||
|
StorageFileEntity data = new StorageFileEntity();
|
||||||
|
data.setId(UUID.randomUUID());
|
||||||
|
data.setFileRef(storageFile.getFileRef());
|
||||||
|
data.setName(storageFile.getName());
|
||||||
|
data.setOwnerId(storageFile.getOwnerId());
|
||||||
|
data.setExtension(storageFile.getExtension());
|
||||||
|
data.setStorageType(storageFile.getStorageType());
|
||||||
|
data.setMimeType(storageFile.getMimeType());
|
||||||
|
data.setCreatedAt(Instant.now());
|
||||||
|
data.setPurgeAt(storageFile.getPurgeAt());
|
||||||
|
|
||||||
|
this.entityManager.persist(data);
|
||||||
|
|
||||||
|
this.entityManager.merge(storageFile);
|
||||||
|
return this.builderFactory.builder(StorageFileBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, StorageFile._id), storageFile);
|
||||||
|
|
||||||
File destinationFile = new File(this.filePath(storageFile.getFileRef(), storageFile.getStorageType()));
|
|
||||||
return FileCopyUtils.copy(file, destinationFile) > 0;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
logger.warn("problem reading byte content of storage file " + fileId, ex);
|
logger.warn("problem reading byte content of storage file " + fileId, ex);
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
package eu.eudat.controllers.v2;
|
package eu.eudat.controllers.v2;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import eu.eudat.audit.AuditableAction;
|
import eu.eudat.audit.AuditableAction;
|
||||||
import eu.eudat.authorization.AuthorizationFlags;
|
import eu.eudat.authorization.AuthorizationFlags;
|
||||||
|
import eu.eudat.authorization.Permission;
|
||||||
import eu.eudat.commons.enums.DmpAccessType;
|
import eu.eudat.commons.enums.DmpAccessType;
|
||||||
import eu.eudat.commons.enums.DmpStatus;
|
import eu.eudat.commons.enums.DmpStatus;
|
||||||
import eu.eudat.commons.enums.IsActive;
|
import eu.eudat.commons.enums.IsActive;
|
||||||
|
import eu.eudat.commons.enums.StorageType;
|
||||||
|
import eu.eudat.convention.ConventionService;
|
||||||
|
import eu.eudat.data.StorageFileEntity;
|
||||||
|
import eu.eudat.model.StorageFile;
|
||||||
|
import eu.eudat.model.persist.DescriptionFieldFilePersist;
|
||||||
|
import eu.eudat.model.persist.StorageFilePersist;
|
||||||
|
import eu.eudat.service.storage.StorageFileService;
|
||||||
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
||||||
import eu.eudat.model.Description;
|
import eu.eudat.model.Description;
|
||||||
import eu.eudat.model.Dmp;
|
import eu.eudat.model.Dmp;
|
||||||
|
@ -21,7 +29,6 @@ import eu.eudat.query.DmpQuery;
|
||||||
import eu.eudat.query.lookup.DescriptionLookup;
|
import eu.eudat.query.lookup.DescriptionLookup;
|
||||||
import eu.eudat.service.description.DescriptionService;
|
import eu.eudat.service.description.DescriptionService;
|
||||||
import eu.eudat.service.elastic.ElasticQueryHelperService;
|
import eu.eudat.service.elastic.ElasticQueryHelperService;
|
||||||
import eu.eudat.service.transformer.FileTransformerService;
|
|
||||||
import gr.cite.tools.auditing.AuditService;
|
import gr.cite.tools.auditing.AuditService;
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
import gr.cite.tools.data.censor.CensorFactory;
|
import gr.cite.tools.data.censor.CensorFactory;
|
||||||
|
@ -32,15 +39,22 @@ import gr.cite.tools.exception.MyNotFoundException;
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
import gr.cite.tools.logging.LoggerService;
|
import gr.cite.tools.logging.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static eu.eudat.authorization.AuthorizationFlags.Public;
|
import static eu.eudat.authorization.AuthorizationFlags.Public;
|
||||||
|
@ -63,14 +77,16 @@ public class DescriptionController {
|
||||||
|
|
||||||
private final MessageSource messageSource;
|
private final MessageSource messageSource;
|
||||||
private final ElasticQueryHelperService elasticQueryHelperService;
|
private final ElasticQueryHelperService elasticQueryHelperService;
|
||||||
|
private final StorageFileService storageFileService;
|
||||||
|
private final ConventionService conventionService;
|
||||||
public DescriptionController(
|
public DescriptionController(
|
||||||
BuilderFactory builderFactory,
|
BuilderFactory builderFactory,
|
||||||
AuditService auditService,
|
AuditService auditService,
|
||||||
DescriptionService descriptionService,
|
DescriptionService descriptionService,
|
||||||
CensorFactory censorFactory,
|
CensorFactory censorFactory,
|
||||||
QueryFactory queryFactory,
|
QueryFactory queryFactory,
|
||||||
MessageSource messageSource,
|
MessageSource messageSource,
|
||||||
ElasticQueryHelperService elasticQueryHelperService) {
|
ElasticQueryHelperService elasticQueryHelperService, StorageFileService storageFileService, ConventionService conventionService) {
|
||||||
this.builderFactory = builderFactory;
|
this.builderFactory = builderFactory;
|
||||||
this.auditService = auditService;
|
this.auditService = auditService;
|
||||||
this.descriptionService = descriptionService;
|
this.descriptionService = descriptionService;
|
||||||
|
@ -78,6 +94,8 @@ public class DescriptionController {
|
||||||
this.queryFactory = queryFactory;
|
this.queryFactory = queryFactory;
|
||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
this.elasticQueryHelperService = elasticQueryHelperService;
|
this.elasticQueryHelperService = elasticQueryHelperService;
|
||||||
|
this.storageFileService = storageFileService;
|
||||||
|
this.conventionService = conventionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("public/query")
|
@PostMapping("public/query")
|
||||||
|
@ -192,4 +210,41 @@ public class DescriptionController {
|
||||||
|
|
||||||
return this.descriptionService.export(id, exportType);
|
return this.descriptionService.export(id, exportType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("field-file/upload")
|
||||||
|
@Transactional
|
||||||
|
@ValidationFilterAnnotation(validator = DescriptionFieldFilePersist.PersistValidator.ValidatorName, argumentName = "model")
|
||||||
|
public StorageFile uploadFieldFiles(@RequestParam("file") MultipartFile file, @RequestParam("model") DescriptionFieldFilePersist model, FieldSet fieldSet) throws IOException {
|
||||||
|
logger.debug(new MapLogEntry("uploadFieldFiles" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
|
||||||
|
StorageFile persisted = this.descriptionService.uploadFieldFile(model, file, fieldSet);
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Description_UploadFieldFiles, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("model", model),
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
|
||||||
|
));
|
||||||
|
|
||||||
|
return persisted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("{id}/field-file/{fileId}")
|
||||||
|
public ResponseEntity<ByteArrayResource> getFieldFile(@PathVariable("id") UUID id, @PathVariable("fileId") UUID fileId) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||||
|
logger.debug(new MapLogEntry("get Field File" + Description.class.getSimpleName()).And("id", id).And("fileId", fileId));
|
||||||
|
|
||||||
|
StorageFileEntity storageFile = this.descriptionService.getFieldFile(id, fileId);
|
||||||
|
|
||||||
|
byte[] file = this.storageFileService.readAsBytesSafe(id);
|
||||||
|
if (file == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Description_GetFieldFile, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("id", id)
|
||||||
|
));
|
||||||
|
|
||||||
|
String contentType = storageFile.getMimeType();
|
||||||
|
if (this.conventionService.isNullOrEmpty(contentType)) contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||||
|
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.contentType(MediaType.valueOf(contentType))
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + storageFile.getName() + (storageFile.getExtension().startsWith(".") ? "" : ".") + storageFile.getExtension() + "\"")
|
||||||
|
.body(new ByteArrayResource(file));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue