diff --git a/README.md b/README.md index b41e2ba0..f8c40bc0 100644 --- a/README.md +++ b/README.md @@ -141,9 +141,9 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( ## ⌛ Progress -![Server & Client - 94 / 291](https://img.shields.io/badge/Server_&_Client-94%20%2F%20291-red?style=for-the-badge) +![Server & Client - 95 / 292](https://img.shields.io/badge/Server_&_Client-95%20%2F%20292-red?style=for-the-badge) -![Server - 50 / 201](https://img.shields.io/badge/Server-50%20%2F%20201-red?style=for-the-badge) +![Server - 51 / 202](https://img.shields.io/badge/Server-51%20%2F%20202-red?style=for-the-badge) ![Client - 44 / 90](https://img.shields.io/badge/Client-44%20%2F%2090-gold?style=for-the-badge) @@ -208,7 +208,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Create Phone Verification (Confirmation)](https://appwrite.io/docs/references/1.6.x/client-rest/account#updatePhoneVerification) | ✅ | ❌ | | ### Users -![Account - 39 / 41](https://img.shields.io/badge/Users-39%20%2F%2041-forestgreen?style=for-the-badge) +![Account - 40 / 42](https://img.shields.io/badge/Users-40%20%2F%2042-forestgreen?style=for-the-badge) | Endpoint | Client | Server | |:-:|:-:|:-:| @@ -251,7 +251,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Get User Target](https://appwrite.io/docs/references/1.6.x/server-rest/users#getTarget) | ❌ | ✅ | | [Update User Target](https://appwrite.io/docs/references/1.6.x/server-rest/users#updateTarget) | ❌ | ✅ | | [Delete User Target](https://appwrite.io/docs/references/1.6.x/server-rest/users#deleteTarget) | ❌ | ✅ | -| [Create Token](https://appwrite.io/docs/references/1.6.x/server-rest/users#createToken) | ❌ | ⬛ | +| [Create Token](https://appwrite.io/docs/references/1.6.x/server-rest/users#createToken) | ❌ | ✅ | | [Update Email Verification](https://appwrite.io/docs/references/1.6.x/server-rest/users#updateEmailVerification) | ❌ | ⬛ | | [Update Phone Verification](https://appwrite.io/docs/references/1.6.x/server-rest/users#updatePhoneVerification) | ❌ | ⬛ | diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 7e13d69e..72b0a082 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -17,14 +17,12 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new UpdateUserTargertRequest() + var request = new CreateTokenRequest() { - UserId = "664aac1a00113f82e620", - TargetId = "def", - Name = "New Name" + UserId = "664aac1a00113f82e620" }; - var response = await _server.Users.UpdateUserTarget(request); + var response = await _server.Users.CreateToken(request); Console.WriteLine(response.Result.Match( result => result.ToString(), diff --git a/src/PinguApps.Appwrite.Server/Clients/IUsersClient.cs b/src/PinguApps.Appwrite.Server/Clients/IUsersClient.cs index 80953898..d9ab29ee 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IUsersClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IUsersClient.cs @@ -326,7 +326,13 @@ public interface IUsersClient /// The request content /// The target Task> UpdateUserTarget(UpdateUserTargertRequest request); - [Obsolete("This method hasn't yet been implemented.", true)] + + /// + /// Returns a token with a secret key for creating a session. Use the user ID and secret and submit a request to the PUT /account/sessions/token endpoint to complete the login process + /// Appwrite Docs + /// + /// The request content + /// The token Task> CreateToken(CreateTokenRequest request); [Obsolete("This method hasn't yet been implemented.", true)] Task> UpdateEmailVerification(UpdateEmailVerificationRequest request); diff --git a/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs b/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs index 92f2bcda..7f5a90b2 100644 --- a/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs @@ -684,9 +684,22 @@ public async Task> UpdateUserTarget(UpdateUserTargertRequ } } - [ExcludeFromCodeCoverage] /// - public Task> CreateToken(CreateTokenRequest request) => throw new NotImplementedException(); + public async Task> CreateToken(CreateTokenRequest request) + { + try + { + request.Validate(true); + + var result = await _usersApi.CreateToken(request.UserId, request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Shared/Requests/Users/CreateTokenRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Users/CreateTokenRequest.cs index 682efd96..216b508c 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Users/CreateTokenRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Users/CreateTokenRequest.cs @@ -12,11 +12,13 @@ public class CreateTokenRequest : UserIdBaseRequest [JsonPropertyName("length")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public int? Length { get; set; } /// /// Token expiration period in seconds. The default expiration is 15 minutes /// [JsonPropertyName("expire")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public int? Expire { get; set; } } diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateToken.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateToken.cs new file mode 100644 index 00000000..17a10d47 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateToken.cs @@ -0,0 +1,75 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Users; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Users; +public partial class UsersClientTests +{ + [Fact] + public async Task CreateToken_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new CreateTokenRequest + { + UserId = IdUtils.GenerateUniqueId(), + // Add other properties as needed + }; + + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/users/{request.UserId}/tokens") + .ExpectedHeaders() + .Respond(Constants.AppJson, Constants.TokenResponse); + + // Act + var result = await _appwriteClient.Users.CreateToken(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task CreateToken_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new CreateTokenRequest + { + UserId = IdUtils.GenerateUniqueId(), + // Add other properties as needed + }; + + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/users/{request.UserId}/tokens") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError); + + // Act + var result = await _appwriteClient.Users.CreateToken(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task CreateToken_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new CreateTokenRequest + { + UserId = IdUtils.GenerateUniqueId(), + // Add other properties as needed + }; + + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/users/{request.UserId}/tokens") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Users.CreateToken(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +}