Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented create 2fa challenge confirmation #124

Merged
merged 7 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
<!-- ![23 / 288](https://progress-bar.dev/23/?scale=288&suffix=%20/%20288&width=500) -->
![Server & Client - 23 / 288](https://img.shields.io/badge/Server_&_Client-23%20%2F%20288-red?style=for-the-badge)
<!-- ![24 / 288](https://progress-bar.dev/24/?scale=288&suffix=%20/%20288&width=500) -->
![Server & Client - 24 / 288](https://img.shields.io/badge/Server_&_Client-24%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)

<!-- ![21 / 93](https://progress-bar.dev/21/?scale=93&suffix=%20/%2093&width=300) -->
![Client - 21 / 93](https://img.shields.io/badge/Client-21%20%2F%2093-red?style=for-the-badge)
<!-- ![22 / 93](https://progress-bar.dev/22/?scale=93&suffix=%20/%2093&width=300) -->
![Client - 22 / 93](https://img.shields.io/badge/Client-22%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
<!-- ![23 / 52](https://progress-bar.dev/23/?scale=52&suffix=%20/%2052&width=120) -->
![Account - 23 / 52](https://img.shields.io/badge/Account-23%20%2F%2052-yellow?style=for-the-badge)
<!-- ![24 / 52](https://progress-bar.dev/24/?scale=52&suffix=%20/%2052&width=120) -->
![Account - 24 / 52](https://img.shields.io/badge/Account-24%20%2F%2052-yellow?style=for-the-badge)

| Endpoint | Client | Server |
|:-:|:-:|:-:|
Expand All @@ -172,7 +172,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
| [Verify Authenticator](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaAuthenticator) | ✅ | ❌ |
| [Delete Authenticator](https://appwrite.io/docs/references/1.5.x/client-rest/account#deleteMfaAuthenticator) | ✅ | ❌ |
| [Create 2FA Challenge](https://appwrite.io/docs/references/1.5.x/client-rest/account#createMfaChallenge) | ✅ | ❌ |
| [Create MFA Challenge (confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaChallenge) | | ❌ |
| [Create MFA Challenge (confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaChallenge) | | ❌ |
| [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) | ⬛ | ❌ |
Expand Down
61 changes: 42 additions & 19 deletions src/PinguApps.Appwrite.Client/Clients/AccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public AccountClient(IServiceProvider services)
string? ISessionAware.Session { get; set; }

ISessionAware? _sessionAware;
public string? Session => GetSession();
private string? GetSession()
public string? Session => GetCurrentSession();

private string? GetCurrentSession()
{
if (_sessionAware is null)
{
Expand All @@ -36,12 +37,17 @@ public AccountClient(IServiceProvider services)
return _sessionAware.Session;
}

private string GetCurrentSessionOrThrow()
{
return GetCurrentSession() ?? throw new Exception(ISessionAware.SessionExceptionMessage);
}

/// <inheritdoc/>
public async Task<AppwriteResult<User>> Get()
{
try
{
var result = await _accountApi.GetAccount(Session);
var result = await _accountApi.GetAccount(GetCurrentSessionOrThrow());

return result.GetApiResponse();
}
Expand Down Expand Up @@ -75,7 +81,7 @@ public async Task<AppwriteResult<User>> UpdateEmail(UpdateEmailRequest request)
{
request.Validate(true);

var result = await _accountApi.UpdateEmail(Session, request);
var result = await _accountApi.UpdateEmail(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand All @@ -92,7 +98,7 @@ public async Task<AppwriteResult<User>> UpdateName(UpdateNameRequest request)
{
request.Validate(true);

var result = await _accountApi.UpdateName(Session, request);
var result = await _accountApi.UpdateName(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand All @@ -109,7 +115,7 @@ public async Task<AppwriteResult<User>> UpdatePassword(UpdatePasswordRequest req
{
request.Validate(true);

var result = await _accountApi.UpdatePassword(Session, request);
var result = await _accountApi.UpdatePassword(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand All @@ -126,7 +132,7 @@ public async Task<AppwriteResult<User>> UpdatePhone(UpdatePhoneRequest request)
{
request.Validate(true);

var result = await _accountApi.UpdatePhone(Session, request);
var result = await _accountApi.UpdatePhone(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand All @@ -141,7 +147,7 @@ public async Task<AppwriteResult<IReadOnlyDictionary<string, string>>> GetAccoun
{
try
{
var result = await _accountApi.GetAccountPreferences(Session);
var result = await _accountApi.GetAccountPreferences(GetCurrentSessionOrThrow());

return result.GetApiResponse();
}
Expand All @@ -158,7 +164,7 @@ public async Task<AppwriteResult<User>> UpdatePreferences(UpdatePreferencesReque
{
request.Validate(true);

var result = await _accountApi.UpdatePreferences(Session, request);
var result = await _accountApi.UpdatePreferences(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand Down Expand Up @@ -207,7 +213,7 @@ public async Task<AppwriteResult<Session>> GetSession(string sessionId = "curren
{
try
{
var result = await _accountApi.GetSession(Session, sessionId);
var result = await _accountApi.GetSession(GetCurrentSessionOrThrow(), sessionId);

return result.GetApiResponse();
}
Expand All @@ -222,7 +228,7 @@ public async Task<AppwriteResult<Session>> UpdateSession(string sessionId = "cur
{
try
{
var result = await _accountApi.UpdateSession(Session, sessionId);
var result = await _accountApi.UpdateSession(GetCurrentSessionOrThrow(), sessionId);

return result.GetApiResponse();
}
Expand All @@ -239,7 +245,7 @@ public async Task<AppwriteResult<Token>> CreateEmailVerification(CreateEmailVeri
{
request.Validate(true);

var result = await _accountApi.CreateEmailVerification(Session, request);
var result = await _accountApi.CreateEmailVerification(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand Down Expand Up @@ -271,7 +277,7 @@ public async Task<AppwriteResult<Jwt>> CreateJwt()
{
try
{
var result = await _accountApi.CreateJwt(Session);
var result = await _accountApi.CreateJwt(GetCurrentSessionOrThrow());

return result.GetApiResponse();
}
Expand All @@ -288,7 +294,7 @@ public async Task<AppwriteResult<LogsList>> ListLogs(List<Query>? queries = null
{
var queryStrings = queries?.Select(x => x.GetQueryString()) ?? [];

var result = await _accountApi.ListLogs(Session, queryStrings);
var result = await _accountApi.ListLogs(GetCurrentSessionOrThrow(), queryStrings);

return result.GetApiResponse();
}
Expand All @@ -305,7 +311,7 @@ public async Task<AppwriteResult<MfaType>> AddAuthenticator(AddAuthenticatorRequ
{
request.Validate(true);

var result = await _accountApi.AddAuthenticator(Session, request.Type);
var result = await _accountApi.AddAuthenticator(GetCurrentSessionOrThrow(), request.Type);

return result.GetApiResponse();
}
Expand All @@ -322,7 +328,7 @@ public async Task<AppwriteResult<User>> VerifyAuthenticator(VerifyAuthenticatorR
{
request.Validate(true);

var result = await _accountApi.VerifyAuthenticator(Session, request.Type, request);
var result = await _accountApi.VerifyAuthenticator(GetCurrentSessionOrThrow(), request.Type, request);

return result.GetApiResponse();
}
Expand All @@ -339,7 +345,7 @@ public async Task<AppwriteResult<User>> UpdateMfa(UpdateMfaRequest request)
{
request.Validate(true);

var result = await _accountApi.UpdateMfa(Session, request);
var result = await _accountApi.UpdateMfa(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand All @@ -356,7 +362,7 @@ public async Task<AppwriteResult> DeleteAuthenticator(DeleteAuthenticatorRequest
{
request.Validate(true);

var result = await _accountApi.DeleteAuthenticator(Session, request.Type, request);
var result = await _accountApi.DeleteAuthenticator(GetCurrentSessionOrThrow(), request.Type, request);

return result.GetApiResponse();
}
Expand All @@ -373,7 +379,7 @@ public async Task<AppwriteResult<MfaChallenge>> Create2faChallenge(Create2faChal
{
request.Validate(true);

var result = await _accountApi.Create2faChallenge(Session, request);
var result = await _accountApi.Create2faChallenge(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
Expand All @@ -382,4 +388,21 @@ public async Task<AppwriteResult<MfaChallenge>> Create2faChallenge(Create2faChal
return e.GetExceptionResponse<MfaChallenge>();
}
}

/// <inheritdoc/>
public async Task<AppwriteResult> Create2faChallengeConfirmation(Create2faChallengeConfirmationRequest request)
{
try
{
request.Validate(true);

var result = await _accountApi.Create2faChallengeConfirmation(GetCurrentSessionOrThrow(), request);

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse();
}
}
}
10 changes: 9 additions & 1 deletion src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,18 @@ public interface IAccountClient
Task<AppwriteResult> DeleteAuthenticator(DeleteAuthenticatorRequest request);

/// <summary>
/// Begin the process of MFA verification after sign-in. Finish the flow with updateMfaChallenge method
/// Begin the process of MFA verification after sign-in. Finish the flow with <see cref="Create2faChallengeConfirmation(Create2faChallengeConfirmationRequest)"/>
/// <para><see href="https://appwrite.io/docs/references/1.5.x/client-rest/account#createMfaChallenge">Appwrite Docs</see></para>
/// </summary>
/// <param name="request">The request content</param>
/// <returns>The Mfa Challenge</returns>
Task<AppwriteResult<MfaChallenge>> Create2faChallenge(Create2faChallengeRequest request);

/// <summary>
/// Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use <see cref="Create2faChallenge(Create2faChallengeRequest)"/>
/// <para><see href="https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaChallenge">Appwrite Docs</see></para>
/// </summary>
/// <param name="request">The request content</param>
/// <returns>The result</returns>
Task<AppwriteResult> Create2faChallengeConfirmation(Create2faChallengeConfirmationRequest request);
}
2 changes: 2 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/ISessionAware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ internal interface ISessionAware
public string? Session { get; protected set; }

public void UpdateSession(string? session) => Session = session;

public const string SessionExceptionMessage = "Session cannot be null.";
}
37 changes: 20 additions & 17 deletions src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@ namespace PinguApps.Appwrite.Client.Internals;
internal interface IAccountApi : IBaseApi
{
[Get("/account")]
Task<IApiResponse<User>> GetAccount([Header("x-appwrite-session")] string? session);
Task<IApiResponse<User>> GetAccount([Header("x-appwrite-session")] string session);

[Post("/account")]
Task<IApiResponse<User>> CreateAccount(CreateAccountRequest request);

[Patch("/account/email")]
Task<IApiResponse<User>> UpdateEmail([Header("x-appwrite-session")] string? session, UpdateEmailRequest request);
Task<IApiResponse<User>> UpdateEmail([Header("x-appwrite-session")] string session, UpdateEmailRequest request);

[Patch("/account/name")]
Task<IApiResponse<User>> UpdateName([Header("x-appwrite-session")] string? session, UpdateNameRequest request);
Task<IApiResponse<User>> UpdateName([Header("x-appwrite-session")] string session, UpdateNameRequest request);

[Patch("/account/password")]
Task<IApiResponse<User>> UpdatePassword([Header("x-appwrite-session")] string? session, UpdatePasswordRequest request);
Task<IApiResponse<User>> UpdatePassword([Header("x-appwrite-session")] string session, UpdatePasswordRequest request);

[Patch("/account/phone")]
Task<IApiResponse<User>> UpdatePhone([Header("x-appwrite-session")] string? session, UpdatePhoneRequest request);
Task<IApiResponse<User>> UpdatePhone([Header("x-appwrite-session")] string session, UpdatePhoneRequest request);

[Get("/account/prefs")]
Task<IApiResponse<IReadOnlyDictionary<string, string>>> GetAccountPreferences([Header("x-appwrite-session")] string? session);
Task<IApiResponse<IReadOnlyDictionary<string, string>>> GetAccountPreferences([Header("x-appwrite-session")] string session);

[Patch("/account/prefs")]
Task<IApiResponse<User>> UpdatePreferences([Header("x-appwrite-session")] string? session, UpdatePreferencesRequest request);
Task<IApiResponse<User>> UpdatePreferences([Header("x-appwrite-session")] string session, UpdatePreferencesRequest request);

[Post("/account/tokens/email")]
Task<IApiResponse<Token>> CreateEmailToken(CreateEmailTokenRequest request);
Expand All @@ -39,36 +39,39 @@ internal interface IAccountApi : IBaseApi
Task<IApiResponse<Session>> CreateSession(CreateSessionRequest request);

[Get("/account/sessions/{sessionId}")]
Task<IApiResponse<Session>> GetSession([Header("x-appwrite-session")] string? session, string sessionId);
Task<IApiResponse<Session>> GetSession([Header("x-appwrite-session")] string session, string sessionId);

[Patch("/account/sessions/{sessionId}")]
Task<IApiResponse<Session>> UpdateSession([Header("x-appwrite-session")] string? session, string sessionId);
Task<IApiResponse<Session>> UpdateSession([Header("x-appwrite-session")] string session, string sessionId);

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

[Put("/account/verification")]
Task<IApiResponse<Token>> CreateEmailVerificationConfirmation(CreateEmailVerificationConfirmationRequest request);

[Post("/account/jwt")]
Task<IApiResponse<Jwt>> CreateJwt([Header("x-appwrite-session")] string? session);
Task<IApiResponse<Jwt>> CreateJwt([Header("x-appwrite-session")] string session);

[Get("/account/logs")]
[QueryUriFormat(System.UriFormat.Unescaped)]
Task<IApiResponse<LogsList>> ListLogs([Header("x-appwrite-session")] string? session, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable<string> queries);
Task<IApiResponse<LogsList>> ListLogs([Header("x-appwrite-session")] string session, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable<string> queries);

[Post("/account/mfa/authenticators/{type}")]
Task<IApiResponse<MfaType>> AddAuthenticator([Header("x-appwrite-session")] string? session, string type);
Task<IApiResponse<MfaType>> AddAuthenticator([Header("x-appwrite-session")] string session, string type);

[Put("/account/mfa/authenticators/{type}")]
Task<IApiResponse<User>> VerifyAuthenticator([Header("x-appwrite-session")] string? session, string type, VerifyAuthenticatorRequest request);
Task<IApiResponse<User>> VerifyAuthenticator([Header("x-appwrite-session")] string session, string type, VerifyAuthenticatorRequest request);

[Patch("/account/mfa")]
Task<IApiResponse<User>> UpdateMfa([Header("x-appwrite-session")] string? session, UpdateMfaRequest request);
Task<IApiResponse<User>> UpdateMfa([Header("x-appwrite-session")] string session, UpdateMfaRequest request);

[Delete("/account/mfa/authenticators/{type}")]
Task<IApiResponse> DeleteAuthenticator([Header("x-appwrite-session")] string? session, string type, [Body] DeleteAuthenticatorRequest request);
Task<IApiResponse> DeleteAuthenticator([Header("x-appwrite-session")] string session, string type, [Body] DeleteAuthenticatorRequest request);

[Post("/account/mfa/challenge")]
Task<IApiResponse<MfaChallenge>> Create2faChallenge([Header("x-appwrite-session")] string? session, Create2faChallengeRequest request);
Task<IApiResponse<MfaChallenge>> Create2faChallenge([Header("x-appwrite-session")] string session, Create2faChallengeRequest request);

[Put("/account/mfa/challenge")]
Task<IApiResponse> Create2faChallengeConfirmation([Header("x-appwrite-session")] string session, Create2faChallengeConfirmationRequest request);
}
14 changes: 12 additions & 2 deletions src/PinguApps.Appwrite.Playground/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,25 @@ public async Task Run(string[] args)
{
_client.SetSession(_session);

Console.WriteLine(_client.Session);

//var response = await _client.Account.AddAuthenticator();
var response = await _client.Account.Create2faChallenge(new Shared.Requests.Create2faChallengeRequest
//var response = await _client.Account.Create2faChallenge(new Shared.Requests.Create2faChallengeRequest
//{
// Factor = Shared.Enums.SecondFactor.Email
//});

var response = await _client.Account.Create2faChallengeConfirmation(new Shared.Requests.Create2faChallengeConfirmationRequest
{
Factor = Shared.Enums.SecondFactor.Email
ChallengeId = "66b771b7bdcb152aaa5b",
Otp = "474376"
});

Console.WriteLine(response.Result.Match(
account => account.ToString(),
appwriteError => appwriteError.Message,
internalERror => internalERror.Message));

Console.WriteLine(_client.Session);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Text.Json.Serialization;
using PinguApps.Appwrite.Shared.Requests.Validators;

namespace PinguApps.Appwrite.Shared.Requests;

/// <summary>
/// The request for creating a 2fa challenge confirmation
/// </summary>
public class Create2faChallengeConfirmationRequest : BaseRequest<Create2faChallengeConfirmationRequest, Create2faChallengeConfirmationRequestValidator>
{
/// <summary>
/// ID of the challenge
/// </summary>
[JsonPropertyName("challengeId")]
public string ChallengeId { get; set; } = string.Empty;

/// <summary>
/// Valid verification token
/// </summary>
[JsonPropertyName("otp")]
public string Otp { get; set; } = string.Empty;
}
Loading