diff --git a/README.md b/README.md index 82d643a..53d8e27 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ * Java 1.5 or above. -* Read API documentation (https://latch.telefonica.com/www/developers/doc_api). +* Read API documentation (https://latch.tu.com/www/developers/doc_api). -* To get the "Application ID" and "Secret", (fundamental values for integrating Latch in any application), it’s necessary to register a developer account in Latch's website: https://latch.telefonica.com. On the upper right side, click on "Developer area". +* To get the "Application ID" and "Secret", (fundamental values for integrating Latch in any application), it’s necessary to register a developer account in Latch's website: https://latch.tu.com. On the upper right side, click on "Developer area". #### CREATING THE JAR DEPENDENCY #### @@ -62,11 +62,11 @@ You need this additional parameters: - WEB3SIGNATURE: A proof-of-ownership signature of a constant, in order to verify that the user owns the private key of the wallet. You can use https://etherscan.io/verifiedSignatures# to sign the following message: - MESSAGE TO SIGN : **"Latch-Web3"** -Example of using it [java example](src/test/java/TestExampleWeb3.java) +Example of using it [java example](src/test/java/ExampleWeb3.java) #### TROUBLESHOOTING #### *A javax.net.ssl.SSLHandshakeException with a nested sun.security.validator.ValidatorException is thrown when invoking an API call.* -This exception is normally thrown when the JDK doesn't trust the CA that signs the digital certificate used in Latch's website (https://latch.telefonica.com). You may need to install the CA (http://www.startssl.com/certs/ca.pem) as a trusted certificate in your JDK's truststore (normally in jre/lib/security/cacerts) using the keytool utility. +This exception is normally thrown when the JDK doesn't trust the CA that signs the digital certificate used in Latch's website (https://latch.tu.com). You may need to install the CA (http://www.startssl.com/certs/ca.pem) as a trusted certificate in your JDK's truststore (normally in jre/lib/security/cacerts) using the keytool utility. diff --git a/src/main/java/com/elevenpaths/latch/Error.java b/src/main/java/com/elevenpaths/latch/Error.java index 13371e4..3dcffb9 100644 --- a/src/main/java/com/elevenpaths/latch/Error.java +++ b/src/main/java/com/elevenpaths/latch/Error.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/com/elevenpaths/latch/Latch.java b/src/main/java/com/elevenpaths/latch/Latch.java index c0178dc..9982e6e 100644 --- a/src/main/java/com/elevenpaths/latch/Latch.java +++ b/src/main/java/com/elevenpaths/latch/Latch.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/com/elevenpaths/latch/LatchApp.java b/src/main/java/com/elevenpaths/latch/LatchApp.java index 9710037..e1d1850 100755 --- a/src/main/java/com/elevenpaths/latch/LatchApp.java +++ b/src/main/java/com/elevenpaths/latch/LatchApp.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -157,6 +157,15 @@ public LatchResponse status(String accountId, boolean silent, String otpToken, S return status(accountId, null, null, silent, otpToken, otpMessage); } + /** + * Return operation status for a given accountId and operation while sending some custom data (Like OTP token or a message) + * @param accountId The accountId which status is going to be retrieved + * @param operationId The operationId which status is going to be retrieved + * @param silent True for not sending lock/unlock push notifications to the mobile devices, false otherwise. + * @param otpToken This will be the OTP sent to the user instead of generating a new one + * @param otpMessage To attach a custom message with the OTP to the user + * @return LatchResponse containing the status + */ public LatchResponse status(String accountId, String operationId, boolean silent, String otpToken, String otpMessage) { return status(accountId, operationId, null, silent, otpToken, otpMessage); } @@ -165,6 +174,7 @@ public LatchResponse status(String accountId, String operationId, boolean silent * Return operation status for a given accountId and operation while sending some custom data (Like OTP token or a message) * @param accountId The accountId which status is going to be retrieved * @param operationId The operationId which status is going to be retrieved + * @param instanceId The instance identifier * @param silent True for not sending lock/unlock push notifications to the mobile devices, false otherwise. * @param otpToken This will be the OTP sent to the user instead of generating a new one * @param otpMessage To attach a custom message with the OTP to the user @@ -191,6 +201,13 @@ public LatchResponse status(String accountId, String operationId, String instanc return HTTP_POST_proxy(url.toString(), data); } + /** + * Create an instance + * @param accountId The user identified + * @param operationId The operation identifier + * @param instanceName The name for the instance + * @return LatchResponse containing the status + */ public LatchResponse addInstance(String accountId, String operationId, String instanceName) { StringBuilder url = new StringBuilder(API_INSTANCE_URL).append("/").append(accountId); if (operationId != null && !operationId.isEmpty()) { @@ -203,6 +220,13 @@ public LatchResponse addInstance(String accountId, String operationId, String in return HTTP_PUT_proxy(url.toString(), data); } + /** + * Remove the instance + * @param accountId The user identified + * @param operationId The operation identifier + * @param instanceId The instance identifier + * @return LatchResponse containing the status + */ public LatchResponse removeInstance(String accountId, String operationId, String instanceId) { StringBuilder url = new StringBuilder(API_INSTANCE_URL).append("/").append(accountId); if (operationId != null && !operationId.isEmpty()) { @@ -213,28 +237,65 @@ public LatchResponse removeInstance(String accountId, String operationId, String } + /** + * Return operation status for a given accountId + * @param accountId The user identified + * @param operationId The operation identifier + * @return LatchResponse containing the status + */ @Deprecated public LatchResponse operationStatus(String accountId, String operationId) { return status(accountId, operationId, null, false, false); } + /** + * Return operation status for a given accountId + * @param accountId The user identified + * @param operationId The operation identifier + * @param silent True for not sending lock/unlock push notifications to the mobile devices, false otherwise + * @param noOtp True for not generating an OTP if needed + * @return LatchResponse containing the status + */ @Deprecated public LatchResponse operationStatus(String accountId, String operationId, boolean silent, boolean noOtp) { return status(accountId, operationId, null, silent, noOtp); } + /** + * Unpairs the origin provider with a user account. + * @param id The account identified + * @return LatchResponse containing the status + */ public LatchResponse unpair(String id) { return HTTP_GET_proxy(new StringBuilder(API_UNPAIR_URL).append("/").append(id).toString()); } + /** + * Locks the operation + * @param accountId The user identified + * @return LatchResponse containing the status + */ public LatchResponse lock(String accountId) { return lock(accountId, null); } + /** + * Locks the operation + * @param accountId The user identified + * @param operationId The operation identifier + * @return LatchResponse containing the status + */ public LatchResponse lock(String accountId, String operationId) { return lock(accountId, operationId, null); } + /** + * Locks the operation + * @param accountId The user identified + * @param operationId The operation identifier + * @param instanceId The instance identifier + * @return LatchResponse containing the status + */ public LatchResponse lock(String accountId, String operationId, String instanceId) { StringBuilder sb = new StringBuilder(API_LOCK_URL).append("/").append(accountId); if (operationId != null && !operationId.isEmpty()) { @@ -246,14 +307,32 @@ public LatchResponse lock(String accountId, String operationId, String instanceI return HTTP_POST_proxy(sb.toString()); } + /** + * Unlocks the operation + * @param accountId The user identified + * @return LatchResponse containing the status + */ public LatchResponse unlock(String accountId) { return unlock(accountId, null); } + /** + * Unlocks the operation + * @param accountId The user identified + * @param operationId The operation identifier + * @return LatchResponse containing the status + */ public LatchResponse unlock(String accountId, String operationId) { return unlock(accountId, operationId, null); } + /** + * Unlocks the operation + * @param accountId The user identified + * @param operationId The operation identifier + * @param instanceId The instance identifier + * @return LatchResponse containing the status + */ public LatchResponse unlock(String accountId, String operationId, String instanceId) { StringBuilder sb = new StringBuilder(API_UNLOCK_URL).append("/").append(accountId); if (operationId != null && !operationId.isEmpty()) { @@ -265,16 +344,36 @@ public LatchResponse unlock(String accountId, String operationId, String instanc return HTTP_POST_proxy(sb.toString()); } + /** + * Get history status + * @param accountId The user identified + * @return LatchResponse containing the status + */ public LatchResponse history(String accountId) { return HTTP_GET_proxy(new StringBuilder(API_HISTORY_URL).append("/").append(accountId).toString()); } + /** + * Get history status + * @param accountId The user identified + * @param from From in epoch format + * @param to To in epoch format + * @return LatchResponse containing the status + */ public LatchResponse history(String accountId, Long from, Long to) { return HTTP_GET_proxy(new StringBuilder(API_HISTORY_URL).append("/").append(accountId) .append("/").append(from != null ? String.valueOf(from) :"0") .append("/").append(to != null ? String.valueOf(to) : String.valueOf(new Date().getTime())).toString()); } + /** + * Add a new operation + * @param parentId identifies the parent of the operation to be created + * @param name The name of the operation + * @param twoFactor Specifies if the Two Factor protection is enabled for this operation + * @param lockOnRequest Specifies if the 'Lock latches on status request' feature is disabled, opt-in or mandatory for this operation + * @return LatchResponse containing the status + */ public LatchResponse createOperation(String parentId, String name, String twoFactor, String lockOnRequest) { Map data = new HashMap(); data.put("parentId", parentId); @@ -284,18 +383,40 @@ public LatchResponse createOperation(String parentId, String name, String twoFac return HTTP_PUT_proxy(new StringBuilder(API_OPERATION_URL).toString(), data); } + /** + * Remove an operation + * @param operationId The operation identifier + * @return LatchResponse containing the status + */ public LatchResponse removeOperation(String operationId) { return HTTP_DELETE_proxy(new StringBuilder(API_OPERATION_URL).append("/").append(operationId).toString()); } + /** + * Get information about the operation + * @return LatchResponse containing the status + */ public LatchResponse getOperations() { return HTTP_GET_proxy(new StringBuilder(API_OPERATION_URL).toString()); } + /** + * Get information about the operation + * @param operationId The operation identifier + * @return LatchResponse containing the status + */ public LatchResponse getOperations(String operationId) { return HTTP_GET_proxy(new StringBuilder(API_OPERATION_URL).append("/").append(operationId).toString()); } + /** + * Update an operation + * @param operationId The operation identifier + * @param name The name of the operation + * @param twoFactor Specifies if the Two Factor protection is enabled for this operation + * @param lockOnRequest Specifies if the 'Lock latches on status request' feature is disabled, opt-in or mandatory for this operation + * @return LatchResponse containing the status + */ public LatchResponse updateOperation(String operationId, String name, String twoFactor, String lockOnRequest) { Map data = new HashMap(); data.put("name", name); @@ -304,4 +425,56 @@ public LatchResponse updateOperation(String operationId, String name, String two return HTTP_POST_proxy(new StringBuilder(API_OPERATION_URL).append("/").append(operationId).toString(), data); } + /** + * Create a Time-based one-time password + * @param userId User identifier (mail) + * @param commonName Name for the Totp + * @return LatchResponse containing the status + */ + public LatchResponse createTotp(String userId, String commonName) { + Map data = new HashMap(); + data.put("userId", userId); + data.put("commonName", commonName); + return HTTP_POST_proxy(API_TOTP_URL, data); + } + + /** + * Get data information about the totp + * @param totpId Totp Identifier + * @return LatchResponse containing the status + */ + public LatchResponse getTotp(String totpId) { + return HTTP_GET_proxy(new StringBuilder(API_TOTP_URL).append("/").append(totpId).toString()); + } + + /** + * Validate a code from a totp + * @param totpId Totp Identifier + * @param code Code generated + * @return LatchResponse containing the status + */ + public LatchResponse validateTotp(String totpId, String code) { + Map data = new HashMap(); + data.put("code", code); + return HTTP_POST_proxy(new StringBuilder(API_TOTP_URL).append("/").append(totpId).append("/validate").toString(), data); + } + + /** + * Remove a totp + * @param totpId Totp Identifier + * @return LatchResponse containing the status + */ + public LatchResponse removeTotp(String totpId) { + return HTTP_DELETE_proxy(new StringBuilder(API_TOTP_URL).append("/").append(totpId).toString()); + } + + /** + * Check operation status + * @param controlId Control status identifier + * @return LatchResponse containing the status + */ + public LatchResponse checkControlStatus(String controlId) { + return HTTP_GET_proxy(new StringBuilder(API_CONTROL_STATUS_CHECK_URL).append("/").append(controlId).toString()); + } + } diff --git a/src/main/java/com/elevenpaths/latch/LatchAuth.java b/src/main/java/com/elevenpaths/latch/LatchAuth.java index 9e45e3e..c8c0232 100755 --- a/src/main/java/com/elevenpaths/latch/LatchAuth.java +++ b/src/main/java/com/elevenpaths/latch/LatchAuth.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -48,7 +48,7 @@ */ public class LatchAuth { protected static final String API_VERSION = "2.0"; - public static String API_HOST = "https://latch.telefonica.com"; + public static String API_HOST = "https://latch.tu.com"; //App API public static final String API_CHECK_STATUS_URL = "/api/"+API_VERSION+"/status"; @@ -60,6 +60,8 @@ public class LatchAuth { public static final String API_HISTORY_URL = "/api/"+API_VERSION+"/history"; public static final String API_OPERATION_URL = "/api/"+API_VERSION+"/operation"; public static final String API_INSTANCE_URL = "/api/"+API_VERSION+"/instance"; + public static final String API_TOTP_URL = "/api/" + API_VERSION + "/totps"; + public static final String API_CONTROL_STATUS_CHECK_URL = "/api/" + API_VERSION + "/control-status"; //User API public static final String API_APPLICATION_URL = "/api/"+API_VERSION+"/application"; diff --git a/src/main/java/com/elevenpaths/latch/LatchResponse.java b/src/main/java/com/elevenpaths/latch/LatchResponse.java index 0ad945f..4cb0c2c 100644 --- a/src/main/java/com/elevenpaths/latch/LatchResponse.java +++ b/src/main/java/com/elevenpaths/latch/LatchResponse.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/com/elevenpaths/latch/LatchUser.java b/src/main/java/com/elevenpaths/latch/LatchUser.java index 664a939..60e2b1f 100755 --- a/src/main/java/com/elevenpaths/latch/LatchUser.java +++ b/src/main/java/com/elevenpaths/latch/LatchUser.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/src/test/java/ExampleTotp.java b/src/test/java/ExampleTotp.java new file mode 100644 index 0000000..364e33b --- /dev/null +++ b/src/test/java/ExampleTotp.java @@ -0,0 +1,72 @@ +/*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. + Copyright (C) 2024 Telefonica Innovación Digital + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/ + +import com.elevenpaths.latch.LatchApp; +import com.elevenpaths.latch.LatchResponse; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class ExampleTotp { + + public static String appId = ""; + public static String secretId = ""; + + public static String readInput(String msg) { + System.out.print(msg); + BufferedReader reader = new BufferedReader( + new InputStreamReader(System.in)); + try { + return reader.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static void createTotp() { + LatchApp latchApp = new LatchApp(appId, secretId); + String id = readInput("Enter the name displayed for the totp: "); + String commonName = readInput("Enter name "); + LatchResponse latchResponse = latchApp.createTotp(id,commonName); + if (latchResponse.hasErrors()) { + System.out.printf("Error creating the TOTP: %s%n", latchResponse.getError().getMessage()); + } else { + System.out.println("Successful totp creating"); + System.out.printf("Totp Id (Save it, you'll need it later): %s%n", latchResponse.getData().get("totpId")); + System.out.printf("QR (Scan the QR with the app, you can open it with any browse): %s%n", latchResponse.getData().get("qr")); + } + } + + public static void validateTotp() { + LatchApp latchApp = new LatchApp(appId, secretId); + String totpId = readInput("Enter the identifier for the totp: "); + String code = readInput("Enter the code generated "); + LatchResponse latchResponse = latchApp.validateTotp(totpId,code); + if (latchResponse.hasErrors()) { + System.out.printf("Error validating the TOTP: %s%n", latchResponse.getError().getMessage()); + } else { + System.out.println("Successful totp validating"); + } + } + + + public static void main(String[] args) { + createTotp(); + validateTotp(); + } +} diff --git a/src/test/java/TestExampleWeb3.java b/src/test/java/ExampleWeb3.java similarity index 98% rename from src/test/java/TestExampleWeb3.java rename to src/test/java/ExampleWeb3.java index a6606ff..2ae7838 100644 --- a/src/test/java/TestExampleWeb3.java +++ b/src/test/java/ExampleWeb3.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital + Copyright (C) 2024 Telefonica Innovación Digital This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,7 @@ import java.io.InputStreamReader; -public class TestExampleWeb3 { +public class ExampleWeb3 { public static String appId = ""; diff --git a/src/test/java/LatchTest.java b/src/test/java/LatchTest.java index 2ce27dd..58aaafa 100644 --- a/src/test/java/LatchTest.java +++ b/src/test/java/LatchTest.java @@ -1,5 +1,5 @@ /*Latch Java SDK - Set of reusable classes to allow developers integrate Latch on their applications. -Copyright (C) 2023 Telefonica Digital España S.L. + Copyright (C) 2024 Telefonica Innovación Digital España S.L. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -137,4 +137,26 @@ void test_latch_status() { String status_app = response.getData().get("operations").getAsJsonObject().get(this.app_id).getAsJsonObject().get("status").getAsString(); assertEquals("on",status_app); } + + @Test + @DisplayName("Test crud totp") + void test_crud_totp() { + LatchResponse response = this.latchApp.createTotp("TOTP_TEST","CommonName"); + String totpId = response.getData().get("totpId").getAsString(); + response = this.latchApp.getTotp(totpId); + assertEquals(totpId,response.getData().get("totpId").getAsString()); + response = this.latchApp.validateTotp(totpId,"123456"); + assertEquals("Invalid totp code",response.getError().getMessage()); + assertEquals(306,response.getError().getCode()); + response = this.latchApp.removeTotp(totpId); + assertNull(null, response.getError()); + } + + @Test + @DisplayName("Test check control status") + void test_control_status() { + LatchResponse response = this.latchApp.checkControlStatus("12345"); + assertEquals("Authorization control not found",response.getError().getMessage()); + assertEquals(1100,response.getError().getCode()); + } }