diff --git a/README.md b/README.md index 12cd05f7..37b5a60e 100644 --- a/README.md +++ b/README.md @@ -138,11 +138,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( ``` ## ⌛ Progress - -![Server & Client - 35 / 293](https://img.shields.io/badge/Server_&_Client-35%20%2F%20293-red?style=for-the-badge) + +![Server & Client - 36 / 293](https://img.shields.io/badge/Server_&_Client-36%20%2F%20293-red?style=for-the-badge) - -![Server - 2 / 200](https://img.shields.io/badge/Server-2%20%2F%20200-red?style=for-the-badge) + +![Server - 3 / 200](https://img.shields.io/badge/Server-3%20%2F%20200-red?style=for-the-badge) ![Client - 33 / 93](https://img.shields.io/badge/Client-33%20%2F%2093-red?style=for-the-badge) @@ -155,8 +155,8 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | ❌ | There is currently no intention to implement the endpoint for the given SDK type (client or server) | ### Account - -![Account - 35 / 57](https://img.shields.io/badge/Account-35%20%2F%2057-0af0?style=for-the-badge) + +![Account - 36 / 57](https://img.shields.io/badge/Account-36%20%2F%2057-gold?style=for-the-badge) | Endpoint | Client | Server | |:-:|:-:|:-:| @@ -186,7 +186,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Create Password Recovery (Confirmation)](https://appwrite.io/docs/references/1.6.x/client-rest/account#updateRecovery) | ✅ | ❌ | | [List Sessions](https://appwrite.io/docs/references/1.6.x/client-rest/account#listSessions) | ✅ | ❌ | | [Delete Sessions](https://appwrite.io/docs/references/1.6.x/client-rest/account#deleteSessions) | ✅ | ❌ | -| [Create Anonymous Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#createAnonymousSession) | ✅ | ⬛ | +| [Create Anonymous Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#createAnonymousSession) | ✅ | ✅ | | [Create Email Password Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#createEmailPasswordSession) | ✅ | ⬛ | | [Update Magic URL Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#updateMagicURLSession) | ⬛ | ⬛ | | [Create OAuth2 Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#createOAuth2Session) | ✅ | ❌ | diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 5b583fc4..4d6cb744 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -20,21 +20,20 @@ public async Task Run(string[] args) { //_client.SetSession(_session); - Console.WriteLine(_client.Session); - - var response = _client.Account.CreateOauth2Session(new Shared.Requests.CreateOauth2SessionRequest - { - Provider = "google", - SuccessUri = "https://localhost:5001/success", - FailureUri = "https://localhost:5001/fail", - Scopes = ["scope1", "scope2"] - }); + var response = await _server.Account.CreateAnonymousSession(); Console.WriteLine(response.Result.Match( account => account.ToString(), appwriteError => appwriteError.Message, internalERror => internalERror.Message)); - Console.WriteLine(_client.Session); + await Task.Delay(5000); + + var response2 = await _server.Account.CreateAnonymousSession(); + + Console.WriteLine(response2.Result.Match( + account => account.ToString(), + appwriteError => appwriteError.Message, + internalERror => internalERror.Message)); } } diff --git a/src/PinguApps.Appwrite.Server/Internals/IAccountApi.cs b/src/PinguApps.Appwrite.Server/Internals/IAccountApi.cs index d867d475..05c39776 100644 --- a/src/PinguApps.Appwrite.Server/Internals/IAccountApi.cs +++ b/src/PinguApps.Appwrite.Server/Internals/IAccountApi.cs @@ -11,4 +11,7 @@ internal interface IAccountApi : IBaseApi [Post("/account/tokens/email")] Task> CreateEmailToken(CreateEmailTokenRequest request); + + [Post("/account/sessions/anonymous")] + Task> CreateAnonymousSession(); } diff --git a/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs b/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs index 2e270d15..bddf9dc4 100644 --- a/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs +++ b/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs @@ -50,4 +50,19 @@ public async Task> CreateEmailToken(CreateEmailTokenReques return e.GetExceptionResponse(); } } + + /// + public async Task> CreateAnonymousSession() + { + try + { + var result = await _accountApi.CreateAnonymousSession(); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } } diff --git a/src/PinguApps.Appwrite.Server/Servers/IAccountServer.cs b/src/PinguApps.Appwrite.Server/Servers/IAccountServer.cs index d6212ed5..0da861b6 100644 --- a/src/PinguApps.Appwrite.Server/Servers/IAccountServer.cs +++ b/src/PinguApps.Appwrite.Server/Servers/IAccountServer.cs @@ -29,4 +29,11 @@ public interface IAccountServer /// The request content /// The token Task> CreateEmailToken(CreateEmailTokenRequest request); + + /// + /// Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to call or create an OAuth2 session + /// Appwrite Docs + /// + /// The Session + Task> CreateAnonymousSession(); } diff --git a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs index a5bad40c..f0a4e940 100644 --- a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Net.Http; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Server.Handlers; using PinguApps.Appwrite.Server.Internals; @@ -27,7 +28,14 @@ public static IServiceCollection AddAppwriteServer(this IServiceCollection servi services.AddRefitClient(refitSettings) .ConfigureHttpClient(x => x.BaseAddress = new Uri(endpoint)) - .AddHttpMessageHandler(); + .AddHttpMessageHandler() + .ConfigurePrimaryHttpMessageHandler((handler, sp) => + { + if (handler is HttpClientHandler clientHandler) + { + clientHandler.UseCookies = false; + } + }); services.AddSingleton(); services.AddSingleton(); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.CreateAnonymousSession.cs b/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.CreateAnonymousSession.cs new file mode 100644 index 00000000..8b86ff27 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.CreateAnonymousSession.cs @@ -0,0 +1,55 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Tests; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Servers.Account; +public partial class AccountServerTests +{ + [Fact] + public async Task CreateAnonymousSession_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/account/sessions/anonymous") + .ExpectedHeaders() + .Respond(Constants.AppJson, Constants.SessionResponse); + + // Act + var result = await _appwriteServer.Account.CreateAnonymousSession(); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task CreateAnonymousSession_ShouldHandleException_WhenApiCallFails() + { + // Arrange + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/account/sessions/anonymous") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError); + + // Act + var result = await _appwriteServer.Account.CreateAnonymousSession(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task CreateAnonymousSession_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/account/sessions/anonymous") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteServer.Account.CreateAnonymousSession(); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.cs b/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.cs index 48df8da0..46ec5b65 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountServerTests.cs @@ -25,18 +25,3 @@ public AccountServerTests() _appwriteServer = serviceProvider.GetRequiredService(); } } - -public static class AccountTestsExtensions -{ - public static MockedRequest ExpectedHeaders(this MockedRequest request) - { - return request - .WithHeaders("x-appwrite-project", Constants.ProjectId) - .WithHeaders("x-appwrite-key", Constants.ApiKey) - .WithHeaders("x-sdk-name", Constants.SdkName) - .WithHeaders("x-sdk-platform", "server") - .WithHeaders("x-sdk-language", Constants.SdkLanguage) - .WithHeaders("x-sdk-version", Constants.SdkVersion) - .WithHeaders("x-appwrite-response-format", Constants.AppwriteResponseFormat); - } -} diff --git a/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountTestsExtensions.cs b/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountTestsExtensions.cs new file mode 100644 index 00000000..19718699 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Servers/Account/AccountTestsExtensions.cs @@ -0,0 +1,19 @@ +using PinguApps.Appwrite.Shared.Tests; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Servers.Account; + +public static class AccountTestsExtensions +{ + public static MockedRequest ExpectedHeaders(this MockedRequest request) + { + return request + .WithHeaders("x-appwrite-project", Constants.ProjectId) + .WithHeaders("x-appwrite-key", Constants.ApiKey) + .WithHeaders("x-sdk-name", Constants.SdkName) + .WithHeaders("x-sdk-platform", "server") + .WithHeaders("x-sdk-language", Constants.SdkLanguage) + .WithHeaders("x-sdk-version", Constants.SdkVersion) + .WithHeaders("x-appwrite-response-format", Constants.AppwriteResponseFormat); + } +}