Skip to content

Commit

Permalink
Merge pull request #81 from PinguApps/47create-email-verification-con…
Browse files Browse the repository at this point in the history
…firmation

create email verification confirmation
  • Loading branch information
pingu2k4 authored Aug 4, 2024
2 parents 43b30ec + 4ce9363 commit b299594
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 5 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(

## ⌛ Progress
### Server & Client
![15 / 288](https://progress-bar.dev/15/?scale=288&suffix=%20/%20288&width=500)
![16 / 288](https://progress-bar.dev/16/?scale=288&suffix=%20/%20288&width=500)
### Server Only
![2 / 195](https://progress-bar.dev/2/?scale=195&suffix=%20/%20195&width=300)
### Client Only
![13 / 93](https://progress-bar.dev/13/?scale=93&suffix=%20/%2093&width=300)
![14 / 93](https://progress-bar.dev/14/?scale=93&suffix=%20/%2093&width=300)

### 🔑 Key
| Icon | Definition |
Expand All @@ -153,7 +153,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
|| There is currently no intention to implement the endpoint for the given SDK type (client or server) |

### Account
![15 / 52](https://progress-bar.dev/15/?scale=52&suffix=%20/%2052&width=120)
![16 / 52](https://progress-bar.dev/16/?scale=52&suffix=%20/%2052&width=120)

| Endpoint | Client | Server |
|:-:|:-:|:-:|
Expand Down Expand Up @@ -201,7 +201,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
| [Create OAuth2 Token](https://appwrite.io/docs/references/1.5.x/client-rest/account#createOAuth2Token) |||
| [Create Phone Token](https://appwrite.io/docs/references/1.5.x/client-rest/account#createPhoneToken) |||
| [Create Email Verification](https://appwrite.io/docs/references/1.5.x/client-rest/account#createVerification) |||
| [Create Email Verification (Confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateVerification) | ||
| [Create Email Verification (Confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateVerification) | ||
| [Create Phone Verification](https://appwrite.io/docs/references/1.5.x/client-rest/account#createPhoneVerification) |||
| [Create Phone Verification (Confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updatePhoneVerification) |||

Expand Down
17 changes: 17 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/AccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,21 @@ public async Task<AppwriteResult<Token>> CreateEmailVerification(CreateEmailVeri
return e.GetExceptionResponse<Token>();
}
}

/// <inheritdoc/>
public async Task<AppwriteResult<Token>> CreateEmailVerificationConfirmation(CreateEmailVerificationConfirmationRequest request)
{
try
{
request.Validate(true);

var result = await _accountApi.CreateEmailVerificationConfirmation(request);

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse<Token>();
}
}
}
8 changes: 8 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,12 @@ public interface IAccountClient
/// <param name="request">The request content</param>
/// <returns>The token</returns>
Task<AppwriteResult<Token>> CreateEmailVerification(CreateEmailVerificationRequest request);

/// <summary>
/// Use this endpoint to complete the user email verification process. Use both the userId and secret parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.
/// <para><see href="https://appwrite.io/docs/references/1.5.x/client-rest/account#updateVerification">Appwrite Docs</see></para>
/// </summary>
/// <param name="request">The request content</param>
/// <returns>The token</returns>
Task<AppwriteResult<Token>> CreateEmailVerificationConfirmation(CreateEmailVerificationConfirmationRequest request);
}
5 changes: 4 additions & 1 deletion src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ internal interface IAccountApi : IBaseApi
[Patch("/account/sessions/{sessionId}")]
Task<IApiResponse<Session>> UpdateSession([Header("x-appwrite-session")] string? session, string sessionId);

[Post(("/account/verification"))]
[Post("/account/verification")]
Task<IApiResponse<Token>> CreateEmailVerification([Header("x-appwrite-session")] string? session, CreateEmailVerificationRequest request);

[Put("/account/verification")]
Task<IApiResponse<Token>> CreateEmailVerificationConfirmation(CreateEmailVerificationConfirmationRequest request);
}
8 changes: 8 additions & 0 deletions src/PinguApps.Appwrite.Playground/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ public async Task Run(string[] args)

var response = await _client.Account.CreateEmailVerification(request);

//var request = new CreateEmailVerificationConfirmationRequest
//{
// Secret = "secret",
// UserId = "userId"
//};

//var response = await _client.Account.CreateEmailVerificationConfirmation(request);

Console.WriteLine(response.Result.Match(
account => account.ToString(),
appwriteError => appwriteError.Message,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
using PinguApps.Appwrite.Shared.Requests.Validators;

namespace PinguApps.Appwrite.Shared.Requests;
public class CreateEmailVerificationConfirmationRequest : BaseRequest<CreateEmailVerificationConfirmationRequest, CreateEmailVerificationConfirmationRequestValidator>
{
/// <summary>
/// User ID.
/// </summary>
[JsonPropertyName("userId")]
public string UserId { get; set; } = string.Empty;

/// <summary>
/// Valid verification token.
/// </summary>
[JsonPropertyName("secret")]
public string Secret { get; set; } = string.Empty;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using FluentValidation;

namespace PinguApps.Appwrite.Shared.Requests.Validators;
public class CreateEmailVerificationConfirmationRequestValidator : AbstractValidator<CreateEmailVerificationConfirmationRequest>
{
public CreateEmailVerificationConfirmationRequestValidator()
{
RuleFor(x => x.UserId).NotEmpty().Matches("^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$");
RuleFor(x => x.Secret).NotEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Net;
using PinguApps.Appwrite.Shared.Requests;
using PinguApps.Appwrite.Shared.Tests;
using RichardSzalay.MockHttp;

namespace PinguApps.Appwrite.Client.Tests.Clients.Account;
public partial class AccountClientTests
{
[Fact]
public async Task CreateEmailVerificationConfirmation_ShouldReturnSuccess_WhenApiCallSucceeds()
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest()
{
UserId = "123456",
Secret = "654321"
};

_mockHttp.Expect(HttpMethod.Put, $"{Constants.Endpoint}/account/verification")
.ExpectedHeaders()
.WithJsonContent(request)
.Respond(Constants.AppJson, Constants.TokenResponse);

// Act
var result = await _appwriteClient.Account.CreateEmailVerificationConfirmation(request);

// Assert
Assert.True(result.Success);
}

[Fact]
public async Task CreateEmailVerificationConfirmation_ShouldHandleException_WhenApiCallFails()
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest()
{
UserId = "123456",
Secret = "654321"
};

_mockHttp.Expect(HttpMethod.Put, $"{Constants.Endpoint}/account/verification")
.ExpectedHeaders()
.WithJsonContent(request)
.Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError);

// Act
var result = await _appwriteClient.Account.CreateEmailVerificationConfirmation(request);

// Assert
Assert.True(result.IsError);
Assert.True(result.IsAppwriteError);
}

[Fact]
public async Task CreateEmailVerificationConfirmation_ShouldReturnErrorResponse_WhenExceptionOccurs()
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest()
{
UserId = "123456",
Secret = "654321"
};

_mockHttp.Expect(HttpMethod.Put, $"{Constants.Endpoint}/account/verification")
.ExpectedHeaders()
.WithJsonContent(request)
.Throw(new HttpRequestException("An error occurred"));

// Act
var result = await _appwriteClient.Account.CreateEmailVerificationConfirmation(request);

// Assert
Assert.False(result.Success);
Assert.True(result.IsInternalError);
Assert.Equal("An error occurred", result.Result.AsT2.Message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using FluentValidation;
using PinguApps.Appwrite.Shared.Requests;

namespace PinguApps.Appwrite.Shared.Tests.Requests;
public class CreateEmailVerificationRequestConfirmationTests
{
[Fact]
public void Constructor_InitializesWithExpectedValues()
{
// Arrange & Act
var request = new CreateEmailVerificationConfirmationRequest();

// Assert
Assert.Equal(string.Empty, request.UserId);
Assert.Equal(string.Empty, request.Secret);
}

[Fact]
public void Properties_CanBeSet()
{
var userId = "123456";
var secret = "[email protected]";

// Arrange
var request = new CreateEmailVerificationConfirmationRequest();

// Act
request.UserId = userId;
request.Secret = secret;

// Assert
Assert.Equal(userId, request.UserId);
Assert.Equal(secret, request.Secret);
}

[Fact]
public void IsValid_WithValidData_ReturnsTrue()
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest
{
UserId = "123456",
Secret = "654321"
};

// Act
var isValid = request.IsValid();

// Assert
Assert.True(isValid);
}

[Theory]
[InlineData("badChar^", "654321")]
[InlineData(".bad", "654321")]
[InlineData("_bad", "654321")]
[InlineData("-bad", "654321")]
[InlineData("", "654321")]
[InlineData("1234567890123456789012345678901234567", "654321")]
[InlineData("123456", "")]
public void IsValid_WithInvalidData_ReturnsFalse(string userId, string secret)
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest
{
UserId = userId,
Secret = secret
};

// Act
var isValid = request.IsValid();

// Assert
Assert.False(isValid);
}

[Fact]
public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure()
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest
{
UserId = ".badChar^",
Secret = ""
};

// Assert
Assert.Throws<ValidationException>(() => request.Validate(true));
}

[Fact]
public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure()
{
// Arrange
var request = new CreateEmailVerificationConfirmationRequest
{
UserId = ".badChar^",
Secret = ""
};

// Act
var result = request.Validate(false);

// Assert
Assert.False(result.IsValid);
}
}

0 comments on commit b299594

Please sign in to comment.