Added generic PUT, PATCH, and GET /arbitrary API endpoints

These will likely avoid the need for some of the /site APIs.
This commit is contained in:
CalDescent 2021-10-29 16:45:08 +01:00
parent c9356d0ff5
commit f1939fdc2b

View File

@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.api.*;
import org.qortal.api.resource.TransactionsResource.ConfirmationStatus;
import org.qortal.arbitrary.ArbitraryDataReader;
import org.qortal.arbitrary.ArbitraryDataTransactionBuilder;
import org.qortal.data.transaction.ArbitraryTransactionData;
import org.qortal.data.transaction.ArbitraryTransactionData.*;
@ -220,16 +221,51 @@ public class ArbitraryResource {
}
}
@POST
@Path("/upload/creator/{publickey}")
@GET
@Path("/{service}/{name}")
@Operation(
summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path to a single file",
summary = "Fetch local file path for data with supplied service and name",
description = "An optional rebuild boolean can be supplied. If true, any existing cached data will be invalidated.",
responses = {
@ApiResponse(
description = "Path to file structure containing requested data",
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
type = "string"
)
)
)
}
)
public String get(@PathParam("service") String serviceString,
@PathParam("name") String name,
@QueryParam("rebuild") boolean rebuild) {
Security.checkApiCallAllowed(request);
Service service = Service.valueOf(serviceString);
ArbitraryDataReader arbitraryDataReader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service);
try {
arbitraryDataReader.loadSynchronously(rebuild);
return arbitraryDataReader.getFilePath().toAbsolutePath().toString();
} catch (Exception e) {
LOGGER.info(String.format("Unable to load %s %s: %s", service, name, e.getMessage()));
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@PUT
@Path("/{service}/{name}/{publickey}")
@Operation(
summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path, using the PUT method",
description = "A PUT transaction replaces the data held for this name and service in its entirety.",
requestBody = @RequestBody(
required = true,
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
type = "string", example = "qortal.jar"
type = "string", example = "/Users/user/Documents/MyDirectoryOrFile"
)
)
),
@ -245,21 +281,60 @@ public class ArbitraryResource {
)
}
)
@ApiErrors({ApiError.REPOSITORY_ISSUE})
public String uploadFileAtPath(@PathParam("method") String methodString,
@PathParam("publickey") String publicKey58,
public String put(@PathParam("service") String serviceString,
@PathParam("name") String name,
@PathParam("publickey") String publicKey58,
String path) {
Security.checkApiCallAllowed(request);
// It's too dangerous to allow user-supplied filenames in weaker security contexts
return this.upload(Method.PUT, Service.valueOf(serviceString), publicKey58, name, path);
}
@PATCH
@Path("/{service}/{name}/{publickey}")
@Operation(
summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path, using the PATCH method",
description = "A PATCH transaction calculates the delta between the current state on the on-chain state, " +
"and then publishes only the differences.",
requestBody = @RequestBody(
required = true,
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
type = "string", example = "/Users/user/Documents/MyDirectoryOrFile"
)
)
),
responses = {
@ApiResponse(
description = "raw, unsigned, ARBITRARY transaction encoded in Base58",
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
type = "string"
)
)
)
}
)
public String patch(@PathParam("service") String serviceString,
@PathParam("name") String name,
@PathParam("publickey") String publicKey58,
String path) {
Security.checkApiCallAllowed(request);
return this.upload(Method.PATCH, Service.valueOf(serviceString), publicKey58, name, path);
}
private String upload(Method method, Service service, String publicKey58, String name, String path) {
// It's too dangerous to allow user-supplied file paths in weaker security contexts
if (Settings.getInstance().isApiRestricted()) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NON_PRODUCTION);
}
try {
ArbitraryDataTransactionBuilder transactionBuilder = new ArbitraryDataTransactionBuilder(
publicKey58, Paths.get(path), name, Method.valueOf(methodString), Service.ARBITRARY_DATA
publicKey58, Paths.get(path), name, method, service
);
ArbitraryTransactionData transactionData = transactionBuilder.build();