Merge branch 'main' into feature/download

This commit is contained in:
Max W. 2024-02-16 22:16:16 +01:00
commit 374d4dc40d
6 changed files with 62 additions and 26 deletions

View File

@ -14,6 +14,18 @@
<button class="btn btn-primary w-full max-w-xs flex justify-center items-center mb-4" (click)="checkFile()"> <button class="btn btn-primary w-full max-w-xs flex justify-center items-center mb-4" (click)="checkFile()">
Download Download
</button> </button>
<p class="text-gray-600 text-center w-2/3">Files are available for a limited time. Ensure the code or link is correct.</p> <p class="text-gray-600 text-center w-2/3">Files are available for a limited time. Ensure the code or link is correct and the file is still downloadable.</p>
</div> </div>
</div> </div>
<dialog #password_modal class="modal">
<div class="modal-box">
<h3 class="font-bold text-lg">Please enter the file password</h3>
<p class="py-4">Please enter the download password:</p>
<input type="password" placeholder="Password..." class="input input-bordered w-full max-w-xs" />
<div class="modal-action">
<form method="dialog">
<button class="btn">Cancel download</button>
</form>
</div>
</div>
</dialog>

View File

@ -3,18 +3,13 @@ package de.w665.sharepulse.db;
import com.rethinkdb.RethinkDB; import com.rethinkdb.RethinkDB;
import com.rethinkdb.gen.exc.ReqlOpFailedError; import com.rethinkdb.gen.exc.ReqlOpFailedError;
import com.rethinkdb.net.Connection; import com.rethinkdb.net.Connection;
import com.rethinkdb.net.Result;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@Slf4j @Slf4j
@Service @Service
public class RethinkDBService { public class RethinkDBService {
@ -24,6 +19,9 @@ public class RethinkDBService {
private final RethinkDB r; private final RethinkDB r;
private final Connection connection; private final Connection connection;
@Value("${sharepulse.auto-reset-on-startup}")
private boolean autoResetOnStartup;
@Autowired @Autowired
public RethinkDBService(RethinkDBConfig config, RethinkDBConnector connector) { public RethinkDBService(RethinkDBConfig config, RethinkDBConnector connector) {
this.config = config; this.config = config;
@ -66,10 +64,13 @@ public class RethinkDBService {
r.db(config.getDatabase()).tableCreate("file_uploads").run(connection).stream(); r.db(config.getDatabase()).tableCreate("file_uploads").run(connection).stream();
log.debug("Table 'file_uploads' created successfully."); log.debug("Table 'file_uploads' created successfully.");
} catch (ReqlOpFailedError e) { } catch (ReqlOpFailedError e) {
log.debug("Table 'file_uploads' already exists. Clearing content..."); log.debug("Table 'file_uploads' already exists.");
if(autoResetOnStartup) {
log.debug("Clearing content...");
r.db(config.getDatabase()).table("file_uploads").delete().run(connection); r.db(config.getDatabase()).table("file_uploads").delete().run(connection);
log.debug("Table 'file_uploads' cleared successfully."); log.debug("Table 'file_uploads' cleared successfully.");
} }
}
// rethinkdb check if table id_store exists // rethinkdb check if table id_store exists
try { try {

View File

@ -8,7 +8,6 @@ import de.w665.sharepulse.service.FileService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -71,4 +70,16 @@ public class Download extends ApiRestController {
.contentType(MediaType.APPLICATION_OCTET_STREAM) .contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource); .body(resource);
} }
@GetMapping("/download-info")
public ResponseEntity<Object> getDownloadInfo(@RequestParam String fileId) {
FileUpload fileUpload = fileService.getFileUploadByFileId(fileId);
Map<String, Object> response = new HashMap<>();
response.put("fileId", fileUpload.getFileId());
response.put("passwordProtected", fileUpload.isPasswordProtected());
response.put("singleDownload", fileUpload.isSingleDownload());
return new ResponseEntity<>(response, HttpStatus.OK);
}
} }

View File

@ -9,12 +9,14 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
@Slf4j @Slf4j
@RestController @RestController
public class Upload extends ApiRestController { public class Upload extends ApiRestController {
@ -28,7 +30,7 @@ public class Upload extends ApiRestController {
// Currently testing // Currently testing
@PostMapping("/upload") @PostMapping("/upload")
public ResponseEntity<String> getUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request, public ResponseEntity<Map<String, Object>> getUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request,
@RequestParam(value = "passwordProtected", required = false) Boolean passwordProtected, @RequestParam(value = "passwordProtected", required = false) Boolean passwordProtected,
@RequestParam(value = "singleDownload", defaultValue = "false") boolean singleDownload, @RequestParam(value = "singleDownload", defaultValue = "false") boolean singleDownload,
@RequestParam(value = "fileDescription", required = false) String fileDescription) { @RequestParam(value = "fileDescription", required = false) String fileDescription) {
@ -37,21 +39,23 @@ public class Upload extends ApiRestController {
if (file.isEmpty()) { if (file.isEmpty()) {
log.debug("User tried to upload an empty file. IP: " + request.getRemoteAddr()); log.debug("User tried to upload an empty file. IP: " + request.getRemoteAddr());
return new ResponseEntity<>("Please select a file to upload.", HttpStatus.NOT_ACCEPTABLE); Map<String, Object> response = new HashMap<>();
response.put("message", "Please select a file to upload.");
return new ResponseEntity<>(response, HttpStatus.NOT_ACCEPTABLE);
} }
FileUpload fileUpload = fileService.processUploadedFile(file, request.getRemoteAddr(), passwordProtected, singleDownload, fileDescription); FileUpload fileUpload = fileService.processUploadedFile(file, request.getRemoteAddr(), passwordProtected, singleDownload, fileDescription);
log.debug("User uploaded file " + file.getOriginalFilename() + " from IP " + request.getRemoteAddr() + " successfully."); log.debug("User uploaded file " + file.getOriginalFilename() + " from IP " + request.getRemoteAddr() + " successfully.");
JsonObject response = new JsonObject(); Map<String, Object> response = new HashMap<>();
response.addProperty("fileId", fileUpload.getFileId()); response.put("fileId", fileUpload.getFileId());
response.addProperty("fileName", fileUpload.getFileName()); response.put("fileName", fileUpload.getFileName());
response.addProperty("message", "File " + file.getOriginalFilename() + " uploaded successfully!"); response.put("message", "File " + fileUpload.getFileName() + " uploaded successfully!");
response.addProperty("passwordProtected", fileUpload.isPasswordProtected()); response.put("passwordProtected", fileUpload.isPasswordProtected());
response.addProperty("singleDownload", fileUpload.isSingleDownload()); response.put("singleDownload", fileUpload.isSingleDownload());
response.addProperty("uploadDate", fileUpload.getUploadDate().toString()); response.put("uploadDate", fileUpload.getUploadDate().toString());
response.addProperty("password", fileUpload.getDownloadPassword()); response.put("password", fileUpload.getDownloadPassword());
return new ResponseEntity<>(response.toString(), HttpStatus.OK); return new ResponseEntity<>(response, HttpStatus.OK);
} }
} }

View File

@ -29,6 +29,9 @@ public class FileService {
@Value("${sharepulse.temp-filestore-path}") @Value("${sharepulse.temp-filestore-path}")
private String tempDirPath; private String tempDirPath;
@Value("${sharepulse.auto-reset-on-startup}")
private boolean autoResetOnStartup;
@Autowired @Autowired
public FileService(FileIdService fileIdService, FileSecurityService fileSecurityService, FileUploadRepository fileUploadRepository) { public FileService(FileIdService fileIdService, FileSecurityService fileSecurityService, FileUploadRepository fileUploadRepository) {
this.fileIdService = fileIdService; this.fileIdService = fileIdService;
@ -45,10 +48,14 @@ public class FileService {
Files.createDirectory(path); Files.createDirectory(path);
log.debug("Directory created"); log.debug("Directory created");
} else { } else {
log.debug("Directory already exists. Clearing content."); log.debug("Directory already exists.");
if(autoResetOnStartup) {
log.debug("Clearing content...");
FileUtils.cleanDirectory(new File(getTempDirPath())); FileUtils.cleanDirectory(new File(getTempDirPath()));
log.debug("Directory content cleared."); log.debug("Directory content cleared.");
} }
}
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -2,6 +2,7 @@
sharepulse.temp-filestore-path=/temp-filestore sharepulse.temp-filestore-path=/temp-filestore
sharepulse.filepassword-length=6 sharepulse.filepassword-length=6
sharepulse.filepassword-charset=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 sharepulse.filepassword-charset=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
sharepulse.auto-reset-on-startup=false
# Static path # Static path
spring.web.resources.static-locations=classpath:/static/browser/ spring.web.resources.static-locations=classpath:/static/browser/