Skip to content

Commit

Permalink
105 delete session (#156)
Browse files Browse the repository at this point in the history
* Add shared request for delete session

* bump response format to 1.6

* implemented delete session on client

* added shared tests

* bump expected appwrite response header

* Add client tests

* Update README.md

* [CodeFactor] Apply fixes

---------

Co-authored-by: codefactor-io <[email protected]>
  • Loading branch information
pingu2k4 and code-factor authored Sep 15, 2024
1 parent d5f11ef commit d966892
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 18 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
<!-- ![38 / 293](https://progress-bar.dev/38/?scale=293&suffix=%20/%20288&width=500) -->
![Server & Client - 38 / 293](https://img.shields.io/badge/Server_&_Client-38%20%2F%20293-red?style=for-the-badge)
<!-- ![39 / 293](https://progress-bar.dev/39/?scale=293&suffix=%20/%20288&width=500) -->
![Server & Client - 39 / 293](https://img.shields.io/badge/Server_&_Client-39%20%2F%20293-red?style=for-the-badge)

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

<!-- ![33 / 93](https://progress-bar.dev/33/?scale=93&suffix=%20/%2093&width=300) -->
![Client - 33 / 93](https://img.shields.io/badge/Client-33%20%2F%2093-red?style=for-the-badge)
<!-- ![34 / 93](https://progress-bar.dev/34/?scale=93&suffix=%20/%2093&width=300) -->
![Client - 34 / 93](https://img.shields.io/badge/Client-34%20%2F%2093-gold?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
<!-- ![38 / 57](https://progress-bar.dev/38/?scale=57&suffix=%20/%2052&width=120) -->
![Account - 38 / 57](https://img.shields.io/badge/Account-38%20%2F%2057-forestgreen?style=for-the-badge)
<!-- ![39 / 57](https://progress-bar.dev/39/?scale=57&suffix=%20/%2052&width=120) -->
![Account - 39 / 57](https://img.shields.io/badge/Account-39%20%2F%2057-forestgreen?style=for-the-badge)

| Endpoint | Client | Server |
|:-:|:-:|:-:|
Expand Down Expand Up @@ -194,7 +194,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
| [Create Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#createSession) |||
| [Get Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#getSession) |||
| [Update Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#updateSession) |||
| [Delete Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#deleteSession) | ||
| [Delete Session](https://appwrite.io/docs/references/1.6.x/client-rest/account#deleteSession) | ||
| [Update Status](https://appwrite.io/docs/references/1.6.x/client-rest/account#updateStatus) |||
| [Create Push Target](https://appwrite.io/docs/references/1.6.x/client-rest/account#createPushTarget) |||
| [Update Push Target](https://appwrite.io/docs/references/1.6.x/client-rest/account#updatePushTarget) |||
Expand Down
17 changes: 17 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/AccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -580,4 +580,21 @@ public AppwriteResult<CreateOauth2Session> CreateOauth2Session(CreateOauth2Sessi
return e.GetExceptionResponse<CreateOauth2Session>();
}
}

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

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

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse();
}
}
}
8 changes: 8 additions & 0 deletions src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,12 @@ public interface IAccountClient
/// <param name="request">The request content</param>
/// <returns>The CreateOauth2Session object</returns>
AppwriteResult<CreateOauth2Session> CreateOauth2Session(CreateOauth2SessionRequest request);

/// <summary>
/// Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use <see cref="DeleteSessions"/> instead.
/// <para><see href="https://appwrite.io/docs/references/1.6.x/client-rest/account#deleteSession">Appwrite Docs</see></para>
/// </summary>
/// <param name="request">The request content</param>
/// <returns>code 204 for success</returns>
Task<AppwriteResult> DeleteSession(DeleteSessionRequest request);
}
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 @@ -104,4 +104,7 @@ internal interface IAccountApi : IBaseApi

[Post("/account/sessions/email")]
Task<IApiResponse<Session>> CreateEmailPasswordSession(CreateEmailPasswordSessionRequest request);

[Delete("/account/sessions/{sessionId}")]
Task<IApiResponse> DeleteSession([Header("x-appwrite-session")] string session, string sessionId);
}
2 changes: 1 addition & 1 deletion src/PinguApps.Appwrite.Client/Internals/IBaseApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace PinguApps.Appwrite.Client.Internals;
"x-sdk-platform: client",
"x-sdk-language: dotnet",
"x-sdk-version: 0.0.1",
"X-Appwrite-Response-Format: 1.5.0")]
"X-Appwrite-Response-Format: 1.6.0")]
internal interface IBaseApi
{
}
24 changes: 16 additions & 8 deletions src/PinguApps.Appwrite.Playground/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,27 @@ public App(IAppwriteClient client, IAppwriteServer server, IConfiguration config

public async Task Run(string[] args)
{
//_client.SetSession(_session);
_client.SetSession(_session);

var request = new CreateSessionRequest()
{
UserId = "664aac1a00113f82e620",
Secret = "339597"
};

var response = await _server.Account.CreateSession(request);
var response = await _client.Account.Get();

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

var r2 = await _client.Account.DeleteSession(new DeleteSessionRequest());

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

var r3 = await _client.Account.Get();

Console.WriteLine(r3.Result.Match(
account => account.ToString(),
appwriteError => appwriteError.Message,
internalERror => internalERror.Message));
}
}
2 changes: 1 addition & 1 deletion src/PinguApps.Appwrite.Server/Internals/IBaseApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace PinguApps.Appwrite.Server.Internals;
"x-sdk-platform: server",
"x-sdk-language: dotnet",
"x-sdk-version: 0.0.1",
"X-Appwrite-Response-Format: 1.5.0")]
"X-Appwrite-Response-Format: 1.6.0")]
internal interface IBaseApi
{
}
16 changes: 16 additions & 0 deletions src/PinguApps.Appwrite.Shared/Requests/DeleteSessionRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
using PinguApps.Appwrite.Shared.Requests.Validators;

namespace PinguApps.Appwrite.Shared.Requests;

/// <summary>
/// The request for deleting a session (logging out of current session)
/// </summary>
public class DeleteSessionRequest : BaseRequest<DeleteSessionRequest, DeleteSessionRequestValidator>
{
/// <summary>
/// Session ID. Use the string 'current' to delete the current device session.
/// </summary>
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = "current";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using FluentValidation;

namespace PinguApps.Appwrite.Shared.Requests.Validators;
public class DeleteSessionRequestValidator : AbstractValidator<DeleteSessionRequest>
{
public DeleteSessionRequestValidator()
{
RuleFor(x => x.SessionId).NotEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System.Net;
using PinguApps.Appwrite.Client.Clients;
using PinguApps.Appwrite.Shared.Requests;
using PinguApps.Appwrite.Shared.Tests;
using RichardSzalay.MockHttp;

namespace PinguApps.Appwrite.Client.Tests.Clients.Account;
public partial class AccountClientTests
{
[Fact]
public async Task DeleteSession_ShouldReturnSuccess_WhenApiCallSucceeds()
{
// Arrange
var request = new DeleteSessionRequest();

_mockHttp.Expect(HttpMethod.Delete, $"{Constants.Endpoint}/account/sessions/current")
.ExpectedHeaders(true)
.Respond(Constants.AppJson, Constants.MfaTypeResponse);

_appwriteClient.SetSession(Constants.Session);

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

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

[Fact]
public async Task DeleteSession_ShouldHitDifferentEndpoint_WhenNewTypeIsUsed()
{
// Arrange
var sessionId = "mySessionId";
var request = new DeleteSessionRequest()
{
SessionId = sessionId
};
var requestUri = $"{Constants.Endpoint}/account/sessions/{sessionId}";
var mockRequest = _mockHttp.Expect(HttpMethod.Delete, requestUri)
.ExpectedHeaders(true)
.Respond(Constants.AppJson, Constants.MfaTypeResponse);

_appwriteClient.SetSession(Constants.Session);

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

// Assert
_mockHttp.VerifyNoOutstandingExpectation();
var matches = _mockHttp.GetMatchCount(mockRequest);
Assert.Equal(1, matches);
}

[Fact]
public async Task DeleteSession_ShouldReturnError_WhenSessionIsNull()
{
// Arrange
var request = new DeleteSessionRequest();

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

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

[Fact]
public async Task DeleteSession_ShouldHandleException_WhenApiCallFails()
{
// Arrange
var request = new DeleteSessionRequest();

_mockHttp.Expect(HttpMethod.Delete, $"{Constants.Endpoint}/account/sessions/current")
.ExpectedHeaders(true)
.Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError);

_appwriteClient.SetSession(Constants.Session);

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

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

[Fact]
public async Task DeleteSession_ShouldReturnErrorResponse_WhenExceptionOccurs()
{
// Arrange
var request = new DeleteSessionRequest();

_mockHttp.Expect(HttpMethod.Delete, $"{Constants.Endpoint}/account/sessions/current")
.ExpectedHeaders(true)
.Throw(new HttpRequestException("An error occurred"));

_appwriteClient.SetSession(Constants.Session);

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

// Assert
Assert.False(result.Success);
Assert.True(result.IsInternalError);
Assert.Equal("An error occurred", result.Result.AsT2.Message);
}
}
2 changes: 1 addition & 1 deletion tests/PinguApps.Appwrite.Shared.Tests/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static class Constants

public const string SdkVersion = "0.0.1";

public const string AppwriteResponseFormat = "1.5.0";
public const string AppwriteResponseFormat = "1.6.0";

public const string AppwriteError = """
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using FluentValidation;
using PinguApps.Appwrite.Shared.Requests;

namespace PinguApps.Appwrite.Shared.Tests.Requests;
public class DeleteSessionRequestTests
{
[Fact]
public void Constructor_InitializesWithExpectedValues()
{
// Arrange & Act
var request = new DeleteSessionRequest();

// Assert
Assert.Equal("current", request.SessionId);
}

[Theory]
[InlineData("A string")]
public void Properties_CanBeSet(string sessionId)
{
// Arrange
var request = new DeleteSessionRequest();

// Act
request.SessionId = sessionId;

// Assert
Assert.Equal(sessionId, request.SessionId);
}

[Fact]
public void IsValid_WithValidInputs_ReturnsTrue()
{
// Arrange
var request = new DeleteSessionRequest
{
SessionId = "blahblah"
};

// Act
var isValid = request.IsValid();

// Assert
Assert.True(isValid);
}

[Theory]
[InlineData("")]
[InlineData(null)]
public void IsValid_WithInvalidInputs_ReturnsFalse(string? sessionId)
{
// Arrange
var request = new DeleteSessionRequest
{
SessionId = sessionId!
};

// Act
var isValid = request.IsValid();

// Assert
Assert.False(isValid);
}

[Fact]
public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure()
{
// Arrange
var request = new DeleteSessionRequest
{
SessionId = ""
};

// Assert
Assert.Throws<ValidationException>(() => request.Validate(true));
}

[Fact]
public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure()
{
// Arrange
var request = new DeleteSessionRequest
{
SessionId = ""
};

// Act
var result = request.Validate(false);

// Assert
Assert.False(result.IsValid);
}
}

0 comments on commit d966892

Please sign in to comment.