forked from Qortal-Forker/qortal
		
	Add support for API key security, where X-API-KEY header must match apiKey from settings
apiKey in settings is null by default at this point, for backwards compatibility. In the future, the Windows installer could generate a UUID for apiKey. apiKey in settings needs to be at least 8 characters. API calls in the documentation engine are now marked with an open/closed padlock to show where API key might be required. Add support for API key security, where X-API-KEY header must match apiKey from settings apiKey in settings is null by default at this point, for backwards compatibility. In the future, the Windows installer could generate a UUID for apiKey. apiKey in settings needs to be at least 8 characters. API calls in the documentation engine are now marked with an open/closed padlock to show where API key might be required.
This commit is contained in:
		@@ -5,10 +5,20 @@ import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
 | 
			
		||||
public class Security {
 | 
			
		||||
import org.qortal.settings.Settings;
 | 
			
		||||
 | 
			
		||||
public abstract class Security {
 | 
			
		||||
 | 
			
		||||
	public static final String API_KEY_HEADER = "X-API-KEY";
 | 
			
		||||
 | 
			
		||||
	// TODO: replace with proper authentication
 | 
			
		||||
	public static void checkApiCallAllowed(HttpServletRequest request) {
 | 
			
		||||
		String expectedApiKey = Settings.getInstance().getApiKey();
 | 
			
		||||
		String passedApiKey = request.getHeader(API_KEY_HEADER);
 | 
			
		||||
 | 
			
		||||
		if ((expectedApiKey != null && !expectedApiKey.equals(passedApiKey)) ||
 | 
			
		||||
				(passedApiKey != null && !passedApiKey.equals(expectedApiKey)))
 | 
			
		||||
			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.UNAUTHORIZED);
 | 
			
		||||
 | 
			
		||||
		InetAddress remoteAddr;
 | 
			
