From f82f2bd2874b36c5224d1e683cc5be0cd9c581d0 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Wed, 16 Jun 2021 20:03:15 +0100 Subject: [PATCH] Added DELETE /data/file API endpoint This deletes a file referenced by a user supplied SHA256 digest string (which we will use as the file's "ID" in the Qortal data system). In the future this could be extended to delete all associated chunks, but first we need to build out the data chain so we have a way to look up chunks associated with a file hash. --- .../org/qortal/api/resource/DataResource.java | 37 +++++++++++++++++++ .../java/org/qortal/storage/DataFile.java | 17 +++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/qortal/api/resource/DataResource.java b/src/main/java/org/qortal/api/resource/DataResource.java index ccc1547f..b17ec0ad 100644 --- a/src/main/java/org/qortal/api/resource/DataResource.java +++ b/src/main/java/org/qortal/api/resource/DataResource.java @@ -20,6 +20,7 @@ import org.qortal.storage.DataFile; import org.qortal.storage.DataFile.ValidationResult; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.DELETE; import javax.ws.rs.Path; import javax.ws.rs.POST; import javax.ws.rs.core.Context; @@ -95,4 +96,40 @@ public class DataResource { } } + @DELETE + @Path("/file") + @Operation( + summary = "Delete file using supplied base58 encoded SHA256 digest string", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string", example = "FZdHKgF5CbN2tKihvop5Ts9vmWmA9ZyyPY6bC1zivjy4" + ) + ) + ), + responses = { + @ApiResponse( + description = "true if deleted, false if not", + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ) + } + ) + @ApiErrors({ApiError.REPOSITORY_ISSUE}) + public String deleteFile(String base58Digest) { + Security.checkApiCallAllowed(request); + + DataFile dataFile = DataFile.fromBase58Digest(base58Digest); + if (dataFile.delete()) { + return "true"; + } + return "false"; + } + } diff --git a/src/main/java/org/qortal/storage/DataFile.java b/src/main/java/org/qortal/storage/DataFile.java index f3d09c50..ad35aeb7 100644 --- a/src/main/java/org/qortal/storage/DataFile.java +++ b/src/main/java/org/qortal/storage/DataFile.java @@ -72,6 +72,11 @@ public class DataFile { this(file.getPath()); } + public static DataFile fromBase58Digest(String base58Digest) { + String filePath = DataFile.getOutputFilePath(base58Digest); + return new DataFile(filePath); + } + private boolean createDataDirectory() { // Create the data directory if it doesn't exist String dataPath = Settings.getInstance().getDataPath(); @@ -97,7 +102,7 @@ public class DataFile { } } - protected String getOutputFilePath(String base58Digest) { + public static String getOutputFilePath(String base58Digest) { String base58DigestFirst2Chars = base58Digest.substring(0, Math.min(base58Digest.length(), 2)); String base58DigestNext2Chars = base58Digest.substring(2, Math.min(base58Digest.length(), 4)); String outputDirectory = String.format("%s/%s/%s", Settings.getInstance().getDataPath(), base58DigestFirst2Chars, base58DigestNext2Chars); @@ -169,7 +174,7 @@ public class DataFile { return this.chunks.size(); } - public void delete() { + public boolean delete() { // Delete the complete file Path path = Paths.get(this.filePath); if (Files.exists(path)) { @@ -177,15 +182,17 @@ public class DataFile { Files.delete(path); this.cleanupFilesystem(); LOGGER.debug("Deleted file {}", path.toString()); + return true; } catch (IOException e) { LOGGER.warn("Couldn't delete DataFileChunk at path {}", this.filePath); } } + return false; } - public void deleteAll() { + public boolean deleteAll() { // Delete the complete file - this.delete(); + boolean success = this.delete(); // Delete the individual chunks if (this.chunks != null && this.chunks.size() > 0) { @@ -194,8 +201,10 @@ public class DataFile { DataFileChunk chunk = (DataFileChunk) iterator.next(); chunk.delete(); iterator.remove(); + success = true; } } + return success; } protected void cleanupFilesystem() {