package eu.eudat.controllers; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.data.entities.FileUpload; import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.managers.DatasetProfileManager; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; import eu.eudat.logic.utilities.json.JsonSearcher; import eu.eudat.models.HintedModelFactory; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; import eu.eudat.types.Authorities; import org.apache.poi.util.IOUtils; import org.json.JSONArray; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.transaction.Transactional; import java.io.*; import java.nio.file.Files; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @RestController @CrossOrigin @RequestMapping(value = {"/api/file/"}) public class FileController { private DatasetProfileManager datasetProfileManager; private final Environment environment; private DatabaseRepository databaseRepository; @Autowired public FileController(DatasetProfileManager datasetProfileManager, Environment environment, ApiContext apiContext) { this.datasetProfileManager = datasetProfileManager; this.environment = environment; this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); } @RequestMapping(method = RequestMethod.POST, value = {"/upload"}) public ResponseEntity> upload( @RequestParam("file") MultipartFile file, @RequestParam("datasetProfileId") String datasetProfileId, @RequestParam("fieldId") String fieldId, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER}) Principal principal) throws IllegalAccessException, IOException { String uuid = UUID.randomUUID().toString(); eu.eudat.models.data.admin.composite.DatasetProfile datasetprofile = this.datasetProfileManager.getDatasetProfile(datasetProfileId); ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String json = mapper.writeValueAsString(datasetprofile.getSections());; JsonNode propertiesJson = mapper.readTree(json); Set fieldNodes = new HashSet<>(); fieldNodes.addAll(JsonSearcher.findNodes(propertiesJson, "id", fieldId, false)); // AtomicReference exceptionMessage = null; AtomicBoolean acceptedFile = new AtomicBoolean(false); fieldNodes.forEach(node -> { JsonNode data = node.get("data"); if (data != null && !data.toString().equals("\"\"") && !data.toString().equals("null")) { String stringValue = data.toString().replaceAll("=", ":"); JSONObject dataObj = new JSONObject(stringValue); Map dataMap = ((JSONObject) dataObj).toMap(); if(dataMap.get("maxFileSizeInMB") != null && !dataMap.get("maxFileSizeInMB").toString().equals("\"\"") && !dataMap.get("maxFileSizeInMB").toString().equals("null")) { if (file.getSize() <= Integer.parseInt(dataMap.get("maxFileSizeInMB").toString())*1048576) { acceptedFile.set(true); } // else { // exceptionMessage.set("The file is too large. Max file upload is " + dataMap.get("maxFileSizeInMB").toString() + " MB."); // } } if(acceptedFile.get() && data.get("types") != null && !data.get("types").toString().equals("\"\"") && !data.get("types").toString().equals("null")) { acceptedFile.set(false); JSONArray types = new JSONArray(data.get("types").toString()); types.iterator().forEachRemaining(element -> { Map typesMap = ((JSONObject) element).toMap(); if(typesMap.get("value") != null && !typesMap.get("value").toString().equals("\"\"") && !typesMap.get("value").toString().equals("null")) { if(file.getContentType().equals(typesMap.get("value").toString())) { acceptedFile.set(true); } } }); } // if(!acceptedFile.get()) { // exceptionMessage.set("The file type is not accepted."); // } } }); if(!acceptedFile.get()) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("The uploaded file is too large or has an unaccepted type")); } File convFile = new File(this.environment.getProperty("temp.temp") + uuid); convFile.createNewFile(); FileOutputStream fos = new FileOutputStream(convFile); fos.write(file.getBytes()); fos.close(); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(uuid) .status(ApiMessageCode.SUCCESS_MESSAGE).message("")); } @RequestMapping(method = RequestMethod.POST, value = {"/delete-temp"}) public ResponseEntity> upload(@RequestBody String filename) throws IllegalAccessException, IOException { File convFile = new File(this.environment.getProperty("temp.temp") + filename); // Boolean deleted = convFile.delete(); Boolean deleted = Files.deleteIfExists(convFile.toPath()); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(deleted.toString()) .status(ApiMessageCode.SUCCESS_MESSAGE).message("")); } @Transactional @RequestMapping(method = RequestMethod.GET, value = {"{id}"}, produces = "application/json") public @ResponseBody ResponseEntity download(@PathVariable String id ,@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal ) throws IOException { FileUpload fileUpload = databaseRepository.getFileUploadDao().find(UUID.fromString(id)); if(fileUpload == null) { throw new NoSuchElementException("File with id "+id+" not found"); } if(fileUpload.getEntityType().name().equals(FileUpload.EntityType.DATASET.name())) { eu.eudat.data.entities.Dataset datasetEntity = databaseRepository.getDatasetDao().find(fileUpload.getEntityId(), HintedModelFactory.getHint(DatasetWizardModel.class)); if (datasetEntity == null) { throw new NoSuchElementException("No dataset with id " + fileUpload.getEntityId() + " found. This dataset was related to the file with id " + id); } if (!datasetEntity.getDmp().isPublic() && datasetEntity.getDmp().getUsers() .stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) .collect(Collectors.toList()).size() == 0) throw new UnauthorisedException(); } FileEnvelope fileEnvelope = new FileEnvelope(); fileEnvelope.setFilename(fileUpload.getName()); File exportFile = new File(this.environment.getProperty("file.storage") + id); fileEnvelope.setFile(exportFile); InputStream resource = new FileInputStream(fileEnvelope.getFile()); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(fileEnvelope.getFile().length()); responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); String fileName = fileEnvelope.getFilename().replace(" ", "_").replace(",", "_"); responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName); responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); responseHeaders.set("Cache-Control", "no-store"); responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); byte[] content = IOUtils.toByteArray(resource); resource.close(); return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); } }