2022-03-16 11:14:08 +01:00
package eu.eudat.controllers ;
import com.fasterxml.jackson.annotation.JsonInclude ;
import com.fasterxml.jackson.databind.JsonNode ;
import com.fasterxml.jackson.databind.ObjectMapper ;
2023-10-18 17:52:03 +02:00
import eu.eudat.authorization.Permission ;
import eu.eudat.commons.scope.user.UserScope ;
2023-10-18 12:04:53 +02:00
import eu.eudat.data.old.Dataset ;
import eu.eudat.data.old.FileUpload ;
2022-03-16 11:14:08 +01:00
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.types.ApiMessageCode ;
2023-10-18 17:52:03 +02:00
import gr.cite.commons.web.authz.service.AuthorizationService ;
2022-03-16 11:14:08 +01:00
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 ;
2023-10-03 16:29:45 +02:00
import jakarta.transaction.Transactional ;
2023-10-18 17:52:03 +02:00
import javax.management.InvalidApplicationException ;
2022-03-16 11:14:08 +01:00
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 ;
2023-10-18 17:52:03 +02:00
private final AuthorizationService authorizationService ;
private final UserScope userScope ;
2022-03-16 11:14:08 +01:00
@Autowired
2023-10-18 17:52:03 +02:00
public FileController ( DatasetProfileManager datasetProfileManager , Environment environment , ApiContext apiContext , AuthorizationService authorizationService , UserScope userScope ) {
2022-03-16 11:14:08 +01:00
this . datasetProfileManager = datasetProfileManager ;
this . environment = environment ;
this . databaseRepository = apiContext . getOperationsContext ( ) . getDatabaseRepository ( ) ;
2023-10-18 17:52:03 +02:00
this . authorizationService = authorizationService ;
this . userScope = userScope ;
2022-03-16 11:14:08 +01:00
}
@RequestMapping ( method = RequestMethod . POST , value = { " /upload " } )
public ResponseEntity < ResponseItem < String > > upload (
2023-10-18 17:52:03 +02:00
@RequestParam ( " file " ) MultipartFile file , @RequestParam ( " datasetProfileId " ) String datasetProfileId , @RequestParam ( " fieldId " ) String fieldId )
throws IllegalAccessException , IOException , InvalidApplicationException {
this . authorizationService . authorizeForce ( Permission . AdminRole , Permission . ManagerRole , Permission . UserRole ) ;
2022-03-16 11:14:08 +01:00
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 < JsonNode > fieldNodes = new HashSet < > ( ) ;
fieldNodes . addAll ( JsonSearcher . findNodes ( propertiesJson , " id " , fieldId , false ) ) ;
// AtomicReference<String> 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 < String , Object > 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 < String , Object > 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 < String > ( ) . 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 < String > ( ) . payload ( uuid )
. status ( ApiMessageCode . SUCCESS_MESSAGE ) . message ( " " ) ) ;
}
@RequestMapping ( method = RequestMethod . POST , value = { " /delete-temp " } )
public ResponseEntity < ResponseItem < String > > 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 < String > ( ) . payload ( deleted . toString ( ) )
. status ( ApiMessageCode . SUCCESS_MESSAGE ) . message ( " " ) ) ;
}
@Transactional
@RequestMapping ( method = RequestMethod . GET , value = { " {id} " } , produces = " application/json " )
public @ResponseBody
2023-10-18 17:52:03 +02:00
ResponseEntity download ( @PathVariable String id ) throws IOException , InvalidApplicationException {
this . authorizationService . authorizeForce ( Permission . AdminRole , Permission . ManagerRole , Permission . UserRole , Permission . AnonymousRole ) ;
2022-03-16 11:14:08 +01:00
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 ( ) ) ) {
2023-10-18 12:04:53 +02:00
Dataset datasetEntity = databaseRepository . getDatasetDao ( ) . find ( fileUpload . getEntityId ( ) , HintedModelFactory . getHint ( DatasetWizardModel . class ) ) ;
2022-03-16 11:14:08 +01:00
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 ( )
2023-10-24 17:00:11 +02:00
. stream ( ) . filter ( userInfo - > this . userScope . getUserIdSafe ( ) . equals ( userInfo . getUser ( ) . getId ( ) ) )
2022-03-16 11:14:08 +01:00
. 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 ) ;
}
}