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.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.FieldType; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; import eu.eudat.commons.types.descriptiontemplate.FieldEntity; import eu.eudat.commons.types.descriptiontemplate.FieldSetEntity; import eu.eudat.commons.types.descriptiontemplate.SectionEntity; import eu.eudat.commons.types.descriptiontemplate.fielddata.UploadDataEntity; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.data.old.Dataset; import eu.eudat.data.old.FileUpload; import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.managers.DatasetProfileManager; 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.query.DescriptionTemplateQuery; import eu.eudat.types.ApiMessageCode; import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.data.query.QueryFactory; import jakarta.xml.bind.JAXBException; 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.util.unit.DataSize; import org.springframework.util.unit.DataUnit; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import jakarta.transaction.Transactional; import org.xml.sax.SAXException; import javax.management.InvalidApplicationException; import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.nio.file.Files; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @RestController @CrossOrigin @RequestMapping(value = {"/api/file/"}) public class FileController { private DatasetProfileManager datasetProfileManager; private final Environment environment; private DatabaseRepository databaseRepository; private final AuthorizationService authorizationService; private final UserScope userScope; private final QueryFactory queryFactory; private final XmlHandlingService xmlHandlingService; @Autowired public FileController(DatasetProfileManager datasetProfileManager, Environment environment, ApiContext apiContext, AuthorizationService authorizationService, UserScope userScope, QueryFactory queryFactory, XmlHandlingService xmlHandlingService) { this.datasetProfileManager = datasetProfileManager; this.environment = environment; this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); this.authorizationService = authorizationService; this.userScope = userScope; this.queryFactory = queryFactory; this.xmlHandlingService = xmlHandlingService; } @RequestMapping(method = RequestMethod.POST, value = {"/upload"}) public ResponseEntity> upload( @RequestParam("file") MultipartFile file, @RequestParam("datasetProfileId") String datasetProfileId, @RequestParam("fieldId") String fieldId) throws IllegalAccessException, IOException, InvalidApplicationException, JAXBException, ParserConfigurationException, InstantiationException, SAXException { this.authorizationService.authorizeForce(Permission.AdminRole, Permission.ManagerRole, Permission.UserRole); String uuid = UUID.randomUUID().toString(); DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).ids(UUID.fromString(datasetProfileId)).authorize(AuthorizationFlags.OwnerOrPermission).first(); DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXml(DefinitionEntity.class, descriptionTemplate.getDefinition()); AtomicBoolean acceptedFile = new AtomicBoolean(false); List fieldEntities = definition != null ? definition.getFieldById(fieldId).stream().filter(x -> x != null && x.getData() != null && x.getData().getFieldType().equals(FieldType.UPLOAD)).toList() : new ArrayList<>(); fieldEntities.forEach(x-> { UploadDataEntity uploadDataEntity = (UploadDataEntity)x.getData(); if (DataSize.ofBytes(file.getSize()).equals(DataSize.ofMegabytes(uploadDataEntity.getMaxFileSizeInMB()))) { acceptedFile.set(true); } if(acceptedFile.get() && uploadDataEntity.getTypes() != null && !uploadDataEntity.getTypes().isEmpty()) { acceptedFile.set(false); for (UploadDataEntity.Option option: uploadDataEntity.getTypes()) { if(Objects.equals(file.getContentType(), option.getValue())) { acceptedFile.set(true); } } } }); 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) throws IOException, InvalidApplicationException { this.authorizationService.authorizeForce(Permission.AdminRole, Permission.ManagerRole, Permission.UserRole, Permission.AnonymousRole); 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())) { 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 -> this.userScope.getUserIdSafe().equals(userInfo.getUser().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); } }