Browse Source

Added POST /lists/blacklist/addresses and DELETE /lists/blacklist/addresses API endpoints.

These are the same as the /lists/blacklist/address/{address} endpoints but allow a JSON array of addresses to be specified in the request body. They currently return true if
lists
CalDescent 3 years ago
parent
commit
9fdc901b7a
  1. 18
      src/main/java/org/qortal/api/model/AddressListRequest.java
  2. 153
      src/main/java/org/qortal/api/resource/ListsResource.java
  3. 11
      src/main/java/org/qortal/list/ResourceList.java
  4. 34
      src/main/java/org/qortal/list/ResourceListManager.java

18
src/main/java/org/qortal/api/model/AddressListRequest.java

@ -0,0 +1,18 @@
package org.qortal.api.model;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import java.util.List;
@XmlAccessorType(XmlAccessType.FIELD)
public class AddressListRequest {
@Schema(description = "A list of addresses")
public List<String> addresses;
public AddressListRequest() {
}
}

153
src/main/java/org/qortal/api/resource/ListsResource.java

@ -3,10 +3,12 @@ package org.qortal.api.resource;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.qortal.api.*; import org.qortal.api.*;
import org.qortal.api.model.AddressListRequest;
import org.qortal.crypto.Crypto; import org.qortal.crypto.Crypto;
import org.qortal.data.account.AccountData; import org.qortal.data.account.AccountData;
import org.qortal.list.ResourceListManager; import org.qortal.list.ResourceListManager;
@ -50,7 +52,7 @@ public class ListsResource {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN);
// Valid address, so go ahead and blacklist it // Valid address, so go ahead and blacklist it
boolean success = ResourceListManager.getInstance().addAddressToBlacklist(address); boolean success = ResourceListManager.getInstance().addAddressToBlacklist(address, true);
return success ? "true" : "false"; return success ? "true" : "false";
} catch (DataException e) { } catch (DataException e) {
@ -58,6 +60,78 @@ public class ListsResource {
} }
} }
@POST
@Path("/blacklist/addresses")
@Operation(
summary = "Add one or more QORT addresses to the local blacklist",
requestBody = @RequestBody(
required = true,
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(
implementation = AddressListRequest.class
)
)
),
responses = {
@ApiResponse(
description = "Returns true if all addresses were processed, false if any couldn't be " +
"processed, or an exception on failure. If false or an exception is returned, " +
"the list will not be updated, and the request will need to be re-issued.",
content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean"))
)
}
)
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN, ApiError.REPOSITORY_ISSUE})
public String addAddressesToBlacklist(AddressListRequest addressListRequest) {
if (addressListRequest == null || addressListRequest.addresses == null) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
}
int successCount = 0;
int errorCount = 0;
try (final Repository repository = RepositoryManager.getRepository()) {
for (String address : addressListRequest.addresses) {
if (!Crypto.isValidAddress(address)) {
errorCount++;
continue;
}
AccountData accountData = repository.getAccountRepository().getAccount(address);
// Not found?
if (accountData == null) {
errorCount++;
continue;
}
// Valid address, so go ahead and blacklist it
boolean success = ResourceListManager.getInstance().addAddressToBlacklist(address, false);
if (success) {
successCount++;
}
else {
errorCount++;
}
}
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
if (successCount > 0 && errorCount == 0) {
// All were successful, so save the blacklist
ResourceListManager.getInstance().saveBlacklist();
return "true";
}
else {
// Something went wrong, so revert
ResourceListManager.getInstance().revertBlacklist();
return "false";
}
}
@DELETE @DELETE
@Path("/blacklist/address/{address}") @Path("/blacklist/address/{address}")
@ -82,7 +156,7 @@ public class ListsResource {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN);
// Valid address, so go ahead and blacklist it // Valid address, so go ahead and blacklist it
boolean success = ResourceListManager.getInstance().removeAddressFromBlacklist(address); boolean success = ResourceListManager.getInstance().removeAddressFromBlacklist(address, true);
return success ? "true" : "false"; return success ? "true" : "false";
} catch (DataException e) { } catch (DataException e) {
@ -90,10 +164,83 @@ public class ListsResource {
} }
} }
@DELETE
@Path("/blacklist/addresses")
@Operation(
summary = "Remove one or more QORT addresses from the local blacklist",
requestBody = @RequestBody(
required = true,
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(
implementation = AddressListRequest.class
)
)
),
responses = {
@ApiResponse(
description = "Returns true if all addresses were processed, false if any couldn't be " +
"processed, or an exception on failure. If false or an exception is returned, " +
"the list will not be updated, and the request will need to be re-issued.",
content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean"))
)
}
)
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN, ApiError.REPOSITORY_ISSUE})
public String removeAddressesFromBlacklist(AddressListRequest addressListRequest) {
if (addressListRequest == null || addressListRequest.addresses == null) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
}
int successCount = 0;
int errorCount = 0;
try (final Repository repository = RepositoryManager.getRepository()) {
for (String address : addressListRequest.addresses) {
if (!Crypto.isValidAddress(address)) {
errorCount++;
continue;
}
AccountData accountData = repository.getAccountRepository().getAccount(address);
// Not found?
if (accountData == null) {
errorCount++;
continue;
}
// Valid address, so go ahead and blacklist it
// Don't save as we will do this at the end of the process
boolean success = ResourceListManager.getInstance().removeAddressFromBlacklist(address, false);
if (success) {
successCount++;
}
else {
errorCount++;
}
}
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
if (successCount > 0 && errorCount == 0) {
// All were successful, so save the blacklist
ResourceListManager.getInstance().saveBlacklist();
return "true";
}
else {
// Something went wrong, so revert
ResourceListManager.getInstance().revertBlacklist();
return "false";
}
}
@GET @GET
@Path("/blacklist/address/{address}") @Path("/blacklist/address/{address}")
@Operation( @Operation(
summary = "Checks if an address is present in the local blacklist", summary = "Check if an address is present in the local blacklist",
responses = { responses = {
@ApiResponse( @ApiResponse(
description = "Returns true or false if the list was queried, or an exception on failure", description = "Returns true or false if the list was queried, or an exception on failure",

11
src/main/java/org/qortal/list/ResourceList.java

@ -17,6 +17,8 @@ import java.util.List;
public class ResourceList { public class ResourceList {
private static final Logger LOGGER = LogManager.getLogger(ResourceList.class);
private String category; private String category;
private String resourceName; private String resourceName;
private List<String> list; private List<String> list;
@ -84,6 +86,15 @@ public class ResourceList {
return true; return true;
} }
public boolean revert() {
try {
return this.load();
} catch (IOException e) {
LOGGER.info("Unable to revert {} {}", this.resourceName, this.category);
}
return false;
}
/* List management */ /* List management */

34
src/main/java/org/qortal/list/ResourceListManager.java

@ -2,7 +2,6 @@ package org.qortal.list;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.util.IO;
import java.io.IOException; import java.io.IOException;
@ -29,10 +28,12 @@ public class ResourceListManager {
return instance; return instance;
} }
public boolean addAddressToBlacklist(String address) { public boolean addAddressToBlacklist(String address, boolean save) {
try { try {
this.addressBlacklist.add(address); this.addressBlacklist.add(address);
this.addressBlacklist.save(); if (save) {
this.addressBlacklist.save();
}
return true; return true;
} catch (IllegalStateException | IOException e) { } catch (IllegalStateException | IOException e) {
@ -41,10 +42,13 @@ public class ResourceListManager {
} }
} }
public boolean removeAddressFromBlacklist(String address) { public boolean removeAddressFromBlacklist(String address, boolean save) {
try { try {
this.addressBlacklist.remove(address); this.addressBlacklist.remove(address);
this.addressBlacklist.save();
if (save) {
this.addressBlacklist.save();
}
return true; return true;
} catch (IllegalStateException | IOException e) { } catch (IllegalStateException | IOException e) {
@ -60,4 +64,24 @@ public class ResourceListManager {
return this.addressBlacklist.contains(address); return this.addressBlacklist.contains(address);
} }
public void saveBlacklist() {
if (this.addressBlacklist == null) {
return;
}
try {
this.addressBlacklist.save();
} catch (IOException e) {
LOGGER.info("Unable to save blacklist - reverting back to last saved state");
this.addressBlacklist.revert();
}
}
public void revertBlacklist() {
if (this.addressBlacklist == null) {
return;
}
this.addressBlacklist.revert();
}
} }

Loading…
Cancel
Save