Skip to content

Commit

Permalink
Merge pull request #128 from PinguApps/95-feat-account-regenerate-mfa…
Browse files Browse the repository at this point in the history
…-recovery-codes

Implemented regenerate mfa recovery codes
  • Loading branch information
pingu2k4 authored Aug 10, 2024
2 parents ceabee2 + d3a2791 commit f49a309
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 8 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,14 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
```

## ⌛ Progress
<!-- ![27 / 288](https://progress-bar.dev/27/?scale=288&suffix=%20/%20288&width=500) -->
![Server & Client - 27 / 288](https://img.shields.io/badge/Server_&_Client-27%20%2F%20288-red?style=for-the-badge)
<!-- ![28 / 288](https://progress-bar.dev/28/?scale=288&suffix=%20/%20288&width=500) -->
![Server & Client - 28 / 288](https://img.shields.io/badge/Server_&_Client-28%20%2F%20288-red?style=for-the-badge)

<!-- ![2 / 195](https://progress-bar.dev/2/?scale=195&suffix=%20/%20195&width=300) -->
![Server - 2 / 195](https://img.shields.io/badge/Server-2%20%2F%20195-red?style=for-the-badge)

<!-- ![25 / 93](https://progress-bar.dev/25/?scale=93&suffix=%20/%2093&width=300) -->
![Client - 25 / 93](https://img.shields.io/badge/Client-25%20%2F%2093-red?style=for-the-badge)
<!-- ![26 / 93](https://progress-bar.dev/26/?scale=93&suffix=%20/%2093&width=300) -->
![Client - 26 / 93](https://img.shields.io/badge/Client-26%20%2F%2093-red?style=for-the-badge)

### 🔑 Key
| Icon | Definition |
Expand All @@ -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
<!-- ![27 / 52](https://progress-bar.dev/27/?scale=52&suffix=%20/%2052&width=120) -->
![Account - 27 / 52](https://img.shields.io/badge/Account-27%20%2F%2052-yellow?style=for-the-badge)
<!-- ![28 / 52](https://progress-bar.dev/28/?scale=52&suffix=%20/%2052&width=120) -->
![Account - 28 / 52](https://img.shields.io/badge/Account-28%20%2F%2052-yellow?style=for-the-badge)

| Endpoint | Client | Server |
|:-:|:-:|:-:|
Expand All @@ -176,7 +176,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
| [List Factors](https://appwrite.io/docs/references/1.5.x/client-rest/account#listMfaFactors) |||
| [Get MFA Recovery Codes](https://appwrite.io/docs/references/1.5.x/client-rest/account#getMfaRecoveryCodes) |||
| [Create MFA Recovery Codes](https://appwrite.io/docs/references/1.5.x/client-rest/account#createMfaRecoveryCodes) |||
| [Regenerate MFA Recovery Codes](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaRecoveryCodes) | ||
| [Regenerate MFA Recovery Codes](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaRecoveryCodes) | ||
| [Update Name](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateName) |||
| [Update Password](https://appwrite.io/docs/references/1.5.x/client-rest/account#updatePassword) |||
| [Update Phone](https://appwrite.io/docs/references/1.5.x/client-rest/account#updatePhone) |||
Expand Down
15 changes: 15 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/AccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -450,4 +450,19 @@ public async Task<AppwriteResult<MfaRecoveryCodes>> GetMfaRecoveryCodes()
return e.GetExceptionResponse<MfaRecoveryCodes>();
}
}

/// <inheritdoc/>
public async Task<AppwriteResult<MfaRecoveryCodes>> RegenerateMfaRecoveryCodes()
{
try
{
var result = await _accountApi.RegenerateMfaRecoveryCodes(GetCurrentSessionOrThrow());

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse<MfaRecoveryCodes>();
}
}
}
7 changes: 7 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,11 @@ public interface IAccountClient
/// </summary>
/// <returns>The Mfa Recovery Codes</returns>
Task<AppwriteResult<MfaRecoveryCodes>> GetMfaRecoveryCodes();

/// <summary>
/// Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using <see cref="CreateMfaRecoveryCodes"/> method. An OTP challenge is required to regenreate recovery codes
/// <para><see href="https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaRecoveryCodes">Appwrite Docs</see></para>
/// </summary>
/// <returns></returns>
Task<AppwriteResult<MfaRecoveryCodes>> RegenerateMfaRecoveryCodes();
}
3 changes: 3 additions & 0 deletions src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@ internal interface IAccountApi : IBaseApi

[Get("/account/mfa/recovery-codes")]
Task<IApiResponse<MfaRecoveryCodes>> GetMfaRecoveryCodes([Header("x-appwrite-session")] string session);

[Patch("/account/mfa/recovery-codes")]
Task<IApiResponse<MfaRecoveryCodes>> RegenerateMfaRecoveryCodes([Header("x-appwrite-session")] string session);
}
2 changes: 1 addition & 1 deletion src/PinguApps.Appwrite.Playground/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public async Task Run(string[] args)
{
_client.SetSession(_session);

var response = await _client.Account.GetMfaRecoveryCodes();
var response = await _client.Account.RegenerateMfaRecoveryCodes();

Console.WriteLine(response.Result.Match(
account => account.ToString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Net;
using PinguApps.Appwrite.Client.Clients;
using PinguApps.Appwrite.Shared.Tests;
using RichardSzalay.MockHttp;

namespace PinguApps.Appwrite.Client.Tests.Clients.Account;
public partial class AccountClientTests
{
[Fact]
public async Task RegenerateMfaRecoveryCodes_ShouldReturnSuccess_WhenApiCallSucceeds()
{
// Arrange
_mockHttp.Expect(HttpMethod.Patch, $"{Constants.Endpoint}/account/mfa/recovery-codes")
.ExpectedHeaders(true)
.Respond(Constants.AppJson, Constants.JwtResponse);

_appwriteClient.SetSession(Constants.Session);

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

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

[Fact]
public async Task RegenerateMfaRecoveryCodes_ShouldReturnError_WhenSessionIsNull()
{
// Act
var result = await _appwriteClient.Account.RegenerateMfaRecoveryCodes();

// Assert
Assert.True(result.IsError);
Assert.True(result.IsInternalError);
Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message);
}

[Fact]
public async Task RegenerateMfaRecoveryCodes_ShouldHandleException_WhenApiCallFails()
{
// Arrange
_mockHttp.Expect(HttpMethod.Patch, $"{Constants.Endpoint}/account/mfa/recovery-codes")
.ExpectedHeaders(true)
.Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError);

_appwriteClient.SetSession(Constants.Session);

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

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

[Fact]
public async Task RegenerateMfaRecoveryCodes_ShouldReturnErrorResponse_WhenExceptionOccurs()
{
// Arrange
_mockHttp.Expect(HttpMethod.Patch, $"{Constants.Endpoint}/account/mfa/recovery-codes")
.ExpectedHeaders(true)
.Throw(new HttpRequestException("An error occurred"));

_appwriteClient.SetSession(Constants.Session);

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

// Assert
Assert.False(result.Success);
Assert.True(result.IsInternalError);
Assert.Equal("An error occurred", result.Result.AsT2.Message);
}
}

0 comments on commit f49a309

Please sign in to comment.