├── LICENSE ├── README.md ├── TESTING.md ├── build.gradle ├── settings.gradle └── src ├── main └── java │ └── net │ └── tcpshield │ └── tcpshieldapi │ ├── APIClient.java │ ├── BackendSet.java │ ├── Domain.java │ ├── MitigationSettings.java │ ├── Network.java │ ├── deserializer │ └── DateDeserializer.java │ ├── exception │ ├── APIConnectionException.java │ ├── APIException.java │ └── status │ │ ├── NoPermissionException.java │ │ ├── NotFoundException.java │ │ └── ResponseException.java │ ├── impl │ ├── APIClientImpl.java │ ├── BackendSetImpl.java │ ├── DomainImpl.java │ ├── MitigationSettingsImpl.java │ └── NetworkImpl.java │ ├── request │ ├── BackendSetPatchRequest.java │ ├── BackendSetPostRequest.java │ ├── DomainPatchRequest.java │ ├── DomainPostRequest.java │ ├── DomainPreverifyRequest.java │ ├── NetworkPatchRequest.java │ └── NetworkPostRequest.java │ ├── response │ ├── BackendSetPostResponse.java │ ├── BackendSetResponse.java │ ├── BackendSetsResponse.java │ ├── DomainPostResponse.java │ ├── DomainPreverifyResponse.java │ ├── DomainResponse.java │ ├── DomainVerifyResponse.java │ ├── DomainsResponse.java │ ├── NetworkPostRepsonse.java │ ├── NetworkResponse.java │ └── NetworksResponse.java │ └── rest │ ├── APIConstants.java │ ├── RequestType.java │ ├── RestClient.java │ ├── RestRequest.java │ └── RestResponse.java └── test └── java └── de └── tcpshield └── tcpshieldapi ├── APIClientTest.java ├── CUDTest.java ├── FetchTest.java ├── TestConstants.java └── VerificationTest.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 TCPShield 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TCPShield API Wrapper 2 | 3 | ![Build badge](https://ci.fuzzlemann.de/job/TCPShield-Java-API-Wrapper/badge/icon) 4 | 5 | This is a Java wrapper for the official [TCPShield API](https://github.com/TCPShield/api-docs). \ 6 | This wrapper supports every documented API endpoint, as seen in the [API Documentation](https://swagger.tcpshield.com). 7 | 8 | ## Download 9 | 10 | ### Option 1: Standalone Jar 11 | 12 | Download the [latest build](https://ci.fuzzlemann.de/job/TCPShield-Java-API-Wrapper/lastBuild/) from our CI and the 13 | latest [Jackson Databind](https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/) and add them both 14 | to your buildpath. 15 | 16 | ### Option 2: Build automation tools 17 | 18 | Using build automation tools like [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/) streamlines the 19 | usage of our API. 20 | 21 | see https://jitpack.io/#TCPShield/TCPShield-Java-API-Wrapper/-SNAPSHOT 22 | 23 | ## Example 24 | 25 | Simple example of setting up a network from scratch: 26 | 27 | ```java 28 | public class NetworkSetup { 29 | 30 | private final APIClient apiClient = new APIClientImpl("APIKEY"); // create an instance of the API Client 31 | 32 | public void setup(String networkName, String backend, String domainName) { 33 | List networks = apiClient.getNetworks(); // fetches all networks 34 | 35 | int networkID; 36 | int domainID; 37 | 38 | Optional foundNetwork = networks.stream().filter(network -> network.getName().equals("TestNetwork")).findAny(); // checks if any networks with the name "TestNetwork" exist 39 | 40 | if (foundNetwork.isPresent()) { // network found 41 | Network network = foundNetwork.get(); 42 | networkID = network.getID(); 43 | 44 | Domain foundDomain = apiClient.getDomains(networkID).stream().filter(domain -> domain.getName().equals(domainName)).findAny().orElseThrow(IllegalStateException::new); // gets the ID of the domain 45 | domainID = foundDomain.getID(); 46 | } else { // no network found 47 | networkID = apiClient.addNetwork("TestNetwork").getData().getNetworkID(); // adds the network 48 | int backendSetID = apiClient.addBackendSet(networkID, networkName + " Set", backend).getData().getID(); // adds the backend set 49 | domainID = apiClient.addDomain(networkID, domainName, backendSetID, false).getData().getID(); // adds the domain 50 | } 51 | 52 | if (apiClient.verify(networkID, domainID)) { // verifies the domain; true if successful, false if not 53 | System.out.println("Successfully created the network."); 54 | } else { 55 | Network network = apiClient.getNetwork(networkID); // fetches the network in order to get the TXT verification string 56 | 57 | System.out.println("Create a TXT record on @ with \"" + network.getTXTVerification() + "\" and re-run the program."); 58 | } 59 | } 60 | } 61 | ``` 62 | 63 | ## Support 64 | 65 | If any help with the usage of the API is needed, feel free to contact us on our [Discord](https://discord.gg/XKU9UpV). 66 | 67 | ## Used Libraries 68 | 69 | * [Jackson Databind](https://github.com/FasterXML/jackson-databind) 70 | 71 | ## Contributions 72 | 73 | We're more than happy to accept contributions! We welcome pull requests with open arms.
74 | In order to get testing to work, follow the instructions outlined [here](TESTING.md). 75 | 76 | ## ToDo 77 | 78 | * adding a repository for build tools like Gradle and Maven 79 | * adding documentation 80 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Test Setup 2 | In order to get testing to work, there are some preconditions which have to be met: 3 | * TCPShield with the Premium plan or higher (in order to get a proper API Key & test setting custom mitigation settings) 4 | * a custom setup network with predefined variables 5 | * one additional free space for another network 6 | * a domain 7 | * variables in `gradle.properties` 8 | 9 | ## Network setup 10 | We need to create a custom network with specific variables as that network is used for the read testing. 11 | 12 | **Name**: `TestNetwork`
13 | **Domains:** `unverifiedtestdomain.com` and one custom domain with the verification TXT record already setup; 14 | both domains pointing to the backend set `TestSet`
15 | **Backend Sets:** `TestSet` with the backends `127.0.0.1:25565` and `127.0.0.1:25566`
16 | **Mitigation Settings:** CPS: `10 c/s`; Ban Seconds: `70`; Allow Seconds: `500`; Mitigation Message: `TestMitigationMessage` 17 | 18 | ## gradle.properties 19 | ``` 20 | testing.api-key=API_KEY # the TCPShield API Key 21 | testing.domain1=test.example.net # an own domain with the TXT verification record already setup 22 | testing.domain2=test2.example.net # another own domain; whether the TXT verification is setup or not is irrelevant 23 | ``` -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'net.tcpshield' 6 | version '1.0' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.0' 14 | 15 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' 16 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' 17 | } 18 | 19 | test { 20 | useJUnitPlatform() 21 | 22 | systemProperty "testing.api-key", project.getProperty("testing.api-key") 23 | systemProperty "testing.domain1", project.getProperty("testing.domain1") 24 | systemProperty "testing.domain2", project.getProperty("testing.domain2") 25 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'TCPShield-Java-API-Wrapper' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/APIClient.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi; 2 | 3 | import net.tcpshield.tcpshieldapi.request.*; 4 | import net.tcpshield.tcpshieldapi.response.BackendSetPostResponse; 5 | import net.tcpshield.tcpshieldapi.response.DomainPostResponse; 6 | import net.tcpshield.tcpshieldapi.response.NetworkPostRepsonse; 7 | 8 | import java.util.List; 9 | 10 | public interface APIClient { 11 | 12 | List getNetworks(); 13 | 14 | NetworkPostRepsonse addNetwork(NetworkPostRequest request); 15 | 16 | default NetworkPostRepsonse addNetwork(String name) { 17 | return addNetwork(new NetworkPostRequest(name)); 18 | } 19 | 20 | Network getNetwork(int networkID); 21 | 22 | /** 23 | * Sets the network to the specified settings. 24 | * 25 | * @param networkID the network id 26 | * @param request the request which is to be executed 27 | * @throws net.tcpshield.tcpshieldapi.exception.status.NoPermissionException if your plan doesn't have the capability to patch the network settings 28 | * @throws net.tcpshield.tcpshieldapi.exception.status.NotFoundException if the network can't be found 29 | * @see NetworkPatchRequest 30 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, String, int, int, int, String) 31 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(Network, MitigationSettings) 32 | */ 33 | void patchNetwork(int networkID, NetworkPatchRequest request); 34 | 35 | /** 36 | * Sets the network to the specified settings. 37 | * 38 | * @param networkID the network id 39 | * @param name the name of the network; max. length: 50 characters 40 | * @param connectionsPerSecondThreshold how many total connections your server should receive before TCPShield starts mitigating; 1 <= x <= 100 41 | * @param clientBanSeconds total amount of time blocked attempts should be banned for; 60 <= x <= 3600 42 | * @param clientAllowSeconds total amount of time valid connections should be accepted; 30 <= x <= 600 43 | * @param mitigationMessage the message to be displayed after successful validation; max. length: 489 characters 44 | * @throws IllegalArgumentException if the conditions for the parameters aren't met 45 | * @throws net.tcpshield.tcpshieldapi.exception.status.NoPermissionException if your plan doesn't have the capability to patch the network settings 46 | * @throws net.tcpshield.tcpshieldapi.exception.status.NotFoundException if the network can't be found 47 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, NetworkPatchRequest) 48 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, String, int, int, int, String) 49 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(Network, MitigationSettings) 50 | */ 51 | default void patchNetwork(int networkID, String name, int connectionsPerSecondThreshold, int clientBanSeconds, int clientAllowSeconds, String mitigationMessage) { 52 | patchNetwork(networkID, new NetworkPatchRequest(networkID, name, connectionsPerSecondThreshold, clientBanSeconds, clientAllowSeconds, mitigationMessage)); 53 | } 54 | 55 | /** 56 | * Sets the mitigation settings of the network to the specified mitigation settings 57 | * 58 | * @param network the network to be patched 59 | * @param mitigationSettings the new mitigation settings 60 | * @throws IllegalArgumentException if the conditions for the parameters aren't met 61 | * @throws net.tcpshield.tcpshieldapi.exception.status.NoPermissionException if your plan doesn't have the capability to patch the network settings 62 | * @throws net.tcpshield.tcpshieldapi.exception.status.NotFoundException if the network can't be found 63 | * @see MitigationSettings 64 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, NetworkPatchRequest) 65 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, String, int, int, int, String) 66 | */ 67 | default void patchNetwork(Network network, MitigationSettings mitigationSettings) { 68 | patchNetwork(network.getID(), network.getName(), mitigationSettings.getConnectionsPerSecondThreshold(), mitigationSettings.getClientBanSeconds(), mitigationSettings.getClientAllowSeconds(), mitigationSettings.getMitigationMessage()); 69 | } 70 | 71 | void deleteNetwork(int networkID); 72 | 73 | List getDomains(int networkID); 74 | 75 | DomainPostResponse addDomain(int networkID, DomainPostRequest request); 76 | 77 | default DomainPostResponse addDomain(int networkID, String name, int setID, boolean bac) { 78 | return addDomain(networkID, new DomainPostRequest(name, setID, bac)); 79 | } 80 | 81 | Domain getDomain(int networkID, int domainID); 82 | 83 | void patchDomain(int networkID, int domainID, DomainPatchRequest request); 84 | 85 | default void patchDomain(int networkID, int domainID, String newName, int newBackendID, boolean newBAC) { 86 | patchDomain(networkID, domainID, new DomainPatchRequest(newName, newBackendID, newBAC)); 87 | } 88 | 89 | void deleteDomain(int networkID, int domainID); 90 | 91 | boolean preverify(int networkID, DomainPreverifyRequest request); 92 | 93 | default boolean preverify(int networkID, String domain) { 94 | return preverify(networkID, new DomainPreverifyRequest(domain)); 95 | } 96 | 97 | boolean verify(int networkID, int domainID); 98 | 99 | List getBackendSets(int networkID); 100 | 101 | BackendSetPostResponse addBackendSet(int networkID, BackendSetPostRequest request); 102 | 103 | default BackendSetPostResponse addBackendSet(int networkID, String name, String... backends) { 104 | return addBackendSet(networkID, new BackendSetPostRequest(name, backends)); 105 | } 106 | 107 | BackendSet getBackendSet(int networkID, int setID); 108 | 109 | void patchBackendSet(int networkID, int setID, BackendSetPatchRequest request); 110 | 111 | default void patchBackendSet(int networkID, int setID, String name, String... backends) { 112 | patchBackendSet(networkID, setID, new BackendSetPatchRequest(name, backends)); 113 | } 114 | 115 | void deleteBackendSet(int networkID, int setID); 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/BackendSet.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi; 2 | 3 | import java.util.List; 4 | 5 | public interface BackendSet { 6 | 7 | int getID(); 8 | 9 | String getName(); 10 | 11 | List getBackends(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/Domain.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi; 2 | 3 | import java.util.Date; 4 | 5 | public interface Domain { 6 | 7 | int getID(); 8 | 9 | String getName(); 10 | 11 | int getBackendSetID(); 12 | 13 | boolean isBACEnabled(); 14 | 15 | boolean isVerified(); 16 | 17 | Date getUpdatedAt(); 18 | 19 | Date getCreatedAt(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/MitigationSettings.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi; 2 | 3 | /** 4 | * Represents the mitigation settings of a network. 5 | */ 6 | public interface MitigationSettings { 7 | 8 | /** 9 | * @return how many total connections your server should receive before TCPShield starts mitigating 10 | */ 11 | int getConnectionsPerSecondThreshold(); 12 | 13 | /** 14 | * Sets how many total connections your server should receive before TCPShield starts mitigating. 15 | * @param threshold how many total connections your server should receive before TCPShield starts mitigating; 1 <= x <= 100 16 | * @throws IllegalArgumentException if the {@code threshold} is not between 1 and 100 17 | */ 18 | void setConnectionsPerSecondThreshold(int threshold); 19 | 20 | /** 21 | * @return the total amount of time blocked attempts should be banned for 22 | */ 23 | int getClientBanSeconds(); 24 | 25 | /** 26 | * Sets the total amount of time blocked attempts should be banned for. 27 | * @param seconds the total amount of time blocked attempts should be banned for; 60 <= x <= 3600 28 | * @throws IllegalArgumentException if {@code seconds} is not between 60 and 3600 29 | */ 30 | void setClientBanSeconds(int seconds); 31 | 32 | /** 33 | * @return the total amount of time valid connections should be accepted 34 | */ 35 | int getClientAllowSeconds(); 36 | 37 | /** 38 | * Sets the total amount of time valid connections should be accepted. 39 | * 40 | * @param seconds the total amount of time valid connections should be accepted; 30 <= x <= 600 41 | * @throws IllegalArgumentException if {@code seconds} is not between 30 and 600 42 | */ 43 | void setClientAllowSeconds(int seconds); 44 | 45 | /** 46 | * @return the message to be displayed after successful validation 47 | */ 48 | String getMitigationMessage(); 49 | 50 | /** 51 | * Sets the message to be displayed after successful validation. 52 | * 53 | * @param message the message to be displayed after successful validation; max. length: 489 characters 54 | * @implNote this is the raw mitigation message. Before sending the request to the server, it has to be wrapped in {@code {"text":"..."}} 55 | */ 56 | void setMitigationMessage(String message); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/Network.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | public interface Network { 7 | 8 | int getID(); 9 | 10 | String getName(); 11 | 12 | boolean isPremium(); 13 | 14 | String getProtectedCNAME(); 15 | 16 | String getTXTVerification(); 17 | 18 | MitigationSettings getMitigationSettings(); 19 | 20 | Date getUpdatedAt(); 21 | 22 | Date getCreatedAt(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/deserializer/DateDeserializer.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.deserializer; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.databind.DeserializationContext; 5 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 6 | 7 | import java.io.IOException; 8 | import java.text.ParseException; 9 | import java.text.SimpleDateFormat; 10 | import java.util.Date; 11 | 12 | public class DateDeserializer extends StdDeserializer { 13 | 14 | private final SimpleDateFormat formatOne = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'"); 15 | 16 | public DateDeserializer() { 17 | this(null); 18 | } 19 | 20 | public DateDeserializer(Class vc) { 21 | super(vc); 22 | } 23 | 24 | @Override 25 | public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 26 | String text = p.getText(); 27 | int pointIndex = text.indexOf('.'); 28 | 29 | String cleanedText; 30 | if (pointIndex != -1) { 31 | cleanedText = text.substring(0, pointIndex) + "Z"; 32 | } else { 33 | cleanedText = text; 34 | } 35 | 36 | try { 37 | return formatOne.parse(cleanedText); 38 | } catch (ParseException e) { 39 | throw new RuntimeException(e); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/exception/APIConnectionException.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.exception; 2 | 3 | public class APIConnectionException extends APIException { 4 | 5 | public APIConnectionException(Throwable cause) { 6 | super(cause); 7 | } 8 | 9 | public APIConnectionException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/exception/APIException.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.exception; 2 | 3 | public class APIException extends RuntimeException { 4 | 5 | public APIException() { 6 | } 7 | 8 | public APIException(String message) { 9 | super(message); 10 | } 11 | 12 | public APIException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public APIException(Throwable cause) { 17 | super(cause); 18 | } 19 | 20 | public APIException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 21 | super(message, cause, enableSuppression, writableStackTrace); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/exception/status/NoPermissionException.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.exception.status; 2 | 3 | public class NoPermissionException extends ResponseException { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/exception/status/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.exception.status; 2 | 3 | public class NotFoundException extends ResponseException { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/exception/status/ResponseException.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.exception.status; 2 | 3 | import net.tcpshield.tcpshieldapi.exception.APIException; 4 | 5 | public class ResponseException extends APIException { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/impl/APIClientImpl.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.impl; 2 | 3 | import net.tcpshield.tcpshieldapi.APIClient; 4 | import net.tcpshield.tcpshieldapi.BackendSet; 5 | import net.tcpshield.tcpshieldapi.Domain; 6 | import net.tcpshield.tcpshieldapi.Network; 7 | import net.tcpshield.tcpshieldapi.exception.status.NoPermissionException; 8 | import net.tcpshield.tcpshieldapi.request.*; 9 | import net.tcpshield.tcpshieldapi.response.*; 10 | import net.tcpshield.tcpshieldapi.rest.APIConstants; 11 | import net.tcpshield.tcpshieldapi.rest.RequestType; 12 | import net.tcpshield.tcpshieldapi.rest.RestClient; 13 | import net.tcpshield.tcpshieldapi.rest.RestRequest; 14 | 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.Modifier; 17 | import java.net.HttpURLConnection; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | public class APIClientImpl implements APIClient { 22 | 23 | private final RestClient client; 24 | 25 | public APIClientImpl(String apiKey) { 26 | if (apiKey == null) throw new IllegalArgumentException("apiKey is null"); 27 | 28 | setupOverride(); 29 | this.client = new RestClient(apiKey); 30 | } 31 | 32 | @Override 33 | public List getNetworks() { 34 | NetworksResponse response = RestRequest.builder(NetworksResponse.class) 35 | .url(APIConstants.NETWORKS_ENDPOINT) 36 | .requestType(RequestType.GET) 37 | .build() 38 | .execute(client); 39 | 40 | List networks = new ArrayList<>(); 41 | for (NetworkResponse networkResponse : response) { 42 | Network network = new NetworkImpl(networkResponse); 43 | networks.add(network); 44 | } 45 | 46 | return networks; 47 | } 48 | 49 | @Override 50 | public NetworkPostRepsonse addNetwork(NetworkPostRequest request) { 51 | return RestRequest.builder(NetworkPostRepsonse.class) 52 | .url(APIConstants.NETWORKS_ENDPOINT) 53 | .requestType(RequestType.POST) 54 | .data(request) 55 | .build() 56 | .execute(client); 57 | } 58 | 59 | @Override 60 | public Network getNetwork(int id) { 61 | NetworkResponse response = RestRequest.builder(NetworkResponse.class) 62 | .url(APIConstants.NETWORK_SPECIFIC_ENDPOINT) 63 | .pathVariable("networkId", String.valueOf(id)) 64 | .requestType(RequestType.GET) 65 | .build() 66 | .execute(client); 67 | 68 | return new NetworkImpl(response); 69 | } 70 | 71 | @Override 72 | public void patchNetwork(int id, NetworkPatchRequest request) { 73 | RestRequest.builder() 74 | .url(APIConstants.NETWORK_SPECIFIC_ENDPOINT) 75 | .pathVariable("networkId", String.valueOf(id)) 76 | .requestType(RequestType.PATCH) 77 | .data(request) 78 | .build() 79 | .execute(client); 80 | } 81 | 82 | @Override 83 | public void deleteNetwork(int id) { 84 | RestRequest.builder() 85 | .url(APIConstants.NETWORK_SPECIFIC_ENDPOINT) 86 | .pathVariable("networkId", String.valueOf(id)) 87 | .requestType(RequestType.DELETE) 88 | .build() 89 | .execute(client); 90 | } 91 | 92 | @Override 93 | public List getDomains(int networkID) { 94 | DomainsResponse response = RestRequest.builder(DomainsResponse.class) 95 | .url(APIConstants.DOMAINS_ENDPOINT) 96 | .pathVariable("networkId", String.valueOf(networkID)) 97 | .requestType(RequestType.GET) 98 | .build() 99 | .execute(client); 100 | 101 | List domains = new ArrayList<>(); 102 | for (DomainResponse domainResponse : response) { 103 | Domain domain = new DomainImpl(domainResponse); 104 | domains.add(domain); 105 | } 106 | 107 | return domains; 108 | } 109 | 110 | @Override 111 | public DomainPostResponse addDomain(int networkID, DomainPostRequest request) { 112 | return RestRequest.builder(DomainPostResponse.class) 113 | .url(APIConstants.DOMAINS_ENDPOINT) 114 | .pathVariable("networkId", String.valueOf(networkID)) 115 | .requestType(RequestType.POST) 116 | .data(request) 117 | .build() 118 | .execute(client); 119 | } 120 | 121 | @Override 122 | public Domain getDomain(int networkID, int domainID) { 123 | DomainResponse response = RestRequest.builder(DomainResponse.class) 124 | .url(APIConstants.DOMAIN_SPECIFIC_ENDPOINT) 125 | .pathVariable("networkId", String.valueOf(networkID)) 126 | .pathVariable("domainId", String.valueOf(domainID)) 127 | .requestType(RequestType.GET) 128 | .build() 129 | .execute(client); 130 | 131 | return new DomainImpl(response); 132 | } 133 | 134 | @Override 135 | public void patchDomain(int networkID, int domainID, DomainPatchRequest request) { 136 | RestRequest.builder() 137 | .url(APIConstants.DOMAIN_SPECIFIC_ENDPOINT) 138 | .pathVariable("networkId", String.valueOf(networkID)) 139 | .pathVariable("domainId", String.valueOf(domainID)) 140 | .requestType(RequestType.PATCH) 141 | .data(request) 142 | .build() 143 | .execute(client); 144 | } 145 | 146 | @Override 147 | public void deleteDomain(int networkID, int domainID) { 148 | RestRequest.builder() 149 | .url(APIConstants.DOMAIN_SPECIFIC_ENDPOINT) 150 | .pathVariable("networkId", String.valueOf(networkID)) 151 | .pathVariable("domainId", String.valueOf(domainID)) 152 | .requestType(RequestType.DELETE) 153 | .build() 154 | .execute(client); 155 | } 156 | 157 | @Override 158 | public boolean preverify(int networkID, DomainPreverifyRequest request) { 159 | try { 160 | return RestRequest.builder(DomainPreverifyResponse.class) 161 | .url(APIConstants.DOMAINS_PREVERIFY_ENDPOINT) 162 | .pathVariable("networkId", String.valueOf(networkID)) 163 | .requestType(RequestType.POST) 164 | .data(request) 165 | .build() 166 | .execute(client) 167 | .getStatus() == 0; 168 | } catch (NoPermissionException e) { 169 | return false; 170 | } 171 | } 172 | 173 | @Override 174 | public boolean verify(int networkID, int domainID) { 175 | try { 176 | return RestRequest.builder(DomainVerifyResponse.class) 177 | .url(APIConstants.DOMAIN_VERIFY_ENDPOINT) 178 | .pathVariable("networkId", String.valueOf(networkID)) 179 | .pathVariable("domainId", String.valueOf(domainID)) 180 | .requestType(RequestType.GET) 181 | .build() 182 | .execute(client) 183 | .getStatus() == 0; 184 | } catch (NoPermissionException e) { 185 | return false; 186 | } 187 | } 188 | 189 | @Override 190 | public List getBackendSets(int networkID) { 191 | BackendSetsResponse response = RestRequest.builder(BackendSetsResponse.class) 192 | .url(APIConstants.BACKENDS_ENDPOINT) 193 | .pathVariable("networkId", String.valueOf(networkID)) 194 | .requestType(RequestType.GET) 195 | .build() 196 | .execute(client); 197 | 198 | List backendSets = new ArrayList<>(); 199 | for (BackendSetResponse backendSetResponse : response) { 200 | BackendSet backendSet = new BackendSetImpl(backendSetResponse); 201 | backendSets.add(backendSet); 202 | } 203 | 204 | return backendSets; 205 | } 206 | 207 | @Override 208 | public BackendSetPostResponse addBackendSet(int networkID, BackendSetPostRequest request) { 209 | return RestRequest.builder(BackendSetPostResponse.class) 210 | .url(APIConstants.BACKENDS_ENDPOINT) 211 | .pathVariable("networkId", String.valueOf(networkID)) 212 | .requestType(RequestType.POST) 213 | .data(request) 214 | .build() 215 | .execute(client); 216 | } 217 | 218 | @Override 219 | public BackendSet getBackendSet(int networkID, int setID) { 220 | BackendSetResponse response = RestRequest.builder(BackendSetResponse.class) 221 | .url(APIConstants.BACKENDS_SPECIFIC_ENDPOINT) 222 | .pathVariable("networkId", String.valueOf(networkID)) 223 | .pathVariable("setId", String.valueOf(setID)) 224 | .requestType(RequestType.GET) 225 | .build() 226 | .execute(client); 227 | 228 | return response.getID() == 0 ? new BackendSetImpl(setID, response) : new BackendSetImpl(response); 229 | } 230 | 231 | @Override 232 | public void patchBackendSet(int networkID, int setID, BackendSetPatchRequest request) { 233 | RestRequest.builder(BackendSetResponse.class) 234 | .url(APIConstants.BACKENDS_SPECIFIC_ENDPOINT) 235 | .pathVariable("networkId", String.valueOf(networkID)) 236 | .pathVariable("setId", String.valueOf(setID)) 237 | .requestType(RequestType.PATCH) 238 | .data(request) 239 | .build() 240 | .execute(client); 241 | } 242 | 243 | @Override 244 | public void deleteBackendSet(int networkID, int id) { 245 | RestRequest.builder(BackendSetResponse.class) 246 | .url(APIConstants.BACKENDS_SPECIFIC_ENDPOINT) 247 | .pathVariable("networkId", String.valueOf(networkID)) 248 | .pathVariable("setId", String.valueOf(id)) 249 | .requestType(RequestType.DELETE) 250 | .build() 251 | .execute(client); 252 | } 253 | 254 | /** 255 | * Sets up overrides because the standard Java library does not allow {@code PATCH} requests 256 | */ 257 | private void setupOverride() { 258 | try { 259 | Field methodsField = HttpURLConnection.class.getDeclaredField("methods"); 260 | 261 | Field modifiersField = Field.class.getDeclaredField("modifiers"); 262 | modifiersField.setAccessible(true); 263 | modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL); 264 | 265 | methodsField.setAccessible(true); 266 | 267 | 268 | String[] oldMethods = (String[]) methodsField.get(null); 269 | String[] newMethods = new String[oldMethods.length + 1]; 270 | 271 | System.arraycopy(oldMethods, 0, newMethods, 0, oldMethods.length); 272 | newMethods[oldMethods.length] = "PATCH"; 273 | 274 | methodsField.set(null, newMethods); 275 | } catch (NoSuchFieldException | IllegalAccessException e) { 276 | throw new IllegalStateException(e); 277 | } 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/impl/BackendSetImpl.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.impl; 2 | 3 | import net.tcpshield.tcpshieldapi.BackendSet; 4 | import net.tcpshield.tcpshieldapi.Network; 5 | import net.tcpshield.tcpshieldapi.response.BackendSetResponse; 6 | 7 | import java.util.*; 8 | 9 | class BackendSetImpl implements BackendSet { 10 | 11 | private final int id; 12 | private final String name; 13 | private final List backends; 14 | 15 | BackendSetImpl(int id, String name, List backends) { 16 | this.id = id; 17 | this.name = name; 18 | this.backends = backends; 19 | } 20 | 21 | BackendSetImpl(BackendSetResponse response) { 22 | this(response.getID(), response); 23 | } 24 | 25 | BackendSetImpl(int id, BackendSetResponse response) { 26 | this.id = id; 27 | this.name = response.getName(); 28 | this.backends = new ArrayList<>(response.getBackends() == null ? Collections.emptyList() : Arrays.asList(response.getBackends())); 29 | } 30 | 31 | @Override 32 | public int getID() { 33 | return id; 34 | } 35 | 36 | @Override 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | @Override 42 | public List getBackends() { 43 | return backends; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o == null || getClass() != o.getClass()) return false; 50 | BackendSetImpl that = (BackendSetImpl) o; 51 | return id == that.id && Objects.equals(name, that.name) && Objects.equals(backends, that.backends); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return Objects.hash(id, name, backends); 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "BackendSetImpl{" + 62 | "id=" + id + 63 | ", name='" + name + '\'' + 64 | ", backends=" + backends + 65 | '}'; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/impl/DomainImpl.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.impl; 2 | 3 | import net.tcpshield.tcpshieldapi.Domain; 4 | import net.tcpshield.tcpshieldapi.Network; 5 | import net.tcpshield.tcpshieldapi.response.DomainResponse; 6 | 7 | import java.util.Date; 8 | import java.util.Objects; 9 | 10 | class DomainImpl implements Domain { 11 | 12 | private final int id; 13 | private final String name; 14 | private final int backendSetID; 15 | private final boolean bac; 16 | private final boolean verified; 17 | private final Date updatedAt; 18 | private final Date createdAt; 19 | 20 | DomainImpl(int id, String name, int backendSetID, boolean bac, boolean verified, Date updatedAt, Date createdAt) { 21 | this.id = id; 22 | this.name = name; 23 | this.backendSetID = backendSetID; 24 | this.bac = bac; 25 | this.verified = verified; 26 | this.updatedAt = updatedAt; 27 | this.createdAt = createdAt; 28 | } 29 | 30 | DomainImpl(DomainResponse response) { 31 | this.id = response.getID(); 32 | this.name = response.getName(); 33 | this.backendSetID = response.getBackendSetID(); 34 | this.bac = response.isBACEnabled(); 35 | this.verified = response.isVerified(); 36 | this.updatedAt = response.getUpdatedAt(); 37 | this.createdAt = response.getCreatedAt(); 38 | } 39 | 40 | @Override 41 | public int getID() { 42 | return id; 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | @Override 51 | public int getBackendSetID() { 52 | return backendSetID; 53 | } 54 | 55 | @Override 56 | public boolean isBACEnabled() { 57 | return bac; 58 | } 59 | 60 | @Override 61 | public boolean isVerified() { 62 | return verified; 63 | } 64 | 65 | @Override 66 | public Date getUpdatedAt() { 67 | return updatedAt; 68 | } 69 | 70 | @Override 71 | public Date getCreatedAt() { 72 | return createdAt; 73 | } 74 | 75 | @Override 76 | public boolean equals(Object o) { 77 | if (this == o) return true; 78 | if (o == null || getClass() != o.getClass()) return false; 79 | DomainImpl domain = (DomainImpl) o; 80 | return id == domain.id && backendSetID == domain.backendSetID && bac == domain.bac && verified == domain.verified && Objects.equals(name, domain.name) && Objects.equals(updatedAt, domain.updatedAt) && Objects.equals(createdAt, domain.createdAt); 81 | } 82 | 83 | @Override 84 | public int hashCode() { 85 | return Objects.hash(id, name, backendSetID, bac, verified, updatedAt, createdAt); 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return "DomainImpl{" + 91 | "id=" + id + 92 | ", name='" + name + '\'' + 93 | ", backendSetID=" + backendSetID + 94 | ", bac=" + bac + 95 | ", verified=" + verified + 96 | ", updatedAt=" + updatedAt + 97 | ", createdAt=" + createdAt + 98 | '}'; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/impl/MitigationSettingsImpl.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.impl; 2 | 3 | import net.tcpshield.tcpshieldapi.MitigationSettings; 4 | 5 | import java.util.Objects; 6 | 7 | class MitigationSettingsImpl implements MitigationSettings { 8 | 9 | private int connectionsPerSecondThreshold; 10 | private int clientBanSeconds; 11 | private int clientAllowSeconds; 12 | private String mitigationMessage; 13 | 14 | MitigationSettingsImpl(int connectionsPerSecondThreshold, int clientBanSeconds, int clientAllowSeconds, String mitigationMessage) { 15 | this.connectionsPerSecondThreshold = connectionsPerSecondThreshold; 16 | this.clientBanSeconds = clientBanSeconds; 17 | this.clientAllowSeconds = clientAllowSeconds; 18 | this.mitigationMessage = mitigationMessage; 19 | } 20 | 21 | @Override 22 | public int getConnectionsPerSecondThreshold() { 23 | return connectionsPerSecondThreshold; 24 | } 25 | 26 | @Override 27 | public void setConnectionsPerSecondThreshold(int connectionsPerSecondThreshold) { 28 | if (1 > connectionsPerSecondThreshold || connectionsPerSecondThreshold > 100) 29 | throw new IllegalArgumentException("connectionsPerSecondThreshold not between 1 and 100. Provided value: \"" + connectionsPerSecondThreshold + "\""); 30 | 31 | this.connectionsPerSecondThreshold = connectionsPerSecondThreshold; 32 | } 33 | 34 | @Override 35 | public int getClientBanSeconds() { 36 | return clientBanSeconds; 37 | } 38 | 39 | @Override 40 | public void setClientBanSeconds(int clientBanSeconds) { 41 | if (60 > clientBanSeconds || clientBanSeconds > 3600) 42 | throw new IllegalArgumentException("clientBanSeconds not between 30 and 3600. Provided value: \"" + clientBanSeconds + "\""); 43 | 44 | this.clientBanSeconds = clientBanSeconds; 45 | } 46 | 47 | @Override 48 | public int getClientAllowSeconds() { 49 | return clientAllowSeconds; 50 | } 51 | 52 | @Override 53 | public void setClientAllowSeconds(int clientAllowSeconds) { 54 | if (30 > clientAllowSeconds || clientAllowSeconds > 600) 55 | throw new IllegalArgumentException("clientAllowSeconds not between 30 and 600. Provided value: \"" + clientAllowSeconds + "\""); 56 | 57 | this.clientAllowSeconds = clientAllowSeconds; 58 | } 59 | 60 | @Override 61 | public String getMitigationMessage() { 62 | return mitigationMessage; 63 | } 64 | 65 | @Override 66 | public void setMitigationMessage(String mitigationMessage) { 67 | if (mitigationMessage.length() > 500 - "{\"text\":\"\"}".length()) // 11 less characters 68 | throw new IllegalArgumentException("mitigationMessage cannot be longer than 489 characters. Provided value: \"" + mitigationMessage + "\" (" + " characters)"); 69 | 70 | this.mitigationMessage = mitigationMessage; 71 | } 72 | 73 | @Override 74 | public boolean equals(Object o) { 75 | if (this == o) return true; 76 | if (o == null || getClass() != o.getClass()) return false; 77 | MitigationSettingsImpl that = (MitigationSettingsImpl) o; 78 | return connectionsPerSecondThreshold == that.connectionsPerSecondThreshold && clientBanSeconds == that.clientBanSeconds && clientAllowSeconds == that.clientAllowSeconds && mitigationMessage.equals(that.mitigationMessage); 79 | } 80 | 81 | @Override 82 | public int hashCode() { 83 | return Objects.hash(connectionsPerSecondThreshold, clientBanSeconds, clientAllowSeconds, mitigationMessage); 84 | } 85 | 86 | @Override 87 | public String toString() { 88 | return "MitigationSettingsImpl{" + 89 | "connectionsPerSecondThreshold=" + connectionsPerSecondThreshold + 90 | ", clientBanSeconds=" + clientBanSeconds + 91 | ", clientAllowSeconds=" + clientAllowSeconds + 92 | ", mitigationMessage='" + mitigationMessage + '\'' + 93 | '}'; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/impl/NetworkImpl.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.impl; 2 | 3 | import net.tcpshield.tcpshieldapi.MitigationSettings; 4 | import net.tcpshield.tcpshieldapi.Network; 5 | import net.tcpshield.tcpshieldapi.response.NetworkResponse; 6 | 7 | import java.util.Date; 8 | import java.util.Objects; 9 | 10 | class NetworkImpl implements Network { 11 | 12 | private final int id; 13 | private final String name; 14 | private final boolean premium; 15 | private final String protectedCNAME; 16 | private final String txtVerification; 17 | private final MitigationSettings mitigationSettings; 18 | private final Date updatedAt; 19 | private final Date createdAt; 20 | 21 | NetworkImpl(int id, String name, boolean premium, String protectedCNAME, String txtVerification, MitigationSettings mitigationSettings, Date updatedAt, Date createdAt) { 22 | this.id = id; 23 | this.name = name; 24 | this.premium = premium; 25 | this.protectedCNAME = protectedCNAME; 26 | this.txtVerification = txtVerification; 27 | this.mitigationSettings = mitigationSettings; 28 | this.updatedAt = updatedAt; 29 | this.createdAt = createdAt; 30 | } 31 | 32 | NetworkImpl(NetworkResponse response) { 33 | this.id = response.getID(); 34 | this.name = response.getName(); 35 | this.premium = response.isPremium(); 36 | this.protectedCNAME = response.getProtectedCNAME(); 37 | this.txtVerification = response.getTXTVerification(); 38 | this.mitigationSettings = new MitigationSettingsImpl(response.getConnectionsPerSecondThreshold(), response.getClientBanSeconds(), response.getClientAllowSeconds(), response.getMitigationMessage()); 39 | this.updatedAt = response.getUpdatedAt(); 40 | this.createdAt = response.getCreatedAt(); 41 | } 42 | 43 | @Override 44 | public int getID() { 45 | return id; 46 | } 47 | 48 | @Override 49 | public String getName() { 50 | return name; 51 | } 52 | 53 | @Override 54 | public boolean isPremium() { 55 | return premium; 56 | } 57 | 58 | @Override 59 | public String getProtectedCNAME() { 60 | return protectedCNAME; 61 | } 62 | 63 | @Override 64 | public String getTXTVerification() { 65 | return txtVerification; 66 | } 67 | 68 | @Override 69 | public MitigationSettings getMitigationSettings() { 70 | return mitigationSettings; 71 | } 72 | 73 | @Override 74 | public Date getUpdatedAt() { 75 | return updatedAt; 76 | } 77 | 78 | @Override 79 | public Date getCreatedAt() { 80 | return createdAt; 81 | } 82 | 83 | @Override 84 | public boolean equals(Object o) { 85 | if (this == o) return true; 86 | if (o == null || getClass() != o.getClass()) return false; 87 | NetworkImpl network = (NetworkImpl) o; 88 | return id == network.id && premium == network.premium && Objects.equals(name, network.name) && Objects.equals(protectedCNAME, network.protectedCNAME) && Objects.equals(txtVerification, network.txtVerification) && Objects.equals(mitigationSettings, network.mitigationSettings) && Objects.equals(updatedAt, network.updatedAt) && Objects.equals(createdAt, network.createdAt); 89 | } 90 | 91 | @Override 92 | public int hashCode() { 93 | return Objects.hash(id, name, premium, protectedCNAME, txtVerification, mitigationSettings, updatedAt, createdAt); 94 | } 95 | 96 | @Override 97 | public String toString() { 98 | return "NetworkImpl{" + 99 | "id=" + id + 100 | ", name='" + name + '\'' + 101 | ", premium=" + premium + 102 | ", protectedCNAME='" + protectedCNAME + '\'' + 103 | ", txtVerification='" + txtVerification + '\'' + 104 | ", mitigationSettings=" + mitigationSettings + 105 | ", updatedAt=" + updatedAt + 106 | ", createdAt=" + createdAt + 107 | '}'; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/BackendSetPatchRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.Arrays; 6 | 7 | public class BackendSetPatchRequest { 8 | 9 | @JsonProperty 10 | private final String name; 11 | @JsonProperty 12 | private final String[] backends; 13 | 14 | public BackendSetPatchRequest(String name, String[] backends) { 15 | this.name = name; 16 | this.backends = backends; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "BackendSetPatchRequest{" + 22 | "name='" + name + '\'' + 23 | ", backends=" + Arrays.toString(backends) + 24 | '}'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/BackendSetPostRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.Arrays; 6 | 7 | public class BackendSetPostRequest { 8 | 9 | @JsonProperty 10 | private final String name; 11 | @JsonProperty 12 | private final String[] backends; 13 | 14 | public BackendSetPostRequest(String name, String[] backends) { 15 | this.name = name; 16 | this.backends = backends; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "BackendSetPostRequest{" + 22 | "name='" + name + '\'' + 23 | ", backends=" + Arrays.toString(backends) + 24 | '}'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/DomainPatchRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class DomainPatchRequest { 6 | 7 | @JsonProperty 8 | private final String name; 9 | @JsonProperty("backend_set_id") 10 | private final int backendSetID; 11 | @JsonProperty 12 | private final boolean bac; 13 | 14 | public DomainPatchRequest(String name, int backendSetID, boolean bac) { 15 | this.name = name; 16 | this.backendSetID = backendSetID; 17 | this.bac = bac; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "DomainPatchRequest{" + 23 | "name='" + name + '\'' + 24 | ", backendSetID=" + backendSetID + 25 | ", bac=" + bac + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/DomainPostRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class DomainPostRequest { 6 | 7 | @JsonProperty 8 | private final String name; 9 | @JsonProperty("backend_set_id") 10 | private final int backendSetID; 11 | @JsonProperty 12 | private final boolean bac; 13 | 14 | public DomainPostRequest(String name, int backendSetID, boolean bac) { 15 | this.name = name; 16 | this.backendSetID = backendSetID; 17 | this.bac = bac; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "DomainPostRequest{" + 23 | "name='" + name + '\'' + 24 | ", backendSetID=" + backendSetID + 25 | ", bac=" + bac + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/DomainPreverifyRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class DomainPreverifyRequest { 6 | 7 | @JsonProperty("domain_name") 8 | private final String domain; 9 | 10 | public DomainPreverifyRequest(String domain) { 11 | this.domain = domain; 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return "DomainPreverifyRequest{" + 17 | "domain='" + domain + '\'' + 18 | '}'; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/NetworkPatchRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import net.tcpshield.tcpshieldapi.MitigationSettings; 5 | import net.tcpshield.tcpshieldapi.Network; 6 | 7 | /** 8 | * Represents the request for patching network settings 9 | * 10 | * @see net.tcpshield.tcpshieldapi.rest.APIConstants#NETWORK_SPECIFIC_ENDPOINT 11 | */ 12 | public class NetworkPatchRequest { 13 | 14 | @JsonProperty("id") 15 | private final int networkID; 16 | @JsonProperty("name") 17 | private final String name; 18 | @JsonProperty("connections_per_second_threshold") 19 | private final int connectionsPerSecondThreshold; 20 | @JsonProperty("client_ban_seconds") 21 | private final int clientBanSeconds; 22 | @JsonProperty("client_allow_seconds") 23 | private final int clientAllowSeconds; 24 | @JsonProperty("mitigation_message") 25 | private final String mitigationMessage; 26 | 27 | /** 28 | * Constructs a {@code NetworkPatchRequest} with the specified parameters. 29 | * 30 | * @param networkID the network id 31 | * @param name the name of the network; max. length: 50 characters 32 | * @param connectionsPerSecondThreshold how many total connections your server should receive before TCPShield starts mitigating; 1 <= x <= 100 33 | * @param clientBanSeconds total amount of time blocked attempts should be banned for; 60 <= x <= 3600 34 | * @param clientAllowSeconds total amount of time valid connections should be accepted; 30 <= x <= 600 35 | * @param mitigationMessage the message to be displayed after successful validation; max. length: 489 characters 36 | * @throws IllegalArgumentException if the conditions for the parameters aren't met 37 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, NetworkPatchRequest) 38 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(int, String, int, int, int, String) 39 | * @see net.tcpshield.tcpshieldapi.APIClient#patchNetwork(Network, MitigationSettings) 40 | */ 41 | public NetworkPatchRequest(int networkID, String name, int connectionsPerSecondThreshold, int clientBanSeconds, int clientAllowSeconds, String mitigationMessage) { 42 | if (name.length() > 50) 43 | throw new IllegalArgumentException("name cannot be longer than 50 characters. Provided value:\"" + name + "\""); 44 | if (1 > connectionsPerSecondThreshold || connectionsPerSecondThreshold > 100) 45 | throw new IllegalArgumentException("connectionsPerSecondThreshold not between 1 and 100. Provided value: \"" + connectionsPerSecondThreshold + "\""); 46 | if (60 > clientBanSeconds || clientBanSeconds > 3600) 47 | throw new IllegalArgumentException("clientBanSeconds not between 30 and 3600. Provided value: \"" + clientBanSeconds + "\""); 48 | if (30 > clientAllowSeconds || clientAllowSeconds > 600) 49 | throw new IllegalArgumentException("clientAllowSeconds not between 30 and 600. Provided value: \"" + clientAllowSeconds + "\""); 50 | if (mitigationMessage.length() > 500 - "{\"text\":\"\"}".length()) // 11 less characters 51 | throw new IllegalArgumentException("mitigationMessage cannot be longer than 489 characters. Provided value: \"" + mitigationMessage + "\" (" + " characters)"); 52 | 53 | this.networkID = networkID; 54 | this.name = name; 55 | this.connectionsPerSecondThreshold = connectionsPerSecondThreshold; 56 | this.clientBanSeconds = clientBanSeconds; 57 | this.clientAllowSeconds = clientAllowSeconds; 58 | this.mitigationMessage = "{\"text\":\"" + mitigationMessage + "\"}"; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "NetworkPatchRequest{" + 64 | "networkID=" + networkID + 65 | ", name='" + name + '\'' + 66 | ", connectionsPerSecondThreshold=" + connectionsPerSecondThreshold + 67 | ", clientBanSeconds=" + clientBanSeconds + 68 | ", clientAllowSeconds=" + clientAllowSeconds + 69 | ", mitigationMessage='" + mitigationMessage + '\'' + 70 | '}'; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/request/NetworkPostRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | /** 6 | * Represents the request for creating a new network 7 | * 8 | * @see net.tcpshield.tcpshieldapi.rest.APIConstants#NETWORKS_ENDPOINT 9 | */ 10 | public class NetworkPostRequest { 11 | 12 | @JsonProperty 13 | private final String name; 14 | 15 | /** 16 | * Constructs a {@code NetworkPostRequest} with the specified name. 17 | * 18 | * @param name the name of the network; max. length: 50 characters 19 | */ 20 | public NetworkPostRequest(String name) { 21 | if (name.length() > 50) 22 | throw new IllegalArgumentException("name cannot be longer than 50 characters. Provided value:\"" + name + "\""); 23 | 24 | this.name = name; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "NetworkPostRequest{" + 30 | "name='" + name + '\'' + 31 | '}'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/BackendSetPostResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class BackendSetPostResponse { 6 | 7 | @JsonProperty 8 | private Data data; 9 | @JsonProperty 10 | private String message; 11 | @JsonProperty 12 | private int status; 13 | 14 | public Data getData() { 15 | return data; 16 | } 17 | 18 | public String getMessage() { 19 | return message; 20 | } 21 | 22 | public int getStatus() { 23 | return status; 24 | } 25 | 26 | public static class Data { 27 | 28 | @JsonProperty 29 | private int id; 30 | 31 | public int getID() { 32 | return id; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "Data{" + 38 | "id=" + id + 39 | '}'; 40 | } 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "BackendSetPostResponse{" + 46 | "data=" + data + 47 | ", message='" + message + '\'' + 48 | ", status=" + status + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/BackendSetResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 5 | 6 | import java.util.Arrays; 7 | import java.util.Date; 8 | 9 | public class BackendSetResponse { 10 | 11 | @JsonProperty("id") 12 | private int id; 13 | @JsonProperty 14 | private String name; 15 | @JsonProperty 16 | private boolean active; 17 | @JsonProperty("updated_at") 18 | private Date updatedAt; 19 | @JsonProperty("created_at") 20 | private Date createdAt; 21 | @JsonProperty("deleted_at") 22 | private Date deletedAt; 23 | @JsonProperty 24 | private String[] backends; 25 | @JsonProperty 26 | private int status; 27 | @JsonProperty 28 | private String message; 29 | 30 | public int getID() { 31 | return id; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public boolean isActive() { 39 | return active; 40 | } 41 | 42 | public Date getUpdatedAt() { 43 | return updatedAt; 44 | } 45 | 46 | public Date getCreatedAt() { 47 | return createdAt; 48 | } 49 | 50 | public Date getDeletedAt() { 51 | return deletedAt; 52 | } 53 | 54 | public String[] getBackends() { 55 | return backends; 56 | } 57 | 58 | public int getStatus() { 59 | return status; 60 | } 61 | 62 | public String getMessage() { 63 | return message; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return "BackendSetResponse{" + 69 | "id=" + id + 70 | ", name='" + name + '\'' + 71 | ", active=" + active + 72 | ", updatedAt=" + updatedAt + 73 | ", createdAt=" + createdAt + 74 | ", deletedAt=" + deletedAt + 75 | ", backends=" + Arrays.toString(backends) + 76 | ", status=" + status + 77 | ", message='" + message + '\'' + 78 | '}'; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/BackendSetsResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class BackendSetsResponse extends ArrayList { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/DomainPostResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.Date; 6 | 7 | public class DomainPostResponse { 8 | 9 | @JsonProperty 10 | private Data data; 11 | @JsonProperty 12 | private String message; 13 | @JsonProperty 14 | private int status; 15 | 16 | public Data getData() { 17 | return data; 18 | } 19 | 20 | public String getMessage() { 21 | return message; 22 | } 23 | 24 | public int getStatus() { 25 | return status; 26 | } 27 | 28 | public static class Data { 29 | 30 | @JsonProperty 31 | private int id; 32 | @JsonProperty 33 | private String name; 34 | @JsonProperty("backend_set_id") 35 | private int setID; 36 | @JsonProperty 37 | private boolean bac; 38 | @JsonProperty 39 | private boolean verified; 40 | @JsonProperty("updated_at") 41 | private Date updatedAt; 42 | @JsonProperty("created_at") 43 | private Date createdAt; 44 | 45 | public int getID() { 46 | return id; 47 | } 48 | 49 | public String getName() { 50 | return name; 51 | } 52 | 53 | public int getSetID() { 54 | return setID; 55 | } 56 | 57 | public boolean isBACEnabled() { 58 | return bac; 59 | } 60 | 61 | public boolean isVerified() { 62 | return verified; 63 | } 64 | 65 | public Date getUpdatedAt() { 66 | return updatedAt; 67 | } 68 | 69 | public Date getCreatedAt() { 70 | return createdAt; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | return "Data{" + 76 | "id=" + id + 77 | ", name='" + name + '\'' + 78 | ", setID=" + setID + 79 | ", bac=" + bac + 80 | ", verified=" + verified + 81 | ", updatedAt=" + updatedAt + 82 | ", createdAt=" + createdAt + 83 | '}'; 84 | } 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return "DomainPostResponse{" + 90 | "data=" + data + 91 | ", message='" + message + '\'' + 92 | ", status=" + status + 93 | '}'; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/DomainPreverifyResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class DomainPreverifyResponse { 6 | 7 | @JsonProperty 8 | private String message; 9 | @JsonProperty 10 | private int status; 11 | 12 | public String getMessage() { 13 | return message; 14 | } 15 | 16 | public int getStatus() { 17 | return status; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "DomainPreverifyResponse{" + 23 | "message='" + message + '\'' + 24 | ", status=" + status + 25 | '}'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/DomainResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 5 | 6 | import java.util.Date; 7 | 8 | public class DomainResponse { 9 | 10 | @JsonProperty 11 | private int id; 12 | @JsonProperty 13 | private String name; 14 | @JsonProperty("backend_set_id") 15 | private int backendSetID; 16 | @JsonProperty 17 | private boolean bac; 18 | @JsonProperty 19 | private boolean verified; 20 | @JsonProperty("updated_at") 21 | private Date updatedAt; 22 | @JsonProperty("created_at") 23 | private Date createdAt; 24 | 25 | public int getID() { 26 | return id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public int getBackendSetID() { 34 | return backendSetID; 35 | } 36 | 37 | public boolean isBACEnabled() { 38 | return bac; 39 | } 40 | 41 | public boolean isVerified() { 42 | return verified; 43 | } 44 | 45 | public Date getUpdatedAt() { 46 | return updatedAt; 47 | } 48 | 49 | public Date getCreatedAt() { 50 | return createdAt; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "DomainResponse{" + 56 | "id=" + id + 57 | ", name='" + name + '\'' + 58 | ", backendSetID=" + backendSetID + 59 | ", bac=" + bac + 60 | ", verified=" + verified + 61 | ", updatedAt=" + updatedAt + 62 | ", createdAt=" + createdAt + 63 | '}'; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/DomainVerifyResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class DomainVerifyResponse { 6 | 7 | @JsonProperty 8 | private String message; 9 | @JsonProperty 10 | private String error; 11 | @JsonProperty 12 | private int status; 13 | 14 | public String getMessage() { 15 | return message; 16 | } 17 | 18 | public String getError() { 19 | return error; 20 | } 21 | 22 | public int getStatus() { 23 | return status; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "DomainVerifyResponse{" + 29 | "message='" + message + '\'' + 30 | ", error='" + error + '\'' + 31 | ", status=" + status + 32 | '}'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/DomainsResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class DomainsResponse extends ArrayList { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/NetworkPostRepsonse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class NetworkPostRepsonse { 6 | 7 | @JsonProperty 8 | private Data data; 9 | @JsonProperty 10 | private String message; 11 | @JsonProperty 12 | private int status; 13 | 14 | public Data getData() { 15 | return data; 16 | } 17 | 18 | public String getMessage() { 19 | return message; 20 | } 21 | 22 | public int getStatus() { 23 | return status; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "NetworkPostRepsonse{" + 29 | "data=" + data + 30 | ", message='" + message + '\'' + 31 | ", status=" + status + 32 | '}'; 33 | } 34 | 35 | public static class Data { 36 | 37 | @JsonProperty("network_id") 38 | private int networkID; 39 | 40 | public int getNetworkID() { 41 | return networkID; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "Data{" + 47 | "networkID=" + networkID + 48 | '}'; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/NetworkResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 5 | 6 | import java.util.Date; 7 | 8 | public class NetworkResponse { 9 | 10 | @JsonProperty 11 | private int id; 12 | @JsonProperty 13 | private String name; 14 | @JsonProperty 15 | private boolean premium; 16 | @JsonProperty("protected_cname") 17 | private String protectedCNAME; 18 | @JsonProperty("txt_verification") 19 | private String txtVerification; 20 | @JsonProperty("connections_per_second_threshold") 21 | private int connectionsPerSecondThreshold; 22 | @JsonProperty("client_ban_seconds") 23 | private int clientBanSeconds; 24 | @JsonProperty("client_allow_seconds") 25 | private int clientAllowSeconds; 26 | @JsonProperty("mitigation_message") 27 | private String mitigationMessage; 28 | @JsonProperty("updated_at") 29 | private Date updatedAt; 30 | @JsonProperty("created_at") 31 | private Date createdAt; 32 | 33 | public int getID() { 34 | return id; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public boolean isPremium() { 42 | return premium; 43 | } 44 | 45 | public String getProtectedCNAME() { 46 | return protectedCNAME; 47 | } 48 | 49 | public String getTXTVerification() { 50 | return txtVerification; 51 | } 52 | 53 | public int getConnectionsPerSecondThreshold() { 54 | return connectionsPerSecondThreshold; 55 | } 56 | 57 | public int getClientBanSeconds() { 58 | return clientBanSeconds; 59 | } 60 | 61 | public int getClientAllowSeconds() { 62 | return clientAllowSeconds; 63 | } 64 | 65 | public String getMitigationMessage() { 66 | return mitigationMessage; 67 | } 68 | 69 | public Date getUpdatedAt() { 70 | return updatedAt; 71 | } 72 | 73 | public Date getCreatedAt() { 74 | return createdAt; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "NetworkResponse{" + 80 | "id=" + id + 81 | ", name='" + name + '\'' + 82 | ", premium=" + premium + 83 | ", protectedCNAME='" + protectedCNAME + '\'' + 84 | ", txtVerification='" + txtVerification + '\'' + 85 | ", connectionsPerSecondThreshold=" + connectionsPerSecondThreshold + 86 | ", clientBanSeconds=" + clientBanSeconds + 87 | ", clientAllowSeconds=" + clientAllowSeconds + 88 | ", mitigationMessage='" + mitigationMessage + '\'' + 89 | ", updatedAt=" + updatedAt + 90 | ", createdAt=" + createdAt + 91 | '}'; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/response/NetworksResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.response; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class NetworksResponse extends ArrayList { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/rest/APIConstants.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.rest; 2 | 3 | public class APIConstants { 4 | 5 | private static final String BASE_URL = "https://api.tcpshield.com"; 6 | 7 | /* === ENDPOINTS === */ 8 | 9 | /* Networks */ 10 | public static final String NETWORKS_ENDPOINT = BASE_URL + "/networks"; 11 | public static final String NETWORK_SPECIFIC_ENDPOINT = NETWORKS_ENDPOINT + "/{networkId}"; 12 | 13 | /* Domains */ 14 | public static final String DOMAINS_ENDPOINT = NETWORK_SPECIFIC_ENDPOINT + "/domains"; 15 | public static final String DOMAINS_PREVERIFY_ENDPOINT = DOMAINS_ENDPOINT + "/preverify"; 16 | public static final String DOMAIN_SPECIFIC_ENDPOINT = DOMAINS_ENDPOINT + "/{domainId}"; 17 | public static final String DOMAIN_VERIFY_ENDPOINT = DOMAIN_SPECIFIC_ENDPOINT + "/verify"; 18 | 19 | /* Backends */ 20 | public static final String BACKENDS_ENDPOINT = NETWORK_SPECIFIC_ENDPOINT + "/backendSets"; 21 | public static final String BACKENDS_SPECIFIC_ENDPOINT = BACKENDS_ENDPOINT + "/{setId}"; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/rest/RequestType.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.rest; 2 | 3 | public enum RequestType { 4 | 5 | GET, 6 | POST, 7 | PATCH, 8 | DELETE 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/rest/RestClient.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.rest; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.databind.module.SimpleModule; 6 | import net.tcpshield.tcpshieldapi.deserializer.DateDeserializer; 7 | import net.tcpshield.tcpshieldapi.exception.APIConnectionException; 8 | import net.tcpshield.tcpshieldapi.exception.status.NoPermissionException; 9 | import net.tcpshield.tcpshieldapi.exception.status.NotFoundException; 10 | 11 | import javax.net.ssl.HttpsURLConnection; 12 | import java.io.*; 13 | import java.net.URL; 14 | import java.nio.charset.StandardCharsets; 15 | import java.util.Date; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | import java.util.stream.Collectors; 19 | 20 | public class RestClient { 21 | 22 | private final Pattern HTTP_RESPONSE_CODE_EXCEPTION_PATTERN = Pattern.compile("^Server returned HTTP response code: (\\d+) for URL: .+$"); 23 | private final String apiKey; 24 | private final ObjectMapper mapper = new ObjectMapper(); 25 | 26 | public RestClient(String apiKey) { 27 | this.apiKey = apiKey; 28 | 29 | SimpleModule module = new SimpleModule(); 30 | module.addDeserializer(Date.class, new DateDeserializer()); 31 | 32 | mapper.registerModule(module); 33 | } 34 | 35 | public T makeRequest(RestRequest restRequest) { 36 | RestResponse response = null; 37 | int statusCode = -1; 38 | try { 39 | response = internalRequest(restRequest); 40 | } catch (FileNotFoundException e) { // 404 41 | statusCode = 404; 42 | } catch (IOException e) { 43 | String msg = e.getMessage(); 44 | Matcher matcher = HTTP_RESPONSE_CODE_EXCEPTION_PATTERN.matcher(msg); 45 | 46 | if (!matcher.find()) throw new APIConnectionException(e); 47 | 48 | statusCode = Integer.parseInt(matcher.group(1)); 49 | } 50 | 51 | if (statusCode != 0 && response != null) 52 | statusCode = response.getStatusCode(); 53 | 54 | switch (statusCode) { 55 | case 403: 56 | throw new NoPermissionException(); 57 | case 404: 58 | throw new NotFoundException(); 59 | default: 60 | if (response == null) 61 | throw new APIConnectionException("Response code unknown: " + statusCode + "; for request to " + restRequest.getURL()); 62 | 63 | return response.getData(); 64 | } 65 | } 66 | 67 | private RestResponse internalRequest(RestRequest request) throws IOException { 68 | String data = toJson(request.getData()); 69 | 70 | URL url = new URL(request.getURL()); 71 | 72 | HttpsURLConnection connection = null; 73 | try { 74 | connection = (HttpsURLConnection) url.openConnection(); 75 | 76 | connection.setRequestMethod(request.getRequestType().name()); 77 | 78 | connection.setRequestProperty("X-API-Key", apiKey); 79 | connection.setRequestProperty("Content-Type", "application/json"); 80 | connection.setRequestProperty("Content-Length", data == null ? "0" : String.valueOf(data.length())); 81 | connection.setRequestProperty("Content-Language", "en-US"); 82 | 83 | connection.setDoInput(true); 84 | connection.setDoOutput(true); 85 | 86 | connection.connect(); 87 | 88 | if (data != null) { 89 | try (OutputStream outputStream = connection.getOutputStream(); 90 | OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) { 91 | writer.write(data); 92 | } 93 | } 94 | 95 | try (InputStream inputStream = connection.getInputStream(); 96 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { 97 | String response = bufferedReader.lines().filter(str -> !str.isEmpty()).collect(Collectors.joining("\n")); 98 | int statusCode = connection.getResponseCode(); 99 | 100 | T parsed = parseJson(response, request.getResponseClass()); 101 | return new RestResponse<>(statusCode, parsed); 102 | } 103 | } finally { 104 | if (connection != null) 105 | connection.disconnect(); 106 | } 107 | } 108 | 109 | private String toJson(Object data) throws JsonProcessingException { 110 | if (data == null) return null; 111 | 112 | return mapper.writeValueAsString(data); 113 | } 114 | 115 | private T parseJson(String data, Class targetClass) throws IOException { 116 | if (targetClass == null) return null; 117 | 118 | return mapper.readValue(data, targetClass); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/rest/RestRequest.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.rest; 2 | 3 | public class RestRequest { 4 | 5 | private final Class responseClass; 6 | private final String url; 7 | private final RequestType requestType; 8 | private final Object data; 9 | 10 | RestRequest(Class responseClass, String url, RequestType requestType, Object data) { 11 | this.responseClass = responseClass; 12 | this.url = url; 13 | this.requestType = requestType; 14 | this.data = data; 15 | } 16 | 17 | public static Builder builder() { 18 | return new Builder<>(null); 19 | } 20 | 21 | public static Builder builder(Class responseClass) { 22 | return new Builder<>(responseClass); 23 | } 24 | 25 | public Class getResponseClass() { 26 | return responseClass; 27 | } 28 | 29 | public String getURL() { 30 | return url; 31 | } 32 | 33 | public RequestType getRequestType() { 34 | return requestType; 35 | } 36 | 37 | public Object getData() { 38 | return data; 39 | } 40 | 41 | public T execute(RestClient client) { 42 | return client.makeRequest(this); 43 | } 44 | 45 | public static class Builder { 46 | 47 | private final Class responseClass; 48 | private String url; 49 | private RequestType requestType; 50 | private Object data; 51 | 52 | public Builder(Class responseClass) { 53 | this.responseClass = responseClass; 54 | } 55 | 56 | public Builder url(String url) { 57 | this.url = url; 58 | return this; 59 | } 60 | 61 | public Builder pathVariable(String key, String value) { 62 | this.url = this.url.replaceAll("\\{" + key + "}", value); 63 | return this; 64 | } 65 | 66 | public Builder requestType(RequestType requestType) { 67 | this.requestType = requestType; 68 | return this; 69 | } 70 | 71 | public Builder data(Object data) { 72 | this.data = data; 73 | return this; 74 | } 75 | 76 | public RestRequest build() { 77 | return new RestRequest<>(responseClass, url, requestType, data); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/net/tcpshield/tcpshieldapi/rest/RestResponse.java: -------------------------------------------------------------------------------- 1 | package net.tcpshield.tcpshieldapi.rest; 2 | 3 | public class RestResponse { 4 | 5 | private final int statusCode; 6 | private final T data; 7 | 8 | public RestResponse(int statusCode, T data) { 9 | this.statusCode = statusCode; 10 | this.data = data; 11 | } 12 | 13 | public int getStatusCode() { 14 | return statusCode; 15 | } 16 | 17 | public T getData() { 18 | return data; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/de/tcpshield/tcpshieldapi/APIClientTest.java: -------------------------------------------------------------------------------- 1 | package de.tcpshield.tcpshieldapi; 2 | 3 | import net.tcpshield.tcpshieldapi.impl.APIClientImpl; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static org.junit.jupiter.api.Assertions.assertThrows; 7 | 8 | /** 9 | * Tests regarding the instantiation of the API client 10 | */ 11 | public class APIClientTest { 12 | 13 | @Test 14 | public void testExceptionOnNullInstantiation() { 15 | assertThrows(IllegalArgumentException.class, () -> new APIClientImpl(null)); 16 | } 17 | 18 | @Test 19 | public void testNoExceptionOnCorrectInstantiation() { 20 | new APIClientImpl(TestConstants.API_KEY); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/de/tcpshield/tcpshieldapi/CUDTest.java: -------------------------------------------------------------------------------- 1 | package de.tcpshield.tcpshieldapi; 2 | 3 | import net.tcpshield.tcpshieldapi.*; 4 | import net.tcpshield.tcpshieldapi.exception.status.NotFoundException; 5 | import net.tcpshield.tcpshieldapi.impl.APIClientImpl; 6 | import net.tcpshield.tcpshieldapi.response.BackendSetPostResponse; 7 | import net.tcpshield.tcpshieldapi.response.DomainPostResponse; 8 | import net.tcpshield.tcpshieldapi.response.NetworkPostRepsonse; 9 | import org.junit.jupiter.api.AfterAll; 10 | import org.junit.jupiter.api.AfterEach; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.junit.jupiter.api.Assertions.*; 14 | 15 | /** 16 | * Tests for [c]reating, [u]pdating and [d]eleting 17 | */ 18 | public class CUDTest { 19 | 20 | private static final APIClient API_CLIENT = new APIClientImpl(TestConstants.API_KEY); 21 | 22 | @Test 23 | public void testCUD() { 24 | /* === Create === */ 25 | 26 | // Network 27 | NetworkPostRepsonse addNetworkResponse = API_CLIENT.addNetwork("TemporaryTestNetwork"); 28 | assertEquals(0, addNetworkResponse.getStatus()); 29 | 30 | int networkID = addNetworkResponse.getData().getNetworkID(); 31 | Network network = API_CLIENT.getNetwork(networkID); 32 | 33 | assertEquals("TemporaryTestNetwork", network.getName()); 34 | 35 | // Backend Set 36 | BackendSetPostResponse addBackendSetResponse = API_CLIENT.addBackendSet(networkID, "TestSet", "127.0.0.1:25565", "127.0.0.1:25566"); 37 | assertEquals(0, addBackendSetResponse.getStatus()); 38 | 39 | int setID = addBackendSetResponse.getData().getID(); 40 | BackendSet set = API_CLIENT.getBackendSet(networkID, setID); 41 | 42 | assertEquals("TestSet", set.getName()); 43 | assertEquals(2, set.getBackends().size()); 44 | assertEquals("127.0.0.1:25565", set.getBackends().get(0)); 45 | assertEquals("127.0.0.1:25566", set.getBackends().get(1)); 46 | 47 | // Domain 48 | DomainPostResponse addDomainResponse = API_CLIENT.addDomain(networkID, TestConstants.TEST_DOMAIN_2, setID, true); 49 | assertEquals(0, addDomainResponse.getStatus()); 50 | 51 | int domainID = addDomainResponse.getData().getID(); 52 | Domain domain = API_CLIENT.getDomain(networkID, domainID); 53 | 54 | assertEquals(setID, domain.getBackendSetID()); 55 | assertEquals(TestConstants.TEST_DOMAIN_2, domain.getName()); 56 | assertTrue(domain.isBACEnabled()); 57 | 58 | /* === Update === */ 59 | 60 | // Network 61 | API_CLIENT.patchNetwork(networkID, "TemporaryTestNetwork-Rename", 10, 70, 500, "TestMitigationMessage"); 62 | network = API_CLIENT.getNetwork(networkID); 63 | MitigationSettings mitigationSettings = network.getMitigationSettings(); 64 | 65 | assertEquals("TemporaryTestNetwork-Rename", network.getName()); 66 | assertEquals(10, mitigationSettings.getConnectionsPerSecondThreshold()); 67 | assertEquals(70, mitigationSettings.getClientBanSeconds()); 68 | assertEquals(500, mitigationSettings.getClientAllowSeconds()); 69 | assertEquals("{\"text\":\"TestMitigationMessage\"}", mitigationSettings.getMitigationMessage()); 70 | 71 | // Backend Set 72 | API_CLIENT.patchBackendSet(networkID, setID, "TestSet-Rename", "127.0.0.1:25564"); 73 | set = API_CLIENT.getBackendSet(networkID, setID); 74 | 75 | assertEquals("TestSet-Rename", set.getName()); 76 | assertEquals(1, set.getBackends().size()); 77 | assertEquals("127.0.0.1:25564", set.getBackends().get(0)); 78 | 79 | // Domain 80 | API_CLIENT.patchDomain(networkID, domainID, "rename-" + TestConstants.TEST_DOMAIN_2, setID, false); 81 | domain = API_CLIENT.getDomain(networkID, domainID); 82 | 83 | assertEquals("rename-" + TestConstants.TEST_DOMAIN_2, domain.getName()); 84 | assertEquals(setID, domain.getBackendSetID()); 85 | assertFalse(domain.isBACEnabled()); 86 | 87 | /* === Delete === */ 88 | 89 | // Backend Set 90 | API_CLIENT.deleteBackendSet(networkID, setID); 91 | assertThrows(NotFoundException.class, () -> API_CLIENT.getBackendSet(networkID, setID)); 92 | 93 | // Domain 94 | API_CLIENT.deleteDomain(networkID, domainID); 95 | assertThrows(NotFoundException.class, () -> API_CLIENT.getDomain(networkID, domainID)); 96 | 97 | // Network 98 | API_CLIENT.deleteNetwork(networkID); 99 | assertThrows(NotFoundException.class, () -> API_CLIENT.getNetwork(networkID)); 100 | } 101 | 102 | /** 103 | * Clean up test networks if any tests fail and they aren't automatically deleted 104 | */ 105 | @AfterEach 106 | public void cleanUp() { 107 | for (Network network : API_CLIENT.getNetworks()) { 108 | if (!network.getName().equals("TemporaryTestNetwork") && !network.getName().equals("TemporaryTestNetwork-Rename")) continue; 109 | 110 | API_CLIENT.deleteNetwork(network.getID()); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/test/java/de/tcpshield/tcpshieldapi/FetchTest.java: -------------------------------------------------------------------------------- 1 | package de.tcpshield.tcpshieldapi; 2 | 3 | import net.tcpshield.tcpshieldapi.APIClient; 4 | import net.tcpshield.tcpshieldapi.BackendSet; 5 | import net.tcpshield.tcpshieldapi.Domain; 6 | import net.tcpshield.tcpshieldapi.Network; 7 | import net.tcpshield.tcpshieldapi.impl.APIClientImpl; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | import static org.junit.jupiter.api.Assertions.*; 14 | 15 | /** 16 | * Tests for fetching information from the panel. Note that predefined names, domains and backend sets are required. 17 | * More infos on the testing requirements can be found here. 18 | */ 19 | public class FetchTest { 20 | 21 | private static final APIClient API_CLIENT = new APIClientImpl(TestConstants.API_KEY); 22 | 23 | @Test 24 | public void testFetching() { 25 | // Network fetching 26 | List networks = API_CLIENT.getNetworks(); 27 | 28 | Optional networkOptional = networks.stream().filter(network -> network.getName().equals("TestNetwork")).findAny(); 29 | assertTrue(networkOptional.isPresent()); 30 | 31 | Network network = networkOptional.get(); 32 | 33 | assertNotEquals(0, network.getID()); 34 | assertNotNull(network.getTXTVerification()); 35 | assertNotNull(network.getMitigationSettings()); 36 | assertNotNull(network.getProtectedCNAME()); 37 | assertNotNull(network.getCreatedAt()); 38 | assertNotNull(network.getUpdatedAt()); 39 | 40 | assertEquals(network, API_CLIENT.getNetwork(network.getID())); 41 | 42 | // Domain fetching 43 | List domains = API_CLIENT.getDomains(network.getID()); 44 | 45 | Optional domainOptional = domains.stream().filter(domain -> domain.getName().equals(TestConstants.TEST_DOMAIN_1)).findAny(); 46 | assertTrue(domainOptional.isPresent()); 47 | 48 | Domain domain = domainOptional.get(); 49 | 50 | assertNotEquals(0, domain.getID()); 51 | assertNotEquals(0, domain.getBackendSetID()); 52 | assertNotNull(domain.getCreatedAt()); 53 | assertNotNull(domain.getUpdatedAt()); 54 | 55 | assertEquals(domain, API_CLIENT.getDomain(network.getID(), domain.getID())); 56 | 57 | // Backend fetching 58 | BackendSet backendSet = API_CLIENT.getBackendSet(network.getID(), domain.getBackendSetID()); 59 | 60 | assertEquals(domain.getBackendSetID(), backendSet.getID()); 61 | assertEquals("TestSet", backendSet.getName()); 62 | assertEquals(2, backendSet.getBackends().size()); 63 | assertEquals("127.0.0.1:25565", backendSet.getBackends().get(0)); 64 | assertEquals("127.0.0.1:25566", backendSet.getBackends().get(1)); 65 | 66 | assertEquals(backendSet, API_CLIENT.getBackendSet(network.getID(), domain.getBackendSetID())); 67 | assertEquals(backendSet.getID(), API_CLIENT.getBackendSets(network.getID()).stream().filter(set -> set.getName().equals("TestSet")).findAny().orElseThrow(IllegalStateException::new).getID()); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/de/tcpshield/tcpshieldapi/TestConstants.java: -------------------------------------------------------------------------------- 1 | package de.tcpshield.tcpshieldapi; 2 | 3 | public class TestConstants { 4 | 5 | public static final String API_KEY = System.getProperty("testing.api-key"); 6 | public static final String TEST_DOMAIN_1 = System.getProperty("testing.domain1"); 7 | public static final String TEST_DOMAIN_2 = System.getProperty("testing.domain2"); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/de/tcpshield/tcpshieldapi/VerificationTest.java: -------------------------------------------------------------------------------- 1 | package de.tcpshield.tcpshieldapi; 2 | 3 | import net.tcpshield.tcpshieldapi.APIClient; 4 | import net.tcpshield.tcpshieldapi.Domain; 5 | import net.tcpshield.tcpshieldapi.impl.APIClientImpl; 6 | import org.junit.jupiter.api.AfterEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.util.List; 10 | 11 | import static org.junit.jupiter.api.Assertions.assertFalse; 12 | import static org.junit.jupiter.api.Assertions.assertTrue; 13 | 14 | /** 15 | * Tests regarding domain verification 16 | */ 17 | public class VerificationTest { 18 | 19 | private static final APIClient API_CLIENT = new APIClientImpl(TestConstants.API_KEY); 20 | 21 | @Test 22 | public void testVerification() { 23 | int networkID = API_CLIENT.getNetworks().stream().filter(network -> network.getName().equals("TestNetwork")).findAny().orElseThrow(IllegalStateException::new).getID(); 24 | 25 | List domains = API_CLIENT.getDomains(networkID); 26 | Domain verifySuccessDomain = domains.stream().filter(domain -> domain.getName().equals(TestConstants.TEST_DOMAIN_1)).findAny().orElseThrow(IllegalStateException::new); 27 | Domain verifyFailDomain = domains.stream().filter(domain -> domain.getName().equals("unverifiedtestdomain.com")).findAny().orElseThrow(IllegalStateException::new); 28 | 29 | assertTrue(API_CLIENT.preverify(networkID, TestConstants.TEST_DOMAIN_1)); 30 | assertFalse(API_CLIENT.preverify(networkID, "unverifiedtestdomain.com")); 31 | 32 | assertTrue(API_CLIENT.verify(networkID, verifySuccessDomain.getID())); 33 | assertFalse(API_CLIENT.verify(networkID, verifyFailDomain.getID())); 34 | } 35 | 36 | @AfterEach 37 | public void cleanUp() { // resets domain verification 38 | int networkID = API_CLIENT.getNetworks().stream().filter(network -> network.getName().equals("TestNetwork")).findAny().orElseThrow(IllegalStateException::new).getID(); 39 | 40 | Domain verifySuccessDomain = API_CLIENT.getDomains(networkID).stream().filter(domain -> domain.getName().equals(TestConstants.TEST_DOMAIN_1)).findAny().orElseThrow(IllegalStateException::new); 41 | 42 | API_CLIENT.deleteDomain(networkID, verifySuccessDomain.getID()); 43 | API_CLIENT.addDomain(networkID, TestConstants.TEST_DOMAIN_1, verifySuccessDomain.getBackendSetID(), false); 44 | } 45 | } 46 | --------------------------------------------------------------------------------