		||||
		try {
 | 
			
		||||
			remoteAddr = InetAddress.getByName(request.getRemoteAddr());
 | 
			
		||||
@@ -19,4 +29,5 @@ public class Security {
 | 
			
		||||
		if (!remoteAddr.isLoopbackAddress())
 | 
			
		||||
			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.UNAUTHORIZED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.media.Content;
 | 
			
		||||
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.security.SecurityRequirement;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
@@ -473,6 +474,7 @@ public class AddressesResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.INVALID_DATA, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String computePublicize(String rawBytes58) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Content;
 | 
			
		||||
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.security.SecurityRequirement;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
@@ -133,6 +134,7 @@ public class AdminResource {
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public NodeStatus status() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -153,6 +155,7 @@ public class AdminResource {
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String shutdown() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -181,6 +184,7 @@ public class AdminResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public ActivitySummary summary() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -226,6 +230,7 @@ public class AdminResource {
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public Controller.StatsSnapshot getEngineStats() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -244,6 +249,7 @@ public class AdminResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public List<MintingAccountData> getMintingAccounts() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -290,6 +296,7 @@ public class AdminResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.REPOSITORY_ISSUE, ApiError.CANNOT_MINT})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String addMintingAccount(String seed58) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -342,6 +349,7 @@ public class AdminResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String deleteMintingAccount(String key58) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -441,6 +449,7 @@ public class AdminResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_HEIGHT, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String orphan(String targetHeightString) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -482,6 +491,7 @@ public class AdminResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_DATA, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String forceSync(String targetPeerAddress) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -527,6 +537,7 @@ public class AdminResource {
 | 
			
		||||
		description = "Requires enough free space to rebuild repository. This will pause your node for a while."
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public void performRepositoryMaintenance() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,17 @@
 | 
			
		||||
package org.qortal.api.resource;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
 | 
			
		||||
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
 | 
			
		||||
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
 | 
			
		||||
import io.swagger.v3.oas.annotations.extensions.Extension;
 | 
			
		||||
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
 | 
			
		||||
import io.swagger.v3.oas.annotations.info.Info;
 | 
			
		||||
import io.swagger.v3.oas.annotations.security.SecurityScheme;
 | 
			
		||||
import io.swagger.v3.oas.annotations.security.SecuritySchemes;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import org.qortal.api.Security;
 | 
			
		||||
 | 
			
		||||
@OpenAPIDefinition(
 | 
			
		||||
		info = @Info( title = "Qortal API", description = "NOTE: byte-arrays are encoded in Base58" ),
 | 
			
		||||
		tags = {
 | 
			
		||||
@@ -30,5 +36,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
)
 | 
			
		||||
@SecuritySchemes({
 | 
			
		||||
	@SecurityScheme(name = "basicAuth", type = SecuritySchemeType.HTTP, scheme = "basic"),
 | 
			
		||||
	@SecurityScheme(name = "apiKey", type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, paramName = Security.API_KEY_HEADER)
 | 
			
		||||
})
 | 
			
		||||
public class ApiDefinition {
 | 
			
		||||
}
 | 
			
		||||
@@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.media.Content;
 | 
			
		||||
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.security.SecurityRequirement;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@@ -156,6 +157,7 @@ public class ChatResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String buildChat(ChatTransactionData transactionData) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -203,6 +205,7 @@ public class ChatResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.INVALID_DATA, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String buildChat(String rawBytes58) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.media.Content;
 | 
			
		||||
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.security.SecurityRequirement;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
@@ -155,6 +156,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_DATA, ApiError.INVALID_REFERENCE, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String buildTrade(CrossChainBuildRequest tradeRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -250,6 +252,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String buildTradeMessage(CrossChainTradeRequest tradeRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -333,6 +336,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_DATA, ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String buildRedeemMessage(CrossChainSecretRequest secretRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -404,6 +408,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String buildCancelMessage(CrossChainCancelRequest cancelRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -459,6 +464,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String deriveP2shA(CrossChainBitcoinTemplateRequest templateRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -485,6 +491,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String deriveP2shB(CrossChainBitcoinTemplateRequest templateRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -542,6 +549,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public CrossChainBitcoinP2SHStatus checkP2shA(CrossChainBitcoinTemplateRequest templateRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -568,6 +576,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public CrossChainBitcoinP2SHStatus checkP2shB(CrossChainBitcoinTemplateRequest templateRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -656,6 +665,7 @@ public class CrossChainResource {
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN,
 | 
			
		||||
		ApiError.BTC_TOO_SOON, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String refundP2shA(CrossChainBitcoinRefundRequest refundRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -683,6 +693,7 @@ public class CrossChainResource {
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN,
 | 
			
		||||
		ApiError.BTC_TOO_SOON, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String refundP2shB(CrossChainBitcoinRefundRequest refundRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -793,6 +804,7 @@ public class CrossChainResource {
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN,
 | 
			
		||||
		ApiError.BTC_TOO_SOON, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String redeemP2shA(CrossChainBitcoinRedeemRequest redeemRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -821,6 +833,7 @@ public class CrossChainResource {
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN,
 | 
			
		||||
		ApiError.BTC_TOO_SOON, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String redeemP2shB(CrossChainBitcoinRedeemRequest redeemRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -935,6 +948,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PRIVATE_KEY})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String getBitcoinWalletBalance(String xprv58) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -969,6 +983,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String sendBitcoin(BitcoinSendRequest bitcoinSendRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -1019,6 +1034,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public List<TradeBotData> getTradeBotStates() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -1049,6 +1065,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String tradeBotCreator(TradeBotCreateRequest tradeBotCreateRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -1104,6 +1121,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String tradeBotResponder(TradeBotRespondRequest tradeBotRespondRequest) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -1168,6 +1186,7 @@ public class CrossChainResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String tradeBotDelete(String tradePrivateKey58) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Content;
 | 
			
		||||
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.security.SecurityRequirement;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import java.net.InetSocketAddress;
 | 
			
		||||
@@ -131,6 +132,7 @@ public class PeersResource {
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public ExecuteProduceConsume.StatsSnapshot getEngineStats() {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -168,6 +170,7 @@ public class PeersResource {
 | 
			
		||||
	@ApiErrors({
 | 
			
		||||
		ApiError.INVALID_NETWORK_ADDRESS, ApiError.REPOSITORY_ISSUE
 | 
			
		||||
	})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String addPeer(String address) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -222,6 +225,7 @@ public class PeersResource {
 | 
			
		||||
	@ApiErrors({
 | 
			
		||||
		ApiError.INVALID_NETWORK_ADDRESS, ApiError.REPOSITORY_ISSUE
 | 
			
		||||
	})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String removePeer(String address) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -257,6 +261,7 @@ public class PeersResource {
 | 
			
		||||
	@ApiErrors({
 | 
			
		||||
		ApiError.REPOSITORY_ISSUE
 | 
			
		||||
	})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public String removeKnownPeers(String address) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
@@ -296,6 +301,7 @@ public class PeersResource {
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
	@ApiErrors({ApiError.INVALID_DATA, ApiError.REPOSITORY_ISSUE})
 | 
			
		||||
	@SecurityRequirement(name = "apiKey")
 | 
			
		||||
	public List<BlockSummaryData> commonBlock(String targetPeerAddress) {
 | 
			
		||||
		Security.checkApiCallAllowed(request);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@ public class Settings {
 | 
			
		||||
		"::1", "127.0.0.1"
 | 
			
		||||
	};
 | 
			
		||||
	private Boolean apiRestricted;
 | 
			
		||||
	private String apiKey = null;
 | 
			
		||||
	private boolean apiLoggingEnabled = false;
 | 
			
		||||
	private boolean apiDocumentationEnabled = false;
 | 
			
		||||
	// Both of these need to be set for API to use SSL
 | 
			
		||||
@@ -275,6 +276,9 @@ public class Settings {
 | 
			
		||||
		// Validation goes here
 | 
			
		||||
		if (this.minBlockchainPeers < 1)
 | 
			
		||||
			throwValidationError("minBlockchainPeers must be at least 1");
 | 
			
		||||
 | 
			
		||||
		if (this.apiKey != null && this.apiKey.trim().length() < 8)
 | 
			
		||||
			throwValidationError("apiKey must be at least 8 characters");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Getters / setters
 | 
			
		||||
@@ -323,6 +327,10 @@ public class Settings {
 | 
			
		||||
		return !BlockChain.getInstance().isTestChain();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public String getApiKey() {
 | 
			
		||||
		return this.apiKey;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isApiLoggingEnabled() {
 | 
			
		||||
		return this.apiLoggingEnabled;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user