Skip to content

Commit

Permalink
Merge pull request #78 from PinguApps/44-update-session-implementation
Browse files Browse the repository at this point in the history
update session implementation
  • Loading branch information
pingu2k4 authored Aug 1, 2024
2 parents 6c3abff + bf3a132 commit 376d88e
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 7 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(

## ⌛ Progress
### Server & Client
![13 / 288](https://progress-bar.dev/13/?scale=288&suffix=%20/%20288&width=500)
![14 / 288](https://progress-bar.dev/14/?scale=288&suffix=%20/%20288&width=500)
### Server Only
![2 / 195](https://progress-bar.dev/2/?scale=195&suffix=%20/%20195&width=300)
### Client Only
![11 / 93](https://progress-bar.dev/11/?scale=93&suffix=%20/%2093&width=300)
![12 / 93](https://progress-bar.dev/12/?scale=93&suffix=%20/%2093&width=300)

### 🔑 Key
| Icon | Definition |
Expand All @@ -153,7 +153,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
|| There is currently no intention to implement the endpoint for the given SDK type (client or server) |

### Account
![13 / 52](https://progress-bar.dev/13/?scale=52&suffix=%20/%2052&width=120)
![14 / 52](https://progress-bar.dev/14/?scale=52&suffix=%20/%2052&width=120)

| Endpoint | Client | Server |
|:-:|:-:|:-:|
Expand Down Expand Up @@ -190,7 +190,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
| [Update Phone Session](https://appwrite.io/docs/references/1.5.x/client-rest/account#updatePhoneSession) |||
| [Create Session](https://appwrite.io/docs/references/1.5.x/client-rest/account#createSession) |||
| [Get Session](https://appwrite.io/docs/references/1.5.x/client-rest/account#getSession) |||
| [Update Session](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateSession) | ||
| [Update Session](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateSession) | ||
| [Delete Session](https://appwrite.io/docs/references/1.5.x/client-rest/account#deleteSession) |||
| [Update Status](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateStatus) |||
| [Create Push Target](https://appwrite.io/docs/references/1.5.x/client-rest/account#createPushTarget) |||
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 @@ -214,4 +214,19 @@ public async Task<AppwriteResult<Session>> GetSession(string sessionId = "curren
return e.GetExceptionResponse<Session>();
}
}

/// <inheritdoc/>
public async Task<AppwriteResult<Session>> UpdateSession(string sessionId = "current")
{
try
{
var result = await _accountApi.UpdateSession(Session, sessionId);

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse<Session>();
}
}
}
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 @@ -100,4 +100,12 @@ public interface IAccountClient
/// <param name="sessionId">Session ID. Use the string 'current' to get the current device session</param>
/// <returns>The session</returns>
Task<AppwriteResult<Session>> GetSession(string sessionId = "current");

/// <summary>
/// Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.
/// <para><see href="https://appwrite.io/docs/references/1.5.x/client-rest/account#updateSession">Appwrite Docs</see></para>
/// </summary>
/// <param name="sessionId">Session ID. Use the string 'current' to update the current device session.</param>
/// <returns>The session</returns>
Task<AppwriteResult<Session>> UpdateSession(string sessionId = "current");
}
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 @@ -40,4 +40,7 @@ internal interface IAccountApi : IBaseApi

[Get("/account/sessions/{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);
}
23 changes: 21 additions & 2 deletions src/PinguApps.Appwrite.Playground/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,28 @@ public async Task Run(string[] args)

Console.WriteLine("Getting Session...");

var account = await _client.Account.GetSession("6695d717983fadf6ece1");
//var response = await _client.Account.CreateEmailToken(new CreateEmailTokenRequest
//{
// Email = "[email protected]",
// UserId = "664aac1a00113f82e620"
//});

Console.WriteLine(account.Result.Match(
//var response = await _client.Account.CreateSession(new CreateSessionRequest
//{
// UserId = "664aac1a00113f82e620",
// Secret = "623341"
//});

var response = await _client.Account.GetSession("66a810f2e55b1329e25b");

var response2 = await _client.Account.UpdateSession("66a810f2e55b1329e25b");

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

Console.WriteLine(response2.Result.Match(
account => account.ToString(),
appwriteError => appwriteError.Message,
internalERror => internalERror.Message));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace PinguApps.Appwrite.Shared.Converters;

/// <summary>
/// This is only required temporarily as a workaround for #8447 on Appwrite.
/// <para><see href="https://github.com/appwrite/appwrite/issues/8447"/></para>
/// </summary>
public class MultiFormatDateTimeConverter : JsonConverter<DateTime>
{
private readonly string[] _formats = [
"yyyy-MM-ddTHH:mm:ss.fffK",
"yyyy-MM-dd HH:mm:ss.fff"
];

public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var dateString = reader.GetString();

foreach (var format in _formats)
{
if (DateTime.TryParseExact(dateString, format, null, System.Globalization.DateTimeStyles.None, out var dateTime))
{
return dateTime;
}
}
throw new JsonException($"Unable to parse date: {dateString}");
}
throw new JsonException("Invalid token type");
}

public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(_formats[0])); // Use the first format for serialization
}
}
2 changes: 1 addition & 1 deletion src/PinguApps.Appwrite.Shared/Responses/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public record Session(
[property: JsonPropertyName("$createdAt")] DateTime CreatedAt,
[property: JsonPropertyName("$updatedAt")] DateTime UpdatedAt,
[property: JsonPropertyName("userId")] string UserId,
[property: JsonPropertyName("expire")] DateTime ExpiresAt,
[property: JsonPropertyName("expire"), JsonConverter(typeof(MultiFormatDateTimeConverter))] DateTime ExpiresAt,
[property: JsonPropertyName("provider")] string Provider,
[property: JsonPropertyName("providerUid")] string ProviderUserId,
[property: JsonPropertyName("providerAccessToken")] string ProviderAccessToken,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Net;
using PinguApps.Appwrite.Shared.Tests;
using PinguApps.Appwrite.Shared.Utils;
using RichardSzalay.MockHttp;

namespace PinguApps.Appwrite.Client.Tests.Clients.Account;
public partial class AccountClientTests
{
[Fact]
public async Task UpdateSession_HitsCurrent_ShouldReturnSuccess_WhenApiCallSucceeds()
{
// Arrange
_mockHttp.Expect(HttpMethod.Patch, $"{Constants.Endpoint}/account/sessions/current")
.ExpectedHeaders(true)
.Respond(Constants.AppJson, Constants.UserResponse);

_appwriteClient.SetSession(Constants.Session);

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

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

[Fact]
public async Task UpdateSession_ShouldReturnSuccess_WhenApiCallSucceeds()
{
// Arrange
var sessionId = IdUtils.GenerateUniqueId();

_mockHttp.Expect(HttpMethod.Patch, $"{Constants.Endpoint}/account/sessions/{sessionId}")
.ExpectedHeaders(true)
.Respond(Constants.AppJson, Constants.UserResponse);

_appwriteClient.SetSession(Constants.Session);

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

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

[Fact]
public async Task UpdateSession_ShouldHandleException_WhenApiCallFails()
{
// Arrange
_mockHttp.Expect(HttpMethod.Patch, $"{Constants.Endpoint}/account/sessions/current")
.ExpectedHeaders(true)
.Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError);

_appwriteClient.SetSession(Constants.Session);

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

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

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

_appwriteClient.SetSession(Constants.Session);

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

// Assert
Assert.False(result.Success);
Assert.True(result.IsInternalError);
Assert.Equal("An error occurred", result.Result.AsT2.Message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using PinguApps.Appwrite.Shared.Converters;

namespace PinguApps.Appwrite.Shared.Tests.Converters;
public class MultiFormatDateTimeConverterTests
{
private readonly JsonSerializerOptions _options;

public MultiFormatDateTimeConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new MultiFormatDateTimeConverter());
}

[Fact]
public void Read_ValidDateStringWithTimeZone_ReturnsDateTime()
{
var json = "\"2023-01-01T00:00:00.000Z\"";
var result = JsonSerializer.Deserialize<DateTime>(json, _options);

// Convert both to UTC to compare
var expectedDateTime = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var actualDateTime = result.ToUniversalTime();

Assert.Equal(expectedDateTime, actualDateTime);
}

[Fact]
public void Read_ValidDateStringWithoutTimeZone_ReturnsDateTime()
{
var json = "\"2023-01-01 00:00:00.000\"";
var result = JsonSerializer.Deserialize<DateTime>(json, _options);
Assert.Equal(new DateTime(2023, 1, 1, 0, 0, 0), result);
}

[Fact]
public void Read_InvalidDateString_ThrowsJsonException()
{
var json = "\"invalid-date\"";
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<DateTime>(json, _options));
}

[Fact]
public void Read_UnexpectedTokenType_ThrowsJsonException()
{
var json = "123";
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<DateTime>(json, _options));
}

[Fact]
public void Write_ValidDateTime_WritesExpectedString()
{
var dateTime = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var json = JsonSerializer.Serialize(dateTime, _options);
Assert.Equal("\"2023-01-01T00:00:00.000Z\"", json);
}

public class MultiFormatDateTimeObject
{
[JsonPropertyName("x")]
[JsonConverter(typeof(MultiFormatDateTimeConverter))]
public DateTime X { get; set; }
}

[Fact]
public void Read_ValidDateStringInObject_ReturnsDateTime()
{
var json = "{\"x\": \"2023-01-01T00:00:00.000Z\"}";
var result = JsonSerializer.Deserialize<MultiFormatDateTimeObject>(json, _options);
Assert.NotNull(result);


// Convert both to UTC to compare
var expectedDateTime = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var actualDateTime = result.X.ToUniversalTime();

Assert.Equal(expectedDateTime, actualDateTime);
}

[Fact]
public void Write_ValidDateTimeInObject_WritesExpectedString()
{
var obj = new MultiFormatDateTimeObject { X = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc) };
var json = JsonSerializer.Serialize(obj, _options);
Assert.Equal("{\"x\":\"2023-01-01T00:00:00.000Z\"}", json);
}
}

0 comments on commit 376d88e

Please sign in to comment.