-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add directory structure * Add builder for start verification request * Implement StartVerificationBuilder for SMS * Add StartSmsVerificationRequestTest * Implement serialization test for StartSmsVerificationRequest * Implement flow StartSmsVerification * Implement WhatsApp verification workflow * Refactor VerificationRequest * Implement Result.Merge * WIP - grouping requests to common builder * Implement generic builder, use PhoneNumber to enforce E.164 format validation * Simplify workflow parsing * Add WhatsAppInteractive workflow * Simplify test names * Implement Voice verification * Implement Email verification * Implement SilentAuth verification * Move Client to internal visibility, removing the Client property from the VonageClient instance (consumers can't use VerifyV2Client.cs yet) * Implement VerifyCode * Fixes from test run * Remove verify client * Unify all verification workflows * Handling fallback workflows * Remove test app * Code cleanup * Remove console app from file system * Fix merge conflicts * Fix issues in project file
- Loading branch information
Showing
49 changed files
with
2,347 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using Vonage.Common.Failures; | ||
using Vonage.Common.Test.Extensions; | ||
|
||
namespace Vonage.Common.Test; | ||
|
||
public class MailAddressTest | ||
{ | ||
[Theory] | ||
[InlineData("dummy-vonage.com")] | ||
[InlineData("123456789")] | ||
[InlineData("test@test@test.com")] | ||
public void Parse_ShouldReturnFailure_GivenAddressIsInvalid(string email) => | ||
MailAddress.Parse(email).Map(value => value.Address).Should() | ||
.BeFailure(ResultFailure.FromErrorMessage("Email is invalid.")); | ||
|
||
[Theory] | ||
[InlineData("dummy@vonage.com")] | ||
[InlineData("dum@von.co.uk")] | ||
public void Parse_ShouldReturnSuccess_GivenAddressIsValid(string email) => | ||
MailAddress.Parse(email).Map(value => value.Address).Should().BeSuccess(email); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using Vonage.Common.Failures; | ||
using Vonage.Common.Test.Extensions; | ||
|
||
namespace Vonage.Common.Test; | ||
|
||
public class PhoneNumberTest | ||
{ | ||
[Fact] | ||
public void NumberWithInternationalIndicator_ShouldReturnNumberWithPlusIndicator() => | ||
PhoneNumber.Parse("123456789").Map(number => number.NumberWithInternationalIndicator).Should() | ||
.BeSuccess("+123456789"); | ||
|
||
[Fact] | ||
public void Parse_ShouldReturnFailure_GivenNumberContainsNonDigits() => | ||
PhoneNumber.Parse("1234567abc123").Should() | ||
.BeFailure(ResultFailure.FromErrorMessage("Number can only contain digits.")); | ||
|
||
[Theory] | ||
[InlineData("")] | ||
[InlineData(" ")] | ||
[InlineData(null)] | ||
public void Parse_ShouldReturnFailure_GivenNumberIsNullOrWhitespace(string value) => | ||
PhoneNumber.Parse(value).Should() | ||
.BeFailure(ResultFailure.FromErrorMessage("Number cannot be null or whitespace.")); | ||
|
||
[Fact] | ||
public void Parse_ShouldReturnFailure_GivenNumberLengthIsHigherThan7() => | ||
PhoneNumber.Parse("123456").Should() | ||
.BeFailure(ResultFailure.FromErrorMessage("Number length cannot be lower than 7.")); | ||
|
||
[Fact] | ||
public void Parse_ShouldReturnFailure_GivenNumberLengthIsLowerThan15() => | ||
PhoneNumber.Parse("1234567890123456").Should() | ||
.BeFailure(ResultFailure.FromErrorMessage("Number length cannot be higher than 15.")); | ||
|
||
[Theory] | ||
[InlineData("1234567", "1234567")] | ||
[InlineData("123456789012345", "123456789012345")] | ||
public void Parse_ShouldReturnSuccess_GivenNumberIsValid(string value, string expected) => | ||
PhoneNumber.Parse(value).Map(number => number.Number).Should().BeSuccess(expected); | ||
|
||
[Theory] | ||
[InlineData("+1234567890", "1234567890")] | ||
[InlineData("+123456789012345", "123456789012345")] | ||
[InlineData("+++1234567890", "1234567890")] | ||
public void Parse_ShouldReturnSuccess_GivenNumberStartWithPlus(string value, string expected) => | ||
PhoneNumber.Parse(value).Map(number => number.Number).Should().BeSuccess(expected); | ||
|
||
[Fact] | ||
public void ToString_ShouldReturnNumber() => | ||
PhoneNumber.Parse("123456789").Map(number => number.ToString()).Should().BeSuccess("123456789"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System; | ||
using Vonage.Common.Failures; | ||
using Vonage.Common.Monads; | ||
|
||
namespace Vonage.Common; | ||
|
||
/// <summary> | ||
/// Represents an email address. | ||
/// </summary> | ||
public readonly struct MailAddress | ||
{ | ||
private const string InvalidEmail = "Email is invalid."; | ||
|
||
private MailAddress(string email) => this.Address = email; | ||
|
||
/// <summary> | ||
/// The mail address. | ||
/// </summary> | ||
public string Address { get; } | ||
|
||
/// <summary> | ||
/// Parses an email. | ||
/// </summary> | ||
/// <param name="email">The email.</param> | ||
/// <returns>Success or failure.</returns> | ||
public static Result<MailAddress> Parse(string email) | ||
{ | ||
try | ||
{ | ||
_ = new System.Net.Mail.MailAddress(email); | ||
return Result<MailAddress>.FromSuccess(new MailAddress(email)); | ||
} | ||
catch (Exception) | ||
{ | ||
return Result<MailAddress>.FromFailure(ResultFailure.FromErrorMessage(InvalidEmail)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using System.Linq; | ||
using Vonage.Common.Failures; | ||
using Vonage.Common.Monads; | ||
using Vonage.Common.Validation; | ||
|
||
namespace Vonage.Common; | ||
|
||
/// <summary> | ||
/// Represents a E.164 phone number. | ||
/// </summary> | ||
/// <remarks> | ||
/// See https://en.wikipedia.org/wiki/E.164. | ||
/// </remarks> | ||
public readonly struct PhoneNumber | ||
{ | ||
private const int MaximumLength = 15; | ||
private const int MinimumLength = 7; | ||
private const string InternationalIndicator = "+"; | ||
private const string MustContainDigits = "Number can only contain digits."; | ||
private const string NumberLengthIdentifier = "Number length"; | ||
|
||
private PhoneNumber(string number) => this.Number = number; | ||
|
||
/// <summary> | ||
/// Gets the phone number without international indicator. | ||
/// </summary> | ||
public string Number { get; } | ||
|
||
/// <summary> | ||
/// Gets the phone number with international indicator. | ||
/// </summary> | ||
public string NumberWithInternationalIndicator => string.Concat("+", this.Number); | ||
|
||
/// <summary> | ||
/// Parses the input into a PhoneNumber following E.164 specifications. | ||
/// </summary> | ||
/// <param name="number">The number.</param> | ||
/// <returns>Success if the input matches all requirements. Failure otherwise.</returns> | ||
public static Result<PhoneNumber> Parse(string number) => | ||
Result<PhoneNumber>.FromSuccess(new PhoneNumber(number)) | ||
.Bind(VerifyNumberNotEmpty) | ||
.Map(RemoveInternationalIndicator) | ||
.Bind(VerifyLengthHigherThanMinimum) | ||
.Bind(VerifyLengthLowerThanMaximum) | ||
.Bind(VerifyDigitsOnly); | ||
|
||
/// <inheritdoc /> | ||
public override string ToString() => this.Number; | ||
|
||
private static PhoneNumber RemoveInternationalIndicator(PhoneNumber value) => | ||
new(value.Number.Replace(InternationalIndicator, string.Empty)); | ||
|
||
private static Result<PhoneNumber> VerifyDigitsOnly( | ||
PhoneNumber request) => | ||
request.Number.Select(char.IsDigit).All(_ => _) | ||
? request | ||
: Result<PhoneNumber>.FromFailure(ResultFailure.FromErrorMessage(MustContainDigits)); | ||
|
||
private static Result<PhoneNumber> VerifyLengthHigherThanMinimum( | ||
PhoneNumber request) => | ||
InputValidation | ||
.VerifyHigherOrEqualThan(request, request.Number.Length, MinimumLength, NumberLengthIdentifier); | ||
|
||
private static Result<PhoneNumber> VerifyLengthLowerThanMaximum( | ||
PhoneNumber request) => | ||
InputValidation | ||
.VerifyLowerOrEqualThan(request, request.Number.Length, MaximumLength, NumberLengthIdentifier); | ||
|
||
private static Result<PhoneNumber> VerifyNumberNotEmpty(PhoneNumber number) => | ||
InputValidation | ||
.VerifyNotEmpty(number, number.Number, nameof(number.Number)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace Vonage.Common.Serialization; | ||
|
||
/// <summary> | ||
/// Represents a custom converter from Email to Json. | ||
/// </summary> | ||
public class EmailJsonConverter : JsonConverter<MailAddress> | ||
{ | ||
/// <inheritdoc /> | ||
public override MailAddress Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => | ||
MailAddress.Parse(reader.GetString()).IfFailure(default(MailAddress)); | ||
|
||
/// <inheritdoc /> | ||
public override void Write(Utf8JsonWriter writer, MailAddress value, JsonSerializerOptions options) => | ||
writer.WriteStringValue(value.Address); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace Vonage.Common.Serialization; | ||
|
||
/// <summary> | ||
/// Represents a custom converter from PhoneNumber to Json. | ||
/// </summary> | ||
public class PhoneNumberJsonConverter : JsonConverter<PhoneNumber> | ||
{ | ||
/// <inheritdoc /> | ||
public override PhoneNumber Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => | ||
PhoneNumber.Parse(reader.GetString()).IfFailure(default(PhoneNumber)); | ||
|
||
/// <inheritdoc /> | ||
public override void Write(Utf8JsonWriter writer, PhoneNumber value, JsonSerializerOptions options) => | ||
writer.WriteStringValue(value.Number); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
Vonage.Test.Unit/VerifyV2/StartVerification/Data/ShouldDeserialize200-response.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"request_id": "c11236f4-00bf-4b89-84ba-88b25df97315" | ||
} |
13 changes: 13 additions & 0 deletions
13
Vonage.Test.Unit/VerifyV2/StartVerification/Data/ShouldSerialize-request.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"locale": "es-es", | ||
"channel_timeout": 300, | ||
"client_ref": "my-personal-reference", | ||
"code_length": 4, | ||
"brand": "ACME, Inc", | ||
"workflow": [ | ||
{ | ||
"channel": "email", | ||
"to": "alice@company.com" | ||
} | ||
] | ||
} |
12 changes: 12 additions & 0 deletions
12
Vonage.Test.Unit/VerifyV2/StartVerification/Data/ShouldSerializeEmailWorkflow-request.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"locale": "en-us", | ||
"channel_timeout": 300, | ||
"code_length": 4, | ||
"brand": "ACME, Inc", | ||
"workflow": [ | ||
{ | ||
"channel": "email", | ||
"to": "alice@company.com" | ||
} | ||
] | ||
} |
20 changes: 20 additions & 0 deletions
20
...e.Test.Unit/VerifyV2/StartVerification/Data/ShouldSerializeFallbackWorkflows-request.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"locale": "en-us", | ||
"channel_timeout": 300, | ||
"code_length": 4, | ||
"brand": "ACME, Inc", | ||
"workflow": [ | ||
{ | ||
"channel": "whatsapp_interactive", | ||
"to": "447700900000" | ||
}, | ||
{ | ||
"channel": "whatsapp", | ||
"to": "447700900000" | ||
}, | ||
{ | ||
"channel": "voice", | ||
"to": "447700900000" | ||
} | ||
] | ||
} |
Oops, something went wrong.