description use storage file

This commit is contained in:
Efstratios Giannopoulos 2024-02-06 15:03:49 +02:00
parent fd974d3ee4
commit f7dc3e5a32
7 changed files with 302 additions and 67 deletions

View File

@ -48,7 +48,10 @@ public class AuditableAction {
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_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_Lookup = new EventId(7001, "Reference_Lookup");
public static final EventId Reference_Persist = new EventId(7002, "Reference_Persist");

View File

@ -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()))
);
}
}
}

View File

@ -1,7 +1,9 @@
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.StorageFile;
import eu.eudat.model.persist.DescriptionFieldFilePersist;
import eu.eudat.model.persist.DescriptionPersist;
import eu.eudat.model.persist.DescriptionStatusPersist;
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.fieldset.FieldSet;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import javax.management.InvalidApplicationException;
import java.io.IOException;
@ -26,5 +29,6 @@ public interface DescriptionService {
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);
}

View File

@ -10,7 +10,7 @@ import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.commons.types.description.*;
import eu.eudat.commons.types.descriptionreference.DescriptionReferenceDataEntity;
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.reference.DefinitionEntity;
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.model.*;
import eu.eudat.model.builder.DescriptionBuilder;
import eu.eudat.model.builder.StorageFileBuilder;
import eu.eudat.model.deleter.DescriptionDeleter;
import eu.eudat.model.deleter.DescriptionReferenceDeleter;
import eu.eudat.model.deleter.DescriptionTagDeleter;
import eu.eudat.model.file.FileEnvelope;
import eu.eudat.model.persist.DescriptionPersist;
import eu.eudat.model.persist.DescriptionReferencePersist;
import eu.eudat.model.persist.DescriptionStatusPersist;
import eu.eudat.model.persist.ReferencePersist;
import eu.eudat.model.persist.*;
import eu.eudat.model.persist.descriptionproperties.*;
import eu.eudat.model.persist.descriptionreference.DescriptionReferenceDataPersist;
import eu.eudat.model.persist.dmpreference.DmpReferenceDataPersist;
import eu.eudat.model.persist.referencedefinition.DefinitionPersist;
import eu.eudat.query.*;
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 gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.exception.*;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidatorFactory;
import jakarta.persistence.EntityManager;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.LoggerFactory;
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.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.unit.DataSize;
import org.springframework.web.multipart.MultipartFile;
import javax.management.InvalidApplicationException;
import java.io.IOException;
import java.net.URLConnection;
import java.nio.file.Files;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@ -74,52 +76,41 @@ import java.util.stream.Collectors;
public class DescriptionServiceImpl implements DescriptionService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionServiceImpl.class));
private final EntityManager entityManager;
private final AuthorizationService authorizationService;
private final DeleterFactory deleterFactory;
private final BuilderFactory builderFactory;
private final ConventionService conventionService;
private final ErrorThesaurusProperties errors;
private final MessageSource messageSource;
private final EventBroker eventBroker;
private final QueryFactory queryFactory;
private final JsonHandlingService jsonHandlingService;
private final UserScope userScope;
private final XmlHandlingService xmlHandlingService;
private final FileTransformerService fileTransformerService;
private final NotifyIntegrationEventHandler eventHandler;
private final NotificationProperties notificationProperties;
private final ElasticService elasticService;
private final ValidatorFactory validatorFactory;
private final StorageFileProperties storageFileConfig;
private final StorageFileService storageFileService;
@Autowired
public DescriptionServiceImpl(
EntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource,
EventBroker eventBroker,
QueryFactory queryFactory,
JsonHandlingService jsonHandlingService,
UserScope userScope,
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService) {
EntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource,
EventBroker eventBroker,
QueryFactory queryFactory,
JsonHandlingService jsonHandlingService,
UserScope userScope,
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -136,6 +127,9 @@ public class DescriptionServiceImpl implements DescriptionService {
this.notificationProperties = notificationProperties;
this.fileTransformerService = fileTransformerService;
this.elasticService = elasticService;
this.validatorFactory = validatorFactory;
this.storageFileConfig = storageFileConfig;
this.storageFileService = storageFileService;
}
//region Persist
@ -405,7 +399,15 @@ public class DescriptionServiceImpl implements DescriptionService {
FieldEntity data = new FieldEntity();
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.isTextListType(fieldType)) data.setTextListValue(persist.getTextListValue());
else if (FieldType.isExternalIdentifierType(fieldType) && persist.getExternalIdentifier() != null) data.setExternalIdentifier(this.buildExternalIdentifierEntity(persist.getExternalIdentifier()));
@ -702,14 +704,78 @@ public class DescriptionServiceImpl implements DescriptionService {
@Override
public ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException {
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());
byte[] data = Files.readAllBytes(fileEnvelope.getFile().toPath());
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
//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;
}
}

View File

@ -16,8 +16,8 @@ import java.util.UUID;
public interface StorageFileService extends ApplicationListener<ApplicationReadyEvent> {
StorageFile persistBytes(StorageFilePersist model, byte[] payload, FieldSet fields) throws IOException;
StorageFile persistString(StorageFilePersist model, String payload, FieldSet fields, Charset charset) throws IOException;
boolean moveToStorage(UUID fileId, StorageType storageType);
boolean copyToStorage(UUID fileId, StorageType storageType);
StorageFile moveToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields);
StorageFile copyToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields);
boolean exists(UUID fileId);

View File

@ -93,7 +93,7 @@ public class StorageFileServiceImpl implements StorageFileService {
this.entityManager.persist(storageFile);
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
@ -104,6 +104,7 @@ public class StorageFileServiceImpl implements StorageFileService {
private StorageFileEntity buildDataEntry(StorageFilePersist model) {
StorageFileEntity data = new StorageFileEntity();
data.setId(UUID.randomUUID());
data.setFileRef(UUID.randomUUID().toString().replaceAll("-", "").toLowerCase(Locale.ROOT));
data.setName(model.getName());
data.setOwnerId(model.getOwnerId());
@ -117,42 +118,74 @@ public class StorageFileServiceImpl implements StorageFileService {
}
@Override
public boolean moveToStorage(UUID fileId, StorageType storageType) {
public StorageFile moveToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields) {
try {
StorageFileEntity storageFile = this.entityManager.find(StorageFileEntity.class, fileId);
if (storageFile == null) return false;
if (storageFile == null) return null;
this.authorizeForce(storageFile, StorageFilePermission.Read);
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()));
if (file.exists() && !replaceDestination) return null;
boolean fileCopied = FileCopyUtils.copy(file, destinationFile) > 0;
if (!fileCopied) return false;
return file.delete();
if (!fileCopied) return null;
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) {
logger.warn("problem reading byte content of storage file " + fileId, ex);
return false;
return null;
}
}
@Override
public boolean copyToStorage(UUID fileId, StorageType storageType) {
public StorageFile copyToStorage(UUID fileId, StorageType storageType, boolean replaceDestination, FieldSet fields) {
try {
StorageFileEntity storageFile = this.entityManager.find(StorageFileEntity.class, fileId);
if (storageFile == null) return false;
if (storageFile == null) return null;
this.authorizeForce(storageFile, StorageFilePermission.Read);
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()));
return FileCopyUtils.copy(file, destinationFile) > 0;
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);
}
catch (Exception ex) {
logger.warn("problem reading byte content of storage file " + fileId, ex);
return false;
return null;
}
}

View File

@ -1,11 +1,19 @@
package eu.eudat.controllers.v2;
import com.fasterxml.jackson.core.JsonProcessingException;
import eu.eudat.audit.AuditableAction;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.authorization.Permission;
import eu.eudat.commons.enums.DmpAccessType;
import eu.eudat.commons.enums.DmpStatus;
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 eu.eudat.model.Description;
import eu.eudat.model.Dmp;
@ -21,7 +29,6 @@ import eu.eudat.query.DmpQuery;
import eu.eudat.query.lookup.DescriptionLookup;
import eu.eudat.service.description.DescriptionService;
import eu.eudat.service.elastic.ElasticQueryHelperService;
import eu.eudat.service.transformer.FileTransformerService;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.data.builder.BuilderFactory;
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.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
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.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.management.InvalidApplicationException;
import java.io.IOException;
import java.net.URLConnection;
import java.time.Duration;
import java.util.*;
import static eu.eudat.authorization.AuthorizationFlags.Public;
@ -63,14 +77,16 @@ public class DescriptionController {
private final MessageSource messageSource;
private final ElasticQueryHelperService elasticQueryHelperService;
private final StorageFileService storageFileService;
private final ConventionService conventionService;
public DescriptionController(
BuilderFactory builderFactory,
AuditService auditService,
DescriptionService descriptionService,
CensorFactory censorFactory,
QueryFactory queryFactory,
MessageSource messageSource,
ElasticQueryHelperService elasticQueryHelperService) {
BuilderFactory builderFactory,
AuditService auditService,
DescriptionService descriptionService,
CensorFactory censorFactory,
QueryFactory queryFactory,
MessageSource messageSource,
ElasticQueryHelperService elasticQueryHelperService, StorageFileService storageFileService, ConventionService conventionService) {
this.builderFactory = builderFactory;
this.auditService = auditService;
this.descriptionService = descriptionService;
@ -78,6 +94,8 @@ public class DescriptionController {
this.queryFactory = queryFactory;
this.messageSource = messageSource;
this.elasticQueryHelperService = elasticQueryHelperService;
this.storageFileService = storageFileService;
this.conventionService = conventionService;
}
@PostMapping("public/query")
@ -192,4 +210,41 @@ public class DescriptionController {
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));
}
}