Skip to content

Commit

Permalink
fix: Add missing fields & Locales for Verify v2 (#484)
Browse files Browse the repository at this point in the history
* fix: add ja-jp verify2 locale

* fix: Ensure silent_auth is first workflow

* feat: Synchronous Silent Auth endpoint

* feat: Add missing Silent Auth fields

* fix: Move sandbox field to SilentAuthWorkflow

* fix: Remove Silent Auth check

* fix: Add missing Locales for Verify v2
  • Loading branch information
SMadani authored Oct 17, 2023
1 parent e399285 commit 4874330
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 55 deletions.
22 changes: 18 additions & 4 deletions src/main/java/com/vonage/client/DynamicEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ public Builder<T, R> pathGetter(BiFunction<DynamicEndpoint<T, R>, T, String> pat
return this;
}

public Builder<T, R> addAuthMethodIfTrue(boolean condition, Class<? extends AuthMethod> primary, Class<? extends AuthMethod>... others) {
if (condition) {
authMethod(primary, others);
}
return this;
}

public Builder<T, R> authMethod(Class<? extends AuthMethod> primary, Class<? extends AuthMethod>... others) {
authMethods = new ArrayList<>(2);
authMethods.add(Objects.requireNonNull(primary, "Primary auth method cannot be null"));
Expand Down Expand Up @@ -167,14 +174,21 @@ static RequestBuilder createRequestBuilderFromRequestMethod(HttpMethod requestMe

@Override
protected final Class<?>[] getAcceptableAuthMethods() {
return authMethods.toArray(new Class<?>[0]);
Class<?>[] emptyArray = new Class<?>[0];
return authMethods != null ? authMethods.toArray(emptyArray) : emptyArray;
}

@Override
protected final RequestBuilder applyAuth(RequestBuilder request) throws VonageClientException {
return applyBasicAuth ?
getAuthMethod(getAcceptableAuthMethods()).applyAsBasicAuth(request) :
super.applyAuth(request);
if (authMethods == null || authMethods.isEmpty()) {
return request;
}
else if (applyBasicAuth) {
return getAuthMethod(getAcceptableAuthMethods()).applyAsBasicAuth(request);
}
else {
return super.applyAuth(request);
}
}

@Override
Expand Down
26 changes: 25 additions & 1 deletion src/main/java/com/vonage/client/verify2/Locale.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,31 @@ public enum Locale {
HINDI_INDIA("hi-in"),
PORTUGUESE_BRAZIL("pt-br"),
PORTUGUESE_PORTUGAL("pt-pt"),
INDONESIAN_INDONESIA("id-id");
INDONESIAN_INDONESIA("id-id"),
JAPANESE_JAPAN("ja-jp"),
HEBREW_ISRAEL("he-il"),
YUE_CHINESE_CHINA("yue-cn"),
ARABIC_ARABIAN_PENINSULA("ar-xa"),
CZECH_CZECH_REPUBLIC("cs-cz"),
WELSH_UK("cy-gb"),
GREEK_GREECE("el-gr"),
ENGLISH_AUSTRALIA("en-au"),
ENGLISH_INDIA("en-in"),
FINNISH_FINLAND("fi-fi"),
FILIPINO_PHILIPPINES("fil-ph"),
FRENCH_CANADA("fr-ca"),
HUNGARIAN_HUNGARY("hu-hu"),
ICELANDIC_ICELAND("is-is"),
NORWEGIAN_BOKMAL_NORWAY("nb-no"),
DUTCH_NETHERLANDS("nl-nl"),
POLISH_POLAND("pl-pl"),
ROMANIAN_ROMANIA("ro-ro"),
SWEDISH_SWEDEN("sv-se"),
THAI_THAILAND("th-th"),
TURKISH_TURKEY("tr-tr"),
VIETNAMESE_VIETNAM("vi-vn"),
CHINESE_CHINA("zh-cn"),
CHINESE_TAIWAN("zh-tw");

private final String code;

Expand Down
30 changes: 29 additions & 1 deletion src/main/java/com/vonage/client/verify2/SilentAuthWorkflow.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.vonage.client.verify2;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.vonage.client.common.E164;

/**
* Defines properties for mobile network-based authentication. See the
Expand All @@ -24,13 +26,39 @@
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public final class SilentAuthWorkflow extends Workflow {
private Boolean sandbox;

/**
* Constructs a new Silent Auth verification workflow.
*
* @param to The number to registered to the device on the network to authenticate.
*/
public SilentAuthWorkflow(String to) {
super(Channel.SILENT_AUTH, to);
super(Channel.SILENT_AUTH, new E164(to).toString());
}

/**
* Constructs a new Silent Auth verification workflow.
*
* @param to The number to registered to the device on the network to authenticate.
* @param sandbox Whether the Vonage Sandbox should be used (for testing purposes).
*
* @since 7.10.0
*/
public SilentAuthWorkflow(String to, boolean sandbox) {
this(to);
this.sandbox = sandbox;
}

/**
* Optional parameter if using the Vonage Sandbox to test Silent Auth integrations.
*
* @return Whether the Vonage Sandbox will be used, or {@code null} if not specified (the default).
*
* @since 7.10.0
*/
@JsonProperty("sandbox")
public Boolean getSandbox() {
return sandbox;
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/vonage/client/verify2/SmsWorkflow.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.vonage.client.common.E164;

/**
* Defines workflow properties for sending a verification code to a user via SMS.
Expand All @@ -42,7 +43,7 @@ public SmsWorkflow(String to) {
* @param appHash Android Application Hash Key for automatic code detection on a user's device.
*/
public SmsWorkflow(String to, String appHash) {
super(Channel.SMS, to);
super(Channel.SMS, new E164(to).toString());
if ((this.appHash = appHash) != null && appHash.length() != 11) {
throw new IllegalArgumentException("Android app hash must be 11 characters.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public class VerificationRequest implements Jsonable {
if (code != null && codeLength != null && code.length() != codeLength) {
throw new IllegalStateException("Code '"+code+"' is not "+codeLength+" characters.");
}
if (workflows.stream().anyMatch(SilentAuthWorkflow.class::isInstance)) {
if (!(workflows.get(0) instanceof SilentAuthWorkflow)) {
throw new IllegalStateException("Silent Auth must be the first workflow.");
}
}
}

/**
Expand Down Expand Up @@ -312,6 +317,7 @@ public Builder clientRef(String clientRef) {
}

/**
* (OPTIONAL)
* Set this parameter to {@code false} to force through the request even if it's
* blocked by the network's fraud protection. Refer to
* <a href=https://developer.vonage.com/en/verify/verify-v2/guides/v2-anti-fraud>
Expand Down
29 changes: 18 additions & 11 deletions src/main/java/com/vonage/client/verify2/VerificationResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vonage.client.Jsonable;
import com.vonage.client.VonageResponseParseException;
import java.io.IOException;
import java.net.URI;
import java.util.UUID;

/**
Expand All @@ -29,6 +27,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class VerificationResponse implements Jsonable {
protected UUID requestId;
protected URI checkUrl;

/**
* Protected to prevent users from explicitly creating this object.
Expand All @@ -46,9 +45,21 @@ public UUID getRequestId() {
return requestId;
}

/**
* URL for Silent Auth Verify workflow completion (only present if using Silent Auth).
*
* @return The URL to check for Silent Authentication, or {@code null} if not applicable.
*
* @since 7.10.0
*/
@JsonProperty("check_url")
public URI getCheckUrl() {
return checkUrl;
}

@Override
public String toString() {
return getClass().getSimpleName()+" {requestId='"+requestId+"'}";
return getClass().getSimpleName() + "{requestId=" + requestId + ", checkUrl=" + checkUrl + '}';
}

/**
Expand All @@ -58,12 +69,8 @@ public String toString() {
* @return An instance of this class with the fields populated, if present.
*/
public static VerificationResponse fromJson(String json) {
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, VerificationResponse.class);
}
catch (IOException ex) {
throw new VonageResponseParseException("Failed to produce VerificationResponse from json.", ex);
}
VerificationResponse response = new VerificationResponse();
response.updateFromJson(json);
return response;
}
}
18 changes: 11 additions & 7 deletions src/main/java/com/vonage/client/verify2/Verify2Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ final class Endpoint<T, R> extends DynamicEndpoint<T, R> {
super(DynamicEndpoint.<T, R> builder(type)
.responseExceptionType(VerifyResponseException.class)
.wrapper(wrapper).requestMethod(method)
.authMethod(JWTAuthMethod.class, TokenAuthMethod.class)
.addAuthMethodIfTrue(method != HttpMethod.GET, JWTAuthMethod.class, TokenAuthMethod.class)
.pathGetter((de, req) -> {
String base = de.getHttpWrapper().getHttpConfig().getVersionedApiBaseUri("v2") + "/verify";
return pathGetter != null ? base + "/" + pathGetter.apply(req) : base;
Expand All @@ -59,6 +59,10 @@ final class Endpoint<T, R> extends DynamicEndpoint<T, R> {
cancel = new Endpoint<>(UUID::toString, HttpMethod.DELETE);
}

private UUID validateRequestId(UUID requestId) {
return Objects.requireNonNull(requestId, "Request ID is required.");
}

/**
* Request a verification be sent to a user. This is the first step in the verification process.
*
Expand Down Expand Up @@ -87,7 +91,7 @@ final class Endpoint<T, R> extends DynamicEndpoint<T, R> {
public VerificationResponse sendVerification(VerificationRequest request) {
if (request.isCodeless() && !hasJwtAuthMethod) {
throw new IllegalStateException(
"Codeless verification requires an application ID to be set in order to use webhooks."
"Codeless verification requires an application ID to be set in order to use webhooks."
);
}
return verifyUser.execute(Objects.requireNonNull(request));
Expand All @@ -112,9 +116,10 @@ public VerificationResponse sendVerification(VerificationRequest request) {
* @throws VerifyResponseException If the code was invalid, or any other error.
*/
public void checkVerificationCode(UUID requestId, String code) {
Objects.requireNonNull(requestId, "Request ID is required.");
Objects.requireNonNull(code, "Code is required.");
verifyRequest.execute(new VerifyCodeRequestWrapper(requestId.toString(), code));
verifyRequest.execute(new VerifyCodeRequestWrapper(
validateRequestId(requestId).toString(),
Objects.requireNonNull(code, "Code is required.")
));
}

/**
Expand All @@ -127,7 +132,6 @@ public void checkVerificationCode(UUID requestId, String code) {
* @throws VerifyResponseException If the request ID was not found or it has been verified already.
*/
public void cancelVerification(UUID requestId) {
Objects.requireNonNull(requestId, "Request ID is required.");
cancel.execute(requestId);
cancel.execute(validateRequestId(requestId));
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/vonage/client/verify2/VoiceWorkflow.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.vonage.client.verify2;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.vonage.client.common.E164;

/**
* Defines workflow properties for sending a verification code to a user over a voice call.
Expand All @@ -29,6 +30,6 @@ public final class VoiceWorkflow extends Workflow {
* @param to The number to call, in E.164 format.
*/
public VoiceWorkflow(String to) {
super(Channel.VOICE, to);
super(Channel.VOICE, new E164(to).toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.vonage.client.verify2;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.vonage.client.common.E164;

/**
* Defines properties for sending a verification code to a user over WhatsApp
Expand All @@ -35,6 +36,6 @@ public final class WhatsappCodelessWorkflow extends Workflow {
* @param to The number to send the verification prompt to, in E.164 format.
*/
public WhatsappCodelessWorkflow(String to) {
super(Channel.WHATSAPP_INTERACTIVE, to);
super(Channel.WHATSAPP_INTERACTIVE, new E164(to).toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.vonage.client.common.E164;

/**
* Defines properties for sending a verification code to a user over a WhatsApp message.
Expand Down Expand Up @@ -45,7 +46,7 @@ public WhatsappWorkflow(String to) {
* Note that you will need to get in touch with the Vonage sales team to enable use of the field.
*/
public WhatsappWorkflow(String to, String from) {
super(Channel.WHATSAPP, to, from);
super(Channel.WHATSAPP, new E164(to).toString(), from);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/com/vonage/client/BugRepro.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/
public class BugRepro {
public static void main(String[] args) throws Throwable {
String TO_NUMBER = System.getenv("TO_NUMBER");

VonageClient client = VonageClient.builder()
.httpConfig(HttpConfig.builder().timeoutMillis(12_000).build())
.apiKey(System.getenv("VONAGE_API_KEY"))
Expand Down
Loading

0 comments on commit 4874330

Please sign in to comment.