Added password protected

- Added download rest endpoint
- Added securityService for file
- Finished upload file
- Added url params
- Added dynamic fileUpload object building
This commit is contained in:
Max W. 2024-02-05 00:48:25 +01:00
parent 973ebb6e9d
commit 0d517dc8df
7 changed files with 130 additions and 7 deletions

View File

@ -4,7 +4,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.rethinkdb.RethinkDB;
import com.rethinkdb.gen.ast.Filter;
import com.rethinkdb.net.Connection;
import de.w665.sharepulse.db.RethinkDBConnector;
import de.w665.sharepulse.db.RethinkDBService;
@ -14,7 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Map;
@Repository

View File

@ -0,0 +1,7 @@
package de.w665.sharepulse.exception;
public class NoDownloadPermissionException extends RuntimeException {
public NoDownloadPermissionException(String message) {
super(message);
}
}

View File

@ -1,6 +1,7 @@
package de.w665.sharepulse.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.google.gson.annotations.SerializedName;
import lombok.*;
import java.util.Date;
@ -12,6 +13,7 @@ import java.util.Date;
@NoArgsConstructor
@ToString
public class FileUpload {
private String id;
private String fileId;
private String fileName;
private long fileSize;
@ -21,4 +23,6 @@ public class FileUpload {
private String uploadedByIpAddress;
private long downloadCount;
private String fileDescription;
private boolean passwordProtected;
private String downloadPassword;
}

View File

@ -0,0 +1,64 @@
package de.w665.sharepulse.rest.mappings;
import de.w665.sharepulse.model.FileUpload;
import de.w665.sharepulse.rest.ApiRestController;
import de.w665.sharepulse.service.FileSecurityService;
import de.w665.sharepulse.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@Slf4j
@RestController
public class Download extends ApiRestController {
private final FileService fileService;
private final FileSecurityService fileSecurityService;
@Autowired
public Download(FileService fileService, FileSecurityService fileSecurityService) {
this.fileService = fileService;
this.fileSecurityService = fileSecurityService;
}
@GetMapping("/download")
public ResponseEntity<Resource> download(@RequestParam String fileId,
@RequestParam(value = "password", required = false) String password) throws IOException {
FileUpload fileUpload = fileService.getFileUploadByFileId(fileId);
fileSecurityService.verifyDownloadPermission(fileUpload, password);
// TODO: Update download count in database (single download will not work without this)
File file = fileService.getFileById(fileId);
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"edmbass.flac\"");
//headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"");
headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
headers.add(HttpHeaders.PRAGMA, "no-cache");
headers.add(HttpHeaders.EXPIRES, "0");
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
}

View File

@ -26,13 +26,16 @@ public class Upload extends ApiRestController {
// Currently testing
@PostMapping("/upload")
public ResponseEntity<String> getUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
public ResponseEntity<String> getUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request,
@RequestParam(value = "password", required = false) String password,
@RequestParam(value = "singleDownload", defaultValue = "false") boolean singleDownload,
@RequestParam(value = "fileDescription", required = false) String fileDescription) {
if (file.isEmpty()) {
log.debug("User tried to upload an empty file. IP: " + request.getRemoteAddr());
return new ResponseEntity<>("Please select a file to upload.", HttpStatus.NOT_ACCEPTABLE);
}
String fileId = fileService.processUploadedFile(file, request.getRemoteAddr());
String fileId = fileService.processUploadedFile(file, request.getRemoteAddr(), password, singleDownload, fileDescription);
log.debug("User uploaded file " + file.getOriginalFilename() + " from IP " + request.getRemoteAddr() + " successfully.");
return new ResponseEntity<>("File " + file.getOriginalFilename() + " uploaded successfully! ID(" + fileId + ")", HttpStatus.OK);
}

View File

@ -0,0 +1,37 @@
package de.w665.sharepulse.service;
import de.w665.sharepulse.exception.NoDownloadPermissionException;
import de.w665.sharepulse.model.FileUpload;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.File;
@Slf4j
@Service
public class FileSecurityService {
public boolean verifyDownloadPermission(FileUpload file, String password) throws NoDownloadPermissionException {
if (!file.isPasswordProtected() && !file.isSingleDownload()) {
return true;
}
if (file.isSingleDownload()) {
if(file.getDownloadCount() > 0) {
throw new NoDownloadPermissionException("File has already been downloaded.");
}
if(!file.isPasswordProtected()) {
return true;
}
}
if(file.getDownloadPassword().equals(password)) {
return true;
}
throw new NoDownloadPermissionException("Password protected file can only be downloaded with correct password.");
}
}

View File

@ -53,7 +53,7 @@ public class FileService {
}
}
public String processUploadedFile(MultipartFile file, String uploaderIp) {
public String processUploadedFile(MultipartFile file, String uploaderIp, String password, boolean singleDownload, String fileDescription) {
String fileId = fileIdService.generateNewUniqueId();
@ -61,13 +61,17 @@ public class FileService {
.fileId(fileId)
.fileName(file.getOriginalFilename())
.fileSize(file.getSize())
.singleDownload(false)
.singleDownload(singleDownload)
.uploadDate(new Date())
.uploadedByIpAddress(uploaderIp)
.downloadCount(0)
.fileDescription("fileDescription")
.fileDescription(fileDescription)
.passwordProtected(password != null && !password.isEmpty())
.downloadPassword(password)
.build();
System.out.println(fileUpload.toString());
fileUploadRepository.insertFileUpload(fileUpload);
@ -87,8 +91,14 @@ public class FileService {
return new File(getTempDirPath() + File.separator + fileId);
}
public FileUpload getFileUploadByFileId(String fileId) {
return fileUploadRepository.retrieveFileUploadByFileId(fileId);
}
private String getTempDirPath() {
return System.getProperty("user.dir") + tempDirPath;
}
}