From d588fb400b2f37bb666f4cc965c4c42fed19f8d4 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 8 Oct 2024 17:49:57 +0100 Subject: [PATCH 1/3] implemented create user with scrypt modified password --- src/PinguApps.Appwrite.Playground/App.cs | 10 ++++------ .../Clients/IUsersClient.cs | 8 +++++++- .../Clients/UsersClient.cs | 17 +++++++++++++++-- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 5194cb24..452e697e 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -17,18 +17,16 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new CreateUserWithScryptPasswordRequest() + var request = new CreateUserWithScryptModifiedPasswordRequest() { Email = "pingu@example.com", Password = "dbb97714c09bad417bb51288abd2c049c557e5e617839a7bc8c615492db859b57624366de72f04b9d4c3e6452a497a67a36f1afcc481d6d69f6da9e5f03598d7", PasswordSalt = "MySuperSalt", - PasswordCpu = 16384, - PasswordMemory = 8, - PasswordParallel = 1, - PasswordLength = 64 + PasswordSaltSeparator = ";", + PasswordSignerKey = "MySuperSignerKey" }; - var response = await _server.Users.CreateUserWithScryptPassword(request); + var response = await _server.Users.CreateUserWithScryptModifiedPassword(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 57589562..59d3a6de 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IUsersClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IUsersClient.cs @@ -84,7 +84,13 @@ public interface IUsersClient /// The request content /// The user Task> CreateUserWithScryptPassword(CreateUserWithScryptPasswordRequest request); - [Obsolete("This method hasn't yet been implemented.", true)] + + /// + /// Create a new user. Password provided must be hashed with the Scrypt Modified algorithm. Use to create users with a plain text password. + /// Appwrite Docs + /// + /// The request content + /// The user Task> CreateUserWithScryptModifiedPassword(CreateUserWithScryptModifiedPasswordRequest request); [Obsolete("This method hasn't yet been implemented.", true)] Task> CreateUserWithShaPassword(CreateUserWithShaPasswordRequest request); diff --git a/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs b/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs index e2b2c5b8..9a9b6f7c 100644 --- a/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/UsersClient.cs @@ -179,9 +179,22 @@ public async Task> CreateUserWithScryptPassword(CreateUserW } } - [ExcludeFromCodeCoverage] /// - public Task> CreateUserWithScryptModifiedPassword(CreateUserWithScryptModifiedPasswordRequest request) => throw new NotImplementedException(); + public async Task> CreateUserWithScryptModifiedPassword(CreateUserWithScryptModifiedPasswordRequest request) + { + try + { + request.Validate(true); + + var result = await _usersApi.CreateUserWithScryptModifiedPassword(request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// From 668f705a42083efb2eb1e8ea1354168d6bc39883 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 8 Oct 2024 17:57:07 +0100 Subject: [PATCH 2/3] added tests for create user with scrypt modified --- ...ts.CreateUserWithScryptModifiedPassword.cs | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs new file mode 100644 index 00000000..af38cbfc --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs @@ -0,0 +1,86 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Users; +using PinguApps.Appwrite.Shared.Tests; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Users; +public partial class UsersClientTests +{ + [Fact] + public async Task CreateUserWithScryptModifiedPassword_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new CreateUserWithScryptModifiedPasswordRequest + { + Email = "test@example.com", + Password = "password123", + PasswordSalt = "MySalt", + PasswordSaltSeparator = "Separator", + PasswordSignerKey = "SignerKey" + }; + + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/users/scrypt-modified") + .WithJsonContent(request) + .ExpectedHeaders() + .Respond(Constants.AppJson, Constants.UserResponse); + + // Act + var result = await _appwriteClient.Users.CreateUserWithScryptModifiedPassword(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task CreateUserWithScryptModifiedPassword_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new CreateUserWithScryptModifiedPasswordRequest + { + Email = "test@example.com", + Password = "password123", + PasswordSalt = "MySalt", + PasswordSaltSeparator = "Separator", + PasswordSignerKey = "SignerKey" + }; + + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/users/scrypt-modified") + .WithJsonContent(request) + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError); + + // Act + var result = await _appwriteClient.Users.CreateUserWithScryptModifiedPassword(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task CreateUserWithScryptModifiedPassword_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new CreateUserWithScryptModifiedPasswordRequest + { + Email = "test@example.com", + Password = "password123", + PasswordSalt = "MySalt", + PasswordSaltSeparator = "Separator", + PasswordSignerKey = "SignerKey" + }; + + _mockHttp.Expect(HttpMethod.Post, $"{Constants.Endpoint}/users/scrypt-modified") + .WithJsonContent(request) + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Users.CreateUserWithScryptModifiedPassword(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From 3f10caa42be930a191d0e34ca0f198c01b1bd3cf Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 8 Oct 2024 17:58:18 +0100 Subject: [PATCH 3/3] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index da36b923..93732495 100644 --- a/README.md +++ b/README.md @@ -140,9 +140,9 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( ``` ## ⌛ Progress -![Server & Client - 64 / 291](https://img.shields.io/badge/Server_&_Client-64%20%2F%20291-red?style=for-the-badge) +![Server & Client - 65 / 291](https://img.shields.io/badge/Server_&_Client-65%20%2F%20291-red?style=for-the-badge) -![Server - 20 / 201](https://img.shields.io/badge/Server-20%20%2F%20201-red?style=for-the-badge) +![Server - 21 / 201](https://img.shields.io/badge/Server-21%20%2F%20201-red?style=for-the-badge) ![Client - 44 / 90](https://img.shields.io/badge/Client-44%20%2F%2090-gold?style=for-the-badge) @@ -207,7 +207,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Create Phone Verification (Confirmation)](https://appwrite.io/docs/references/1.6.x/client-rest/account#updatePhoneVerification) | ✅ | ❌ | | ### Users -![Account - 9 / 41](https://img.shields.io/badge/Users-9%20%2F%2041-red?style=for-the-badge) +![Account - 10 / 41](https://img.shields.io/badge/Users-10%20%2F%2041-red?style=for-the-badge) | Endpoint | Client | Server | |:-:|:-:|:-:| @@ -220,7 +220,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Create User with MD5 Password](https://appwrite.io/docs/references/1.6.x/server-rest/users#createMD5User) | ❌ | ✅ | | [Create User with PHPass Password](https://appwrite.io/docs/references/1.6.x/server-rest/users#createPHPassUser) | ❌ | ✅ | | [Create User with Scrypt Password](https://appwrite.io/docs/references/1.6.x/server-rest/users#createScryptUser) | ❌ | ✅ | -| [Create User with Scrypt Modified Password](https://appwrite.io/docs/references/1.6.x/server-rest/users#createScryptModifiedUser) | ❌ | ⬛ | +| [Create User with Scrypt Modified Password](https://appwrite.io/docs/references/1.6.x/server-rest/users#createScryptModifiedUser) | ❌ | ✅ | | [Create User with SHA Password](https://appwrite.io/docs/references/1.6.x/server-rest/users#createSHAUser) | ❌ | ⬛ | | [Get User](https://appwrite.io/docs/references/1.6.x/server-rest/users#get) | ❌ | ⬛ | | [Delete User](https://appwrite.io/docs/references/1.6.x/server-rest/users#delete) | ❌ | ⬛ |