Skip to content

Commit

Permalink
Merge branch 'sprint4_resources' into Main_sprint4_integration
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/it/gov/pagopa/atmlayer/service/model/enumeration/AppErrorCodeEnum.java
#	src/main/java/it/gov/pagopa/atmlayer/service/model/enumeration/AppErrorType.java
#	src/test/resources/application.properties
  • Loading branch information
EmanueleValentini1 committed Nov 10, 2023
2 parents 682b244 + d4ca1f8 commit 5de9cdb
Show file tree
Hide file tree
Showing 15 changed files with 297 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package it.gov.pagopa.atmlayer.service.model.dto;

import it.gov.pagopa.atmlayer.service.model.enumeration.ResourceTypeEnum;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.FormParam;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -12,14 +14,20 @@
@Data
@NoArgsConstructor
public class ResourceCreationDto {
@FormParam("file")
@NotNull(message = "resource file is required")
private File file;
@FormParam("filename")
@NotNull(message = "filename is required")
@Pattern(regexp = "^[a-zA-Z0-9_-]+$", message = "deve essere della forma ${regexp} e non contenere l'estensione del file")
private String filename;
@FormParam("resourceType")
@NotNull(message = "resource type is required")
private ResourceTypeEnum resourceType;

@FormParam("file")
@NotNull(message = "resource file is required")
private File file;
@FormParam("filename")
@NotNull(message = "filename is required")
@Pattern(regexp = "^[a-zA-Z0-9_-]+$", message = "it must be of form ${regexp} and must not contain file extension")
private String filename;
@FormParam("resourceType")
@NotNull(message = "resource type is required")
private ResourceTypeEnum resourceType;
@FormParam("path")
@Nullable
@Pattern(regexp = "^(?!/).*(?<!/)$", message = "String must not start or end with '/'")
@DefaultValue("")
private String path;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.NOT_DEPLOYED_STATUS;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.NOT_EXISTING_REFERENCED_ENTITY;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.ID_NOT_FOUND;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.NOT_UPDATABLE;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.NOT_UPGRADABLE;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.NOT_VALID_FILE;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorType.NOT_VALID_REFERENCED_ENTITY;
Expand Down Expand Up @@ -49,8 +48,8 @@ public enum AppErrorCodeEnum {
WORKFLOW_FILE_DOES_NOT_EXIST("ATMLM_4000023", "The referenced Workflow Resource file does not exist", NOT_EXISTING_REFERENCED_ENTITY),
WORKFLOW_RESOURCE_CANNOT_BE_DELETED_FOR_STATUS("ATMLM_4000024", "The referenced Workflow Resource file can not be deleted in the actual state", NOT_DELETABLE),
WORKFLOW_RESOURCE_CANNOT_BE_UPDATED_FOR_STATUS("ATMLM_4000025", "The referenced Workflow Resource file can not be updated in the actual state", NOT_UPDATABLE),
WORKFLOW_RESOURCE_FILE_CANNOT_BE_DEPLOYED("ATMLM_4000026", "The referenced Workflow Resource file can not be deployed", NOT_DEPLOYABLE_STATUS);

WORKFLOW_RESOURCE_FILE_CANNOT_BE_DEPLOYED("ATMLM_4000026", "The referenced Workflow Resource file can not be deployed", NOT_DEPLOYABLE_STATUS),
RESOURCE_WITH_SAME_NAME_AND_PATH_ALREADY_SAVED("ATMLM_4000025", "A resource with same file name and path already exists", NOT_UPLOADABLE);


private final String errorCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import it.gov.pagopa.atmlayer.service.model.dto.ResourceCreationDto;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceEntity;
import it.gov.pagopa.atmlayer.service.model.model.ResourceEntityDTO;
import it.gov.pagopa.atmlayer.service.model.model.ResourceDTO;
import it.gov.pagopa.atmlayer.service.model.utils.BpmnUtils;
import org.mapstruct.Mapper;

Expand All @@ -20,5 +20,5 @@ public ResourceEntity toEntityCreation(ResourceCreationDto resourceCreationDto)
}

//TODO: IMPLEMENT toDto(ResourceEntity resourceEntity) METHOD
public abstract ResourceEntityDTO toDTO(ResourceEntity resourceEntity);
public abstract ResourceDTO toDTO(ResourceEntity resourceEntity);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package it.gov.pagopa.atmlayer.service.model.model;

import it.gov.pagopa.atmlayer.service.model.enumeration.ResourceTypeEnum;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Timestamp;
import java.util.UUID;

public class ResourceEntityDTO {
@Data
@NoArgsConstructor
public class ResourceDTO {
private UUID resourceId;
private String sha256;
ResourceTypeEnum resourceTypeEnum;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public interface ObjectStoreProperties {

WorkflowResource workflowResource();

Html html();

interface Bucket {
String name();

Expand All @@ -37,5 +39,8 @@ interface WorkflowResource {
String pathTemplate();
}

interface Html {
String pathTemplate();
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package it.gov.pagopa.atmlayer.service.model.repository;

import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import io.quarkus.panache.common.Parameters;
import io.smallrye.mutiny.Uni;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceFile;
import jakarta.enterprise.context.ApplicationScoped;

import java.util.UUID;

@ApplicationScoped
public class ResourceFileRepository implements PanacheRepositoryBase<ResourceFile, UUID> {

public Uni<ResourceFile> findByStorageKey(String key){
return find(
"select resource from ResourceFile resource where resource.storageKey = :key",
Parameters.with("key", key)).firstResult();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import io.smallrye.common.annotation.NonBlocking;
import io.smallrye.mutiny.Uni;
import it.gov.pagopa.atmlayer.service.model.dto.BpmnCreationDto;
import it.gov.pagopa.atmlayer.service.model.dto.ResourceCreationDto;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceEntity;
import it.gov.pagopa.atmlayer.service.model.mapper.ResourceEntityMapper;
import it.gov.pagopa.atmlayer.service.model.model.ResourceEntityDTO;
import it.gov.pagopa.atmlayer.service.model.model.ResourceDTO;
import it.gov.pagopa.atmlayer.service.model.service.ResourceEntityService;
import it.gov.pagopa.atmlayer.service.model.service.impl.ResourceEntityServiceImpl;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
Expand All @@ -29,20 +27,23 @@
@Tag(name = "RESOURCES", description = "RESOURCES operations")
@Slf4j
public class ResourceEntityResource {
@Inject
ResourceEntityMapper resourceEntityMapper;
@Inject
ResourceEntityService resourceEntityService;

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@NonBlocking
public Uni<ResourceEntityDTO> createResource(@RequestBody(required = true) @Valid ResourceCreationDto resourceCreationDto) throws NoSuchAlgorithmException, IOException {
ResourceEntity resourceEntity = resourceEntityMapper.toEntityCreation(resourceCreationDto);
return resourceEntityService.createResource(resourceEntity, resourceCreationDto.getFile(), resourceCreationDto.getFilename())
//.onItem().transformToUni(resource -> Uni.createFrom().item(resource));
//quando il metodo toDto è implementato nel mapper, sostituire con:
.onItem().transformToUni(resource -> Uni.createFrom().item(resourceEntityMapper.toDTO(resource)));
}
@Inject
ResourceEntityMapper resourceEntityMapper;
@Inject
ResourceEntityService resourceEntityService;

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@NonBlocking
public Uni<ResourceDTO> createResource(
@RequestBody(required = true) @Valid ResourceCreationDto resourceCreationDto)
throws NoSuchAlgorithmException, IOException {
ResourceEntity resourceEntity = resourceEntityMapper.toEntityCreation(resourceCreationDto);
return resourceEntityService.createResource(resourceEntity, resourceCreationDto.getFile(),
resourceCreationDto.getFilename(),resourceCreationDto.getPath().trim().replaceAll(" ", "_"))
.onItem()
.transformToUni(resource -> Uni.createFrom().item(resourceEntityMapper.toDTO(resource)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public interface ResourceEntityService {

Uni<Optional<ResourceEntity>> findByUUID(UUID uuid);

Uni<ResourceEntity> saveAndUpload(ResourceEntity resourceEntity, File file, String filename);
Uni<ResourceEntity> saveAndUpload(ResourceEntity resourceEntity, File file, String filename, String path);

Uni<ResourceEntity> createResource(ResourceEntity resourceEntity, File file, String filename);
Uni<ResourceEntity> createResource(ResourceEntity resourceEntity, File file, String filename,String path);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package it.gov.pagopa.atmlayer.service.model.service;

import io.smallrye.mutiny.Uni;
import io.vertx.core.buffer.Buffer;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceEntity;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceFile;
import org.jboss.resteasy.reactive.RestMulti;
import java.io.File;
import java.net.URL;

public interface ResourceEntityStorageService {

Uni<ResourceFile> uploadFile(ResourceEntity resourceEntity, File file, String filename, String path);

Uni<URL> generatePresignedUrl(String storageKey);

RestMulti<Buffer> download(String storageKey);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
import io.smallrye.mutiny.Uni;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceFile;

import java.util.Optional;

public interface ResourceFileService {

Uni<ResourceFile> save(ResourceFile resourceFile);

Uni<Optional<ResourceFile>> findByStorageKey(String storageKey);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,111 @@
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import it.gov.pagopa.atmlayer.service.model.entity.BpmnVersion;
import it.gov.pagopa.atmlayer.service.model.client.ProcessClient;
import it.gov.pagopa.atmlayer.service.model.entity.BpmnVersionPK;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceEntity;
import it.gov.pagopa.atmlayer.service.model.enumeration.ResourceTypeEnum;
import it.gov.pagopa.atmlayer.service.model.exception.AtmLayerException;
import it.gov.pagopa.atmlayer.service.model.repository.ResourceEntityRepository;
import it.gov.pagopa.atmlayer.service.model.service.ResourceEntityService;
import it.gov.pagopa.atmlayer.service.model.service.ResourceEntityStorageService;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import java.io.File;
import java.util.Optional;
import java.util.UUID;

import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.ATMLM_500;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.BPMN_FILE_WITH_SAME_CAMUNDA_DEFINITION_KEY_ALREADY_EXISTS;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.BPMN_FILE_WITH_SAME_CONTENT_ALREADY_EXIST;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.OBJECT_STORE_SAVE_FILE_ERROR;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS;

@ApplicationScoped
@Slf4j
public class ResourceEntityServiceImpl implements ResourceEntityService {

@Inject
ResourceEntityRepository resourceEntityRepository;
@Inject
ResourceEntityStorageService resourceEntityStorageService;
@Inject
ResourceEntityRepository resourceEntityRepository;

@Override
@WithTransaction
public Uni<ResourceEntity> save(ResourceEntity resourceEntity) {
log.info("Persisting resource {} to database", resourceEntity.getFileName());
return resourceEntityRepository.persist(resourceEntity);
}
@Inject
@RestClient
ProcessClient processClient;

@Override
public Uni<Boolean> delete(BpmnVersionPK bpmnVersionPK) {
return null;
}
final ResourceTypeEnum resourceType = ResourceTypeEnum.HTML;

@Override
@WithSession
public Uni<Optional<ResourceEntity>> findBySHA256(String sha256) {
return this.resourceEntityRepository.findBySHA256(sha256)
.onItem().transformToUni(x -> Uni.createFrom().item(Optional.ofNullable(x)));
}
@Override
@WithTransaction
public Uni<ResourceEntity> save(ResourceEntity resourceEntity) {
log.info("Persisting resource {} to database", resourceEntity.getFileName());
return resourceEntityRepository.persist(resourceEntity);
}

@Override
@WithSession
public Uni<Optional<ResourceEntity>> findByUUID(UUID uuid) {
return resourceEntityRepository.findById(uuid)
.onItem().transformToUni(x -> Uni.createFrom().item(Optional.ofNullable(x)));
}
@Override
public Uni<Boolean> delete(BpmnVersionPK bpmnVersionPK) {
return null;
}

@Override
@WithTransaction
public Uni<ResourceEntity> saveAndUpload(ResourceEntity resourceEntity, File file, String filename) {
return this.save(resourceEntity);
//TODO: implementare upload su FileStorageService
}
@Override
@WithSession
public Uni<Optional<ResourceEntity>> findBySHA256(String sha256) {
return this.resourceEntityRepository.findBySHA256(sha256)
.onItem().transformToUni(x -> Uni.createFrom().item(Optional.ofNullable(x)));
}

@Override
public Uni<ResourceEntity> createResource(ResourceEntity resourceEntity, File file, String filename) {
return findBySHA256(resourceEntity.getSha256())
.onItem().transformToUni(Unchecked.function(x -> {
if (x.isPresent()) {
throw new AtmLayerException("A resource with the same content already exists", Response.Status.BAD_REQUEST, BPMN_FILE_WITH_SAME_CAMUNDA_DEFINITION_KEY_ALREADY_EXISTS);
}
return saveAndUpload(resourceEntity, file, filename)
.onItem().transformToUni(bpmn -> {
return this.findByUUID(resourceEntity.getResourceId())
.onItem().transformToUni(optionalResource -> {
if (optionalResource.isEmpty()) {
return Uni.createFrom().failure(new AtmLayerException("Sync problem on resource creation", Response.Status.INTERNAL_SERVER_ERROR, ATMLM_500));
}
return Uni.createFrom().item(optionalResource.get());
});
});
}));
}
@Override
@WithSession
public Uni<Optional<ResourceEntity>> findByUUID(UUID uuid) {
return resourceEntityRepository.findById(uuid)
.onItem().transformToUni(x -> Uni.createFrom().item(Optional.ofNullable(x)));
}

@Override
@WithTransaction
public Uni<ResourceEntity> saveAndUpload(ResourceEntity resourceEntity, File file,
String filename, String path) {
return this.save(resourceEntity)
.onItem().transformToUni(record -> {
return this.resourceEntityStorageService.uploadFile(resourceEntity, file, filename, path)
.onFailure().recoverWithUni(failure -> {
log.error(failure.getMessage());
return Uni.createFrom().failure(new AtmLayerException(
"Failed to save Resource Entity in Object Store. Resource creation aborted",
Response.Status.INTERNAL_SERVER_ERROR, OBJECT_STORE_SAVE_FILE_ERROR));
})
.onItem().transformToUni(putObjectResponse -> {
log.info("Completed Resource Entity Creation");
return Uni.createFrom().item(record);
});
});
}

@Override
public Uni<ResourceEntity> createResource(ResourceEntity resourceEntity, File file,
String filename, String path) {
return findBySHA256(resourceEntity.getSha256())
.onItem().transformToUni(Unchecked.function(x -> {
if (x.isPresent()) {
throw new AtmLayerException("A resource with the same content already exists",
Response.Status.BAD_REQUEST,
RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS);
}
return saveAndUpload(resourceEntity, file, filename, path)
.onItem().transformToUni(bpmn -> {
return this.findByUUID(resourceEntity.getResourceId())
.onItem().transformToUni(optionalResource -> {
if (optionalResource.isEmpty()) {
return Uni.createFrom().failure(
new AtmLayerException("Sync problem on resource creation",
Response.Status.INTERNAL_SERVER_ERROR, ATMLM_500));
}
return Uni.createFrom().item(optionalResource.get());
});
});
}));
}
}
Loading

0 comments on commit 5de9cdb

Please sign in to comment.