Added cleanup job

This commit is contained in:
Max W. 2024-02-18 22:56:26 +01:00
parent 7d253675c8
commit e179cdf2dc
10 changed files with 140 additions and 30 deletions

View File

@ -24,7 +24,7 @@ export class DownloadComponent {
@ViewChild('download_not_possible') download_not_possible: ElementRef<HTMLDialogElement> | undefined;
@ViewChild('file_not_found_modal') file_not_found_modal: ElementRef<HTMLDialogElement> | undefined;
inputFileId: string = "2402183";
inputFileId: string = "";
fileId: string = "";
filePassword: string = "";
fileName: string = "";

View File

@ -4,6 +4,10 @@ import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
/**
* Service to open the privacy policy and terms of use modals
* The modals are controlled by the navbar component
*/
export class LegalService {
private openModalSource = new Subject<string>();

View File

@ -1,9 +1,11 @@
package de.w665.sharepulse.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableScheduling
@Configuration
public class MvcConfig implements WebMvcConfigurer {

View File

@ -35,22 +35,6 @@ public class RethinkDBService {
@PostConstruct
public void initialize() {
//rethinkdb check if database exists
/*Result<Object> result = r.dbList().run(connection);
List<String> databases = new ArrayList<>();
Object db = result.first();
ArrayList<String> dbList = (ArrayList<String>) db;
databases.addAll(dbList);
if (!databases.contains("sharepulse")) {
r.dbCreate("sharepulse").run(connection);
log.info("Database 'sharepulse' created successfully.");
} else {
log.info("Database 'sharepulse' already exists. No action needed.");
}*/
// rethinkdb check if database exists
try {
r.dbCreate(config.getDatabase()).run(connection).stream();
@ -79,6 +63,14 @@ public class RethinkDBService {
} catch (ReqlOpFailedError e) {
log.debug("Table 'id_store' already exists. No action needed.");
}
// rethinkdb check if table expired_file_uploads exists
try {
r.db(config.getDatabase()).tableCreate("expired_file_uploads").run(connection).stream();
log.debug("Table 'expired_file_uploads' created successfully.");
} catch (ReqlOpFailedError e) {
log.debug("Table 'expired_file_uploads' already exists. No action needed.");
}
log.info("Database ready for operation!");
}

View File

@ -0,0 +1,41 @@
package de.w665.sharepulse.db.repo;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.rethinkdb.RethinkDB;
import com.rethinkdb.net.Connection;
import de.w665.sharepulse.db.RethinkDBConnector;
import de.w665.sharepulse.model.FileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.lang.reflect.Type;
import java.util.Map;
@Repository
public class ExpiredFileUploadRepository {
private final RethinkDB r;
private final Connection connection;
private final Gson gson;
@Autowired
public ExpiredFileUploadRepository(RethinkDBConnector connector) {
this.r = connector.getR();
this.connection = connector.getConnection();
this.gson = new GsonBuilder().create();
}
public void insertExpiredFileUpload(FileUpload fileUpload) {
String json = gson.toJson(fileUpload);
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> map = gson.fromJson(json, type);
long uploadDateTimestamp = fileUpload.getUploadDate().getTime() / 1000;
map.put("uploadDate", uploadDateTimestamp);
r.db("sharepulse").table("expired_file_uploads").insert(map).run(connection);
}
}

View File

@ -6,35 +6,28 @@ import com.google.gson.reflect.TypeToken;
import com.rethinkdb.RethinkDB;
import com.rethinkdb.net.Connection;
import de.w665.sharepulse.db.RethinkDBConnector;
import de.w665.sharepulse.db.RethinkDBService;
import de.w665.sharepulse.model.FileUpload;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.*;
@Repository
@RequiredArgsConstructor
public class FileUploadRepository {
private final RethinkDBService rethinkDBService;
private final RethinkDB r;
private final Connection connection;
private final Gson gson;
@Autowired
public FileUploadRepository(RethinkDBService rethinkDBService, RethinkDBConnector connector) {
this.rethinkDBService = rethinkDBService;
public FileUploadRepository(RethinkDBConnector connector) {
this.r = connector.getR();
this.connection = connector.getConnection();
this.gson = new GsonBuilder()
.setDateFormat("dd-MM-yyyy HH:mm:ss") // date field formatting
.create();
this.gson = new GsonBuilder().create();
}
public void insertFileUpload(FileUpload fileUpload) {
@ -43,6 +36,9 @@ public class FileUploadRepository {
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> map = gson.fromJson(json, type);
long uploadDateTimestamp = fileUpload.getUploadDate().getTime() / 1000;
map.put("uploadDate", uploadDateTimestamp);
r.db("sharepulse").table("file_uploads").insert(map).run(connection);
}
@ -72,4 +68,34 @@ public class FileUploadRepository {
.update(map)
.run(connection);
}
public void deleteFileUploadByFileId(String fileId) {
r.db("sharepulse").table("file_uploads")
.filter(r.hashMap("fileId", fileId))
.delete()
.run(connection);
}
public List<FileUpload> getAllExpiredFileUploads() {
long timestamp = getOneMinuteAgoTimestamp();
List<FileUpload> olderFiles = r.db("sharepulse").table("file_uploads")
.filter(row -> row.g("uploadDate").lt(timestamp))
.run(connection, FileUpload.class)
.toList();
return olderFiles;
}
private long get24HoursAgoTimestamp() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR, -24);
return calendar.getTimeInMillis() / 1000;
}
private long getOneMinuteAgoTimestamp() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, -1); // Subtract 1 minute
return calendar.getTimeInMillis() / 1000; // Convert milliseconds to seconds (Unix timestamp)
}
}

View File

@ -18,7 +18,7 @@ public class FileUpload {
private String fileName;
private long fileSize;
private boolean singleDownload;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy HH:mm:ss", timezone = "CET")
@JsonFormat(timezone = "ETC")
private Date uploadDate;
private String uploadedByIpAddress;
private long downloadCount;

View File

@ -0,0 +1,36 @@
package de.w665.sharepulse.service;
import de.w665.sharepulse.db.repo.FileUploadRepository;
import de.w665.sharepulse.db.repo.ExpiredFileUploadRepository;
import de.w665.sharepulse.model.FileUpload;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class FileCleanupService {
private final FileUploadRepository fileUploadRepository;
private final ExpiredFileUploadRepository expiredFileUploadRepository;
private final FileService fileService;
public FileCleanupService(FileUploadRepository fileUploadRepository, ExpiredFileUploadRepository expiredFileUploadRepository, FileService fileService) {
this.fileUploadRepository = fileUploadRepository;
this.expiredFileUploadRepository = expiredFileUploadRepository;
this.fileService = fileService;
}
@Scheduled(cron = "0 0 * * * *")
public void cleanup() {
log.debug("Running cleanup...");
List<FileUpload> expFileUploads = fileUploadRepository.getAllExpiredFileUploads();
for (FileUpload fileUpload : expFileUploads) {
fileService.deleteFile(fileUpload);
expiredFileUploadRepository.insertExpiredFileUpload(fileUpload);
log.debug("Moved file " + fileUpload.getFileId() + " to old_file_uploads table.");
}
}
}

View File

@ -96,7 +96,6 @@ public class FileService {
fileUploadRepository.insertFileUpload(fileUpload);
// TODO: rename file to fileID
Path path = Paths.get(getTempDirPath() + File.separator + fileId);
try {
Files.write(path, file.getBytes());
@ -122,6 +121,16 @@ public class FileService {
return fileUpload.getDownloadCount();
}
public void deleteFile(FileUpload fileUpload) {
fileUploadRepository.deleteFileUploadByFileId(fileUpload.getFileId());
Path path = Paths.get(getTempDirPath() + File.separator + fileUpload.getFileId());
try {
Files.delete(path);
log.debug("File " + fileUpload.getFileId() + " deleted from disk.");
} catch (IOException e) {
log.error("Error deleting file " + fileUpload.getFileId() + " from disk: " + e.getMessage());
}
}
private String getTempDirPath() {
return System.getProperty("user.dir") + tempDirPath;

View File

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