diff --git a/src/main/java/org/qortal/api/resource/ArbitraryResource.java b/src/main/java/org/qortal/api/resource/ArbitraryResource.java index 5825b010..135fad0b 100644 --- a/src/main/java/org/qortal/api/resource/ArbitraryResource.java +++ b/src/main/java/org/qortal/api/resource/ArbitraryResource.java @@ -401,6 +401,26 @@ public class ArbitraryResource { } } + @DELETE + @Path("/resource/{service}/{name}/{identifier}") + @Operation( + summary = "Delete arbitrary resource with supplied service, name and identifier", + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")) + ) + } + ) + @SecurityRequirement(name = "apiKey") + public boolean deleteResource(@PathParam("service") Service service, + @PathParam("name") String name, + @PathParam("identifier") String identifier) { + + Security.checkApiCallAllowed(request); + ArbitraryDataResource resource = new ArbitraryDataResource(name, ResourceIdType.NAME, service, identifier); + return resource.delete(); + } + @POST @Path("/compute") @Operation( diff --git a/src/main/java/org/qortal/arbitrary/ArbitraryDataResource.java b/src/main/java/org/qortal/arbitrary/ArbitraryDataResource.java index 7cee8105..6e2d3dbd 100644 --- a/src/main/java/org/qortal/arbitrary/ArbitraryDataResource.java +++ b/src/main/java/org/qortal/arbitrary/ArbitraryDataResource.java @@ -11,9 +11,14 @@ import org.qortal.list.ResourceListManager; import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; +import org.qortal.settings.Settings; import org.qortal.utils.ArbitraryTransactionUtils; +import org.qortal.utils.FilesystemUtils; import org.qortal.utils.NTP; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -32,6 +37,11 @@ public class ArbitraryDataResource { this.resourceId = resourceId.toLowerCase(); this.resourceIdType = resourceIdType; this.service = service; + + // If identifier is a blank string, or reserved keyword "default", treat it as null + if (identifier == null || identifier.equals("") || identifier.equals("default")) { + identifier = null; + } this.identifier = identifier; } @@ -81,6 +91,42 @@ public class ArbitraryDataResource { return new ArbitraryResourceSummary(ArbitraryResourceStatus.DOWNLOADED); } + public boolean delete() { + try { + this.fetchTransactions(); + + List transactionDataList = new ArrayList<>(this.transactions); + + for (ArbitraryTransactionData transactionData : transactionDataList) { + byte[] hash = transactionData.getData(); + byte[] metadataHash = transactionData.getMetadataHash(); + byte[] signature = transactionData.getSignature(); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(hash, signature); + arbitraryDataFile.setMetadataHash(metadataHash); + + // Delete any chunks or complete files from each transaction + arbitraryDataFile.deleteAll(); + } + + // Also delete cached data for the entire resource + this.deleteCache(); + + return true; + + } catch (DataException | IOException e) { + return false; + } + } + + public void deleteCache() throws IOException { + String baseDir = Settings.getInstance().getTempDataPath(); + String identifier = this.identifier != null ? this.identifier : "default"; + Path cachePath = Paths.get(baseDir, "reader", this.resourceIdType.toString(), this.resourceId, this.service.toString(), identifier); + if (cachePath.toFile().exists()) { + FilesystemUtils.safeDeleteDirectory(cachePath, true); + } + } + private boolean allFilesDownloaded() { try { this.fetchTransactions(); @@ -229,7 +275,7 @@ public class ArbitraryDataResource { @Override public String toString() { - return String.format("%s %s %s %s", this.serviceString(), this.resourceIdString(), this.resourceIdTypeString(), this.identifierString()); + return String.format("%s %s %s", this.serviceString(), this.resourceIdString(), this.identifierString()); } diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java index 6acd3110..9718461c 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java @@ -1,5 +1,6 @@ package org.qortal.controller.arbitrary; +import java.io.IOException; import java.util.*; import org.apache.logging.log4j.LogManager; @@ -343,6 +344,13 @@ public class ArbitraryDataManager extends Thread { // Remove from the signature requests list now that we have all files for this signature ArbitraryDataFileListManager.getInstance().removeFromSignatureRequests(signature58); + + // Delete cached files themselves + try { + resource.deleteCache(); + } catch (IOException e) { + LOGGER.info("Unable to delete cache for resource {}: {}", resource, e.getMessage()); + } } }