Skip to content

Commit

Permalink
Fix Update Resource
Browse files Browse the repository at this point in the history
  • Loading branch information
EmanueleValentini1 committed Nov 14, 2023
1 parent 6be318d commit b6cd885
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import io.quarkus.hibernate.reactive.panache.PanacheEntityBase;
import it.gov.pagopa.atmlayer.service.model.enumeration.NoDeployableResourceType;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
Expand Down Expand Up @@ -36,6 +38,8 @@ public class ResourceEntity extends PanacheEntityBase implements Serializable {
@Column(name="resourceType")
@Enumerated(EnumType.STRING)
NoDeployableResourceType noDeployableResourceType;
@OneToOne(mappedBy = "resourceEntity", cascade = CascadeType.ALL)
ResourceFile resourceFile;
@Column(name="file_name")
String fileName;
@CreationTimestamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ public enum AppErrorCodeEnum {
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),
RESOURCE_WITH_SAME_NAME_AND_PATH_ALREADY_SAVED("ATMLM_4000027", "A resource with same file name and path already exists", NOT_UPLOADABLE),
INEXISTENT_RESOURCE_CANNOT_BE_UPDATED("ATMLM_4000028","The referenced resource does not exist: cannot be updated",NOT_UPDATABLE),
RESOURCE_WITH_DIFFERENT_STORAGE_KEY_CANNOT_BE_UPDATED("ATMLM_4000029","The referenced resource has a different storage key: cannot be updated",NOT_UPDATABLE),
RESOURCE_DOES_NOT_EXIST("ATMLM_4000030", "The referenced Resource does not exist", NOT_EXISTING_REFERENCED_ENTITY),
WORKFLOW_RESOURCE_CANNOT_BE_UPDATED("ATMLM_4000031", "The referenced Workflow Resource file can not be updated", NOT_UPDATABLE),
RESOURCE_FILE_DOES_NOT_EXIST("ATMLM_4000032", "The referenced Resource file does not exist", NOT_EXISTING_REFERENCED_ENTITY);
RESOURCE_WITH_DIFFERENT_STORAGE_KEY_CANNOT_BE_UPDATED("ATMLM_4000028","The referenced resource has a different storage key: cannot be updated",NOT_UPDATABLE),
RESOURCE_DOES_NOT_EXIST("ATMLM_4000029", "The referenced Resource does not exist", NOT_EXISTING_REFERENCED_ENTITY),
WORKFLOW_RESOURCE_CANNOT_BE_UPDATED("ATMLM_4000030", "The referenced Workflow Resource file can not be updated", NOT_UPDATABLE),
RESOURCE_FILE_DOES_NOT_EXIST("ATMLM_4000031", "The referenced Resource file does not exist", NOT_EXISTING_REFERENCED_ENTITY),
WORKFLOW_RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS("ATMLM_4000032","A workflow resource with the same content already exists", CONSTRAINT_VIOLATION);

private final String errorCode;
private final String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Mapper(componentModel = "cdi")
public interface ResourceFileMapper {

ResourceFileDTO toDTO(ResourceFile bpmnVersion);
ResourceFileDTO toDTO(ResourceFile resourceFile);
@Mapping(ignore = true, target = "bpmn")
ResourceFile toEntity(ResourceFileDTO bpmnDTO);
ResourceFile toEntity(ResourceFileDTO resourceFileDTO);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import it.gov.pagopa.atmlayer.service.model.entity.ResourceFile;
import it.gov.pagopa.atmlayer.service.model.entity.WorkflowResource;
import it.gov.pagopa.atmlayer.service.model.exception.AtmLayerException;
import it.gov.pagopa.atmlayer.service.model.mapper.ResourceFileMapper;
import it.gov.pagopa.atmlayer.service.model.mapper.WorkflowResourceMapper;
import it.gov.pagopa.atmlayer.service.model.model.ResourceFileDTO;
import it.gov.pagopa.atmlayer.service.model.model.WorkflowResourceDTO;
import it.gov.pagopa.atmlayer.service.model.service.WorkflowResourceService;
import jakarta.enterprise.context.ApplicationScoped;
Expand Down Expand Up @@ -48,6 +50,9 @@ public class WorkflowResourceResource {
@Inject
WorkflowResourceMapper workflowResourceMapper;

@Inject
ResourceFileMapper resourceFileMapper;

@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<WorkflowResourceDTO>> getAll() {
Expand Down Expand Up @@ -110,10 +115,12 @@ public Uni<Void> delete(@PathParam("uuid") UUID uuid) {
@Path("/update/{uuid}")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Uni<ResourceFile> update(@RequestBody(required = true) @FormParam("file") File file,
@PathParam("uuid") UUID uuid) throws NoSuchAlgorithmException, IOException {
public Uni<ResourceFileDTO> update(@RequestBody(required = true) @FormParam("file") File file,
@PathParam("uuid") UUID uuid) throws NoSuchAlgorithmException, IOException {

return this.workflowResourceService.update(uuid, file);
return workflowResourceService.update(uuid, file)
.onItem()
.transformToUni(updateResourceFile -> Uni.createFrom().item(resourceFileMapper.toDTO(updateResourceFile)));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

public interface ResourceEntityStorageService {

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

Uni<URL> generatePresignedUrl(String storageKey);

Expand All @@ -24,4 +24,6 @@ public interface ResourceEntityStorageService {

String calculateStorageKey(NoDeployableResourceType resourceType, String relativePath, String fileName);

Uni<ResourceFile> saveFile(ResourceEntity resourceEntity, File file, String fileNameWithExtension, String relativePath);

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,32 @@
import it.gov.pagopa.atmlayer.service.model.entity.ResourceEntity;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceFile;
import it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum;
import it.gov.pagopa.atmlayer.service.model.enumeration.S3ResourceTypeEnum;
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 it.gov.pagopa.atmlayer.service.model.service.ResourceFileService;
import it.gov.pagopa.atmlayer.service.model.service.ResourceFileService;
import it.gov.pagopa.atmlayer.service.model.utils.CommonUtils;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import java.io.File;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Objects;
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.INEXISTENT_RESOURCE_CANNOT_BE_UPDATED;
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_DOES_NOT_EXIST;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS;
import static it.gov.pagopa.atmlayer.service.model.utils.FileUtils.calculateSha256;

@ApplicationScoped
@Slf4j
Expand Down Expand Up @@ -93,7 +97,7 @@ public Uni<ResourceEntity> saveAndUpload(ResourceEntity resourceEntity, File fil
@Override
public Uni<ResourceFile> upload(ResourceEntity resourceEntity, File file,
String filename, String path) {
return this.resourceEntityStorageService.uploadFile(resourceEntity, file, filename, path)
return this.resourceEntityStorageService.saveFile(resourceEntity, file, filename, path)
.onFailure().recoverWithUni(failure -> {
log.error(failure.getMessage());
return Uni.createFrom().failure(new AtmLayerException(
Expand Down Expand Up @@ -134,17 +138,33 @@ public Uni<ResourceEntity> createResource(ResourceEntity resourceEntity, File fi
}

@Override
@WithTransaction
public Uni<ResourceFile> updateResource(UUID uuid, File file) {
return this.findByUUID(uuid)
.onItem().transformToUni(optionalResource -> {
.onItem()
.transformToUni(Unchecked.function(optionalResource -> {
if (optionalResource.isEmpty()) {
String errorMessage = String.format("Resource with Id %s does not exist: cannot update", uuid);
throw new AtmLayerException(errorMessage, Response.Status.BAD_REQUEST, INEXISTENT_RESOURCE_CANNOT_BE_UPDATED);
throw new AtmLayerException(errorMessage, Response.Status.BAD_REQUEST, RESOURCE_DOES_NOT_EXIST);
}
ResourceEntity resourceEntity = optionalResource.get();
String newFileSha256 = calculateSha256(file);
if (Objects.equals(resourceEntity.getSha256(), newFileSha256)) {
throw new AtmLayerException("Resource is already present", Response.Status.BAD_REQUEST, RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS);
}
return Uni.createFrom().item(optionalResource.get());
})
.onItem().transformToUni(resource ->
resourceFileService.getRelativePath(resource)
.onItem().transformToUni(path -> upload(resource, file, resource.getFileName(), path)));
resourceEntity.setSha256(newFileSha256);
Date date = new Date();
resourceEntity.setLastUpdatedAt(new Timestamp(date.getTime()));
resourceEntity.getResourceFile().setLastUpdatedAt(new Timestamp(date.getTime()));
return resourceEntityRepository.persist(resourceEntity)
.onItem()
.transformToUni(x -> {
String storageKey = resourceEntity.getResourceFile().getStorageKey();
String fileName = FilenameUtils.getBaseName(storageKey);
String extension = FilenameUtils.getExtension(storageKey);
String path = FilenameUtils.getFullPath(storageKey);
return resourceEntityStorageService.uploadFile(file, resourceEntity, CommonUtils.getFilenameWithExtension(fileName,extension), CommonUtils.getPathWithoutFilename(path), false);
});
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,22 @@

import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import io.vertx.core.Context;
import io.vertx.core.Vertx;
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 it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum;
import it.gov.pagopa.atmlayer.service.model.enumeration.NoDeployableResourceType;
import it.gov.pagopa.atmlayer.service.model.enumeration.ObjectStoreStrategyEnum;
import it.gov.pagopa.atmlayer.service.model.enumeration.S3ResourceTypeEnum;
import it.gov.pagopa.atmlayer.service.model.exception.AtmLayerException;
import it.gov.pagopa.atmlayer.service.model.model.ObjectStorePutResponse;
import it.gov.pagopa.atmlayer.service.model.properties.ObjectStoreProperties;
import it.gov.pagopa.atmlayer.service.model.service.ObjectStoreService;
import it.gov.pagopa.atmlayer.service.model.service.ResourceFileService;
import it.gov.pagopa.atmlayer.service.model.service.ResourceEntityStorageService;
import it.gov.pagopa.atmlayer.service.model.service.ResourceFileService;
import it.gov.pagopa.atmlayer.service.model.strategy.ObjectStoreStrategy;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringSubstitutor;
Expand Down Expand Up @@ -54,19 +50,30 @@ public ResourceEntityStorageServiceImpl(ObjectStoreStrategy objectStoreStrategy,
}

@Override
public Uni<ResourceFile> uploadFile(ResourceEntity resourceEntity, File file, String filenameWithExtension, String relativePath) {
S3ResourceTypeEnum resourceType = convertEnum(resourceEntity.getNoDeployableResourceType());
String finalPath = calculateCompletePath(resourceEntity.getNoDeployableResourceType(),relativePath);
log.info("Requesting to write file {} in Object Store at path {}", file.getName(), finalPath);
public Uni<ResourceFile> uploadFile(File file, ResourceEntity resourceEntity, String filenameWithExtension, String finalPath, boolean creation) {
Context context = Vertx.currentContext();
S3ResourceTypeEnum resourceType = convertEnum(resourceEntity.getNoDeployableResourceType());
return objectStoreService.uploadFile(file, finalPath, resourceType, filenameWithExtension)
.emitOn(command -> context.runOnContext(x -> command.run()))
.onItem()
.transformToUni(objectStorePutResponse -> this.writeResourceInfoToDatabase(resourceEntity,
objectStorePutResponse, filenameWithExtension.split("\\.")[0]));
.transformToUni(objectStorePutResponse -> {
if(creation){
return this.writeResourceInfoToDatabase(resourceEntity,
objectStorePutResponse, filenameWithExtension.split("\\.")[0]);
}
return Uni.createFrom().item(resourceEntity.getResourceFile());
});

}

@Override
public Uni<ResourceFile> saveFile(ResourceEntity resourceEntity, File file, String fileNameWithExtension, String relativePath) {
S3ResourceTypeEnum resourceType = convertEnum(resourceEntity.getNoDeployableResourceType());
String finalPath = calculateCompletePath(resourceEntity.getNoDeployableResourceType(),relativePath);
log.info("Requesting to write file {} in Object Store at path {}", file.getName(), finalPath);
return uploadFile(file, resourceEntity, fileNameWithExtension, finalPath, true);
}

@Override
public Uni<URL> generatePresignedUrl(String storageKey) {
return this.objectStoreService.generatePresignedUrl(storageKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.quarkus.hibernate.reactive.panache.common.WithSession;
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.ResourceEntity;
import it.gov.pagopa.atmlayer.service.model.entity.ResourceFile;
import it.gov.pagopa.atmlayer.service.model.exception.AtmLayerException;
Expand Down Expand Up @@ -44,12 +45,12 @@ public Uni<Optional<ResourceFile>> findByStorageKey(String storageKey) {
public Uni<String> getStorageKey(ResourceEntity resourceEntity) {
return resourceFileRepository.findByResourceId(resourceEntity.getResourceId())
.onItem().transformToUni(resourceFile -> Uni.createFrom().item(Optional.ofNullable(resourceFile)))
.onItem().transformToUni(optionalResourceFile -> {
.onItem().transformToUni(Unchecked.function(optionalResourceFile -> {
if (optionalResourceFile.isEmpty()) {
throw new AtmLayerException("The referenced resource does not exist: cannot retrieve storage key", Response.Status.BAD_REQUEST, RESOURCE_DOES_NOT_EXIST);
}
return Uni.createFrom().item(optionalResourceFile.get().getStorageKey());
});
}));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.WORKFLOW_RESOURCE_CANNOT_BE_UPDATED;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.WORKFLOW_RESOURCE_FILE_WITH_SAME_CAMUNDA_DEFINITION_KEY_ALREADY_EXISTS;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.WORKFLOW_RESOURCE_FILE_WITH_SAME_CONTENT_ALREADY_EXIST;
import static it.gov.pagopa.atmlayer.service.model.enumeration.AppErrorCodeEnum.WORKFLOW_RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS;
import static it.gov.pagopa.atmlayer.service.model.utils.FileUtils.calculateSha256;
import static it.gov.pagopa.atmlayer.service.model.utils.FileUtils.extractIdValue;

Expand Down Expand Up @@ -281,6 +282,9 @@ public Uni<ResourceFile> update(UUID id, File file) throws NoSuchAlgorithmExcept
throw new AtmLayerException(String.format("Workflow Resource with type %s does not match the Workflow Resource you are trying to update", definitionKey), Response.Status.BAD_REQUEST, WORKFLOW_RESOURCE_CANNOT_BE_UPDATED);
}
String shaUpdateFile = calculateSha256(file);
if (workflowFound.getSha256().equals(shaUpdateFile)) {
throw new AtmLayerException("Workflow Resource already present", Response.Status.BAD_REQUEST, WORKFLOW_RESOURCE_WITH_SAME_SHA256_ALREADY_EXISTS);
}
workflowFound.setSha256(shaUpdateFile);
Date date = new Date();
workflowFound.setLastUpdatedAt(new Timestamp(date.getTime()));
Expand Down
Loading

0 comments on commit b6cd885

Please sign in to comment.