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

Fix HTTP login and logout features #14

Merged
merged 2 commits into from
Sep 7, 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
7 changes: 7 additions & 0 deletions Iggy_SDK/Contracts/Http/Auth/AuthResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Iggy_SDK.Contracts.Http;

public record AuthResponse(int UserId, TokenInfo AccessToken)
{
// public required int UserId { get; init; }
// public TokenInfo AccessToken { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System.Text.Json.Serialization;
namespace Iggy_SDK.Contracts.Http;
public sealed class ChangePasswordRequest
{
[JsonIgnore]
public required Identifier UserId { get; init; }
public required string CurrentPassword { get; init; }
public required string NewPassword { get; init; }
using System.Text.Json.Serialization;
namespace Iggy_SDK.Contracts.Http;

public sealed class ChangePasswordRequest
{
[JsonIgnore]
public required Identifier UserId { get; init; }
public required string CurrentPassword { get; init; }
public required string NewPassword { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Iggy_SDK.Enums;
namespace Iggy_SDK.Contracts.Http;
public sealed class CreateUserRequest
{
public required string Username { get; init; }
public required string Password { get; init; }
public required UserStatus Status { get; init; }
public Permissions? Permissions { get; init; }
using Iggy_SDK.Enums;
namespace Iggy_SDK.Contracts.Http;

public sealed class CreateUserRequest
{
public required string Username { get; init; }
public required string Password { get; init; }
public required UserStatus Status { get; init; }
public Permissions? Permissions { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Iggy_SDK.Contracts.Http;
public sealed class LoginUserRequest
{
public required string Username { get; init; }
public required string Password { get; init; }
namespace Iggy_SDK.Contracts.Http;

public sealed class LoginUserRequest
{
public required string Username { get; init; }
public required string Password { get; init; }
}
3 changes: 3 additions & 0 deletions Iggy_SDK/Contracts/Http/Auth/TokenInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Iggy_SDK.Contracts.Http;

public record TokenInfo(string Token, DateTimeOffset Expiry);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Text.Json.Serialization;
namespace Iggy_SDK.Contracts.Http;
public sealed class UpdateUserPermissionsRequest
{
[JsonIgnore]
public required Identifier UserId { get; init; }
public Permissions? Permissions { get; init; }
using System.Text.Json.Serialization;
namespace Iggy_SDK.Contracts.Http;

public sealed class UpdateUserPermissionsRequest
{
[JsonIgnore]
public required Identifier UserId { get; init; }
public Permissions? Permissions { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using Iggy_SDK.Enums;
using System.Text.Json.Serialization;
namespace Iggy_SDK.Contracts.Http;
public sealed class UpdateUserRequest
{
[JsonIgnore]
public required Identifier UserId { get; init; }
public string? Username { get; init; }
public UserStatus? UserStatus { get; init; }
using Iggy_SDK.Enums;
using System.Text.Json.Serialization;
namespace Iggy_SDK.Contracts.Http;

public sealed class UpdateUserRequest
{
[JsonIgnore]
public required Identifier UserId { get; init; }
public string? Username { get; init; }
public UserStatus? UserStatus { get; init; }
}
7 changes: 0 additions & 7 deletions Iggy_SDK/Contracts/Http/AuthResponse.cs

This file was deleted.

7 changes: 0 additions & 7 deletions Iggy_SDK/Contracts/Http/TokenInfo.cs

This file was deleted.

7 changes: 0 additions & 7 deletions Iggy_SDK/Contracts/Http/Tokens.cs

This file was deleted.

62 changes: 35 additions & 27 deletions Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal HttpMessageStream(HttpClient httpClient, Channel<MessageSendRequest>? c
_messageInvoker = messageInvoker;
_logger = loggerFactory.CreateLogger<HttpMessageStream>();
}

public async Task CreateStreamAsync(StreamRequest request, CancellationToken token = default)
{
var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions);
Expand Down Expand Up @@ -238,6 +239,7 @@ public async Task<PolledMessages<TMessage>> FetchMessagesAsync<TMessage>(Message
await HandleResponseAsync(response);
return PolledMessages<TMessage>.Empty;
}

public async IAsyncEnumerable<MessageResponse<TMessage>> PollMessagesAsync<TMessage>(PollMessagesRequest request,
Func<byte[], TMessage> deserializer, Func<byte[], byte[]>? decryptor = null,
[EnumeratorCancellation] CancellationToken token = default)
Expand Down Expand Up @@ -295,6 +297,7 @@ public async IAsyncEnumerable<MessageResponse<TMessage>> PollMessagesAsync<TMess
}
}
}

private async Task StartPollingMessagesAsync<TMessage>(MessageFetchRequest request,
Func<byte[], TMessage> deserializer, TimeSpan interval, ChannelWriter<MessageResponse<TMessage>> writer,
Func<byte[], byte[]>? decryptor = null,
Expand Down Expand Up @@ -324,6 +327,7 @@ private async Task StartPollingMessagesAsync<TMessage>(MessageFetchRequest reque
}
writer.Complete();
}

public async Task StoreOffsetAsync(StoreOffsetRequest request, CancellationToken token = default)
{
var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions);
Expand Down Expand Up @@ -372,6 +376,7 @@ public async Task<IReadOnlyList<ConsumerGroupResponse>> GetConsumerGroupsAsync(I
await HandleResponseAsync(response);
return null;
}

public async Task CreateConsumerGroupAsync(CreateConsumerGroupRequest request, CancellationToken token = default)
{
var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions);
Expand All @@ -383,6 +388,7 @@ public async Task CreateConsumerGroupAsync(CreateConsumerGroupRequest request, C
await HandleResponseAsync(response);
}
}

public async Task DeleteConsumerGroupAsync(DeleteConsumerGroupRequest request, CancellationToken token = default)
{
var response = await _httpClient.DeleteAsync($"/streams/{request.StreamId}/topics/{request.TopicId}/consumer-groups/{request.ConsumerGroupId}", token);
Expand Down Expand Up @@ -550,8 +556,8 @@ public async Task ChangePassword(ChangePasswordRequest request, CancellationToke
if (response.IsSuccessStatusCode)
{
var authResponse = await response.Content.ReadFromJsonAsync<AuthResponse>(JsonConverterFactory.AuthResponseOptions, cancellationToken: token);
var jwtToken = authResponse!.Tokens?.AccessToken?.Token;
if (!string.IsNullOrEmpty(authResponse!.Tokens!.AccessToken!.Token))
var jwtToken = authResponse!.AccessToken?.Token;
if (!string.IsNullOrEmpty(authResponse!.AccessToken!.Token))
{
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", jwtToken);
Expand All @@ -567,11 +573,11 @@ public async Task ChangePassword(ChangePasswordRequest request, CancellationToke
}
public async Task LogoutUser(CancellationToken token = default)
{
var json = JsonSerializer.Serialize(new
{
}, JsonConverterFactory.SnakeCaseOptions);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("users/logout", content, token);
// var json = JsonSerializer.Serialize(new
// {
// }, JsonConverterFactory.SnakeCaseOptions);
// var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.DeleteAsync("users/logout", token);
if (!response.IsSuccessStatusCode)
{
await HandleResponseAsync(response);
Expand Down Expand Up @@ -610,25 +616,27 @@ public async Task DeletePersonalAccessTokenAsync(DeletePersonalAccessTokenReques
}
public async Task<AuthResponse?> LoginWithPersonalAccessToken(LoginWithPersonalAccessToken request, CancellationToken token = default)
{
var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("/personal-access-tokens/login", content, token);
if (response.IsSuccessStatusCode)
{
var authResponse = await response.Content.ReadFromJsonAsync<AuthResponse>(JsonConverterFactory.AuthResponseOptions, cancellationToken: token);
var jwtToken = authResponse!.Tokens?.AccessToken?.Token;
if (!string.IsNullOrEmpty(authResponse!.Tokens!.AccessToken!.Token))
{
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", jwtToken);
}
else
{
throw new Exception("The JWT token is missing.");
}
return authResponse;
}
await HandleResponseAsync(response);
return null;
// var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions);
// var content = new StringContent(json, Encoding.UTF8, "application/json");
// var response = await _httpClient.PostAsync("/personal-access-tokens/login", content, token);
// if (response.IsSuccessStatusCode)
// {
// var authResponse = await response.Content.ReadFromJsonAsync<AuthResponse>(JsonConverterFactory.AuthResponseOptions, cancellationToken: token);
// var jwtToken = authResponse!.Tokens?.AccessToken?.Token;
// if (!string.IsNullOrEmpty(authResponse!.Tokens!.AccessToken!.Token))
// {
// _httpClient.DefaultRequestHeaders.Authorization =
// new AuthenticationHeaderValue("Bearer", jwtToken);
// }
// else
// {
// throw new Exception("The JWT token is missing.");
// }
// return authResponse;
// }
// await HandleResponseAsync(response);
// return null;

throw new NotImplementedException();
}
}
14 changes: 6 additions & 8 deletions Iggy_SDK/IggyClient/Implementations/TcpMessageStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,10 +1045,9 @@ public async Task ChangePassword(ChangePasswordRequest request, CancellationToke
}

var userId = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan()[8..(8 + response.Length)]);
return new AuthResponse
{
UserId = userId
};

//TODO: Figure out how to solve this workaround about default of TokenInfo
return new AuthResponse(userId, default);
}
public async Task LogoutUser(CancellationToken token = default)
{
Expand Down Expand Up @@ -1164,9 +1163,8 @@ public async Task DeletePersonalAccessTokenAsync(DeletePersonalAccessTokenReques
return null;
}
var userId = BinaryPrimitives.ReadInt32LittleEndian(responseBuffer.AsSpan()[..4]);
return new AuthResponse
{
UserId = userId
};

//TODO: Figure out how to solve this workaround about default of TokenInfo
return new AuthResponse(userId, default);
}
}
35 changes: 8 additions & 27 deletions Iggy_SDK/JsonConfiguration/AuthResponseConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,15 @@
using var doc = JsonDocument.ParseValue(ref reader);
var root = doc.RootElement;

var userId = root.GetProperty(nameof(AuthResponse.UserId).ToSnakeCase()).GetInt32();
var tokens = root.GetProperty(nameof(AuthResponse.Tokens).ToSnakeCase());
var userId = root.GetProperty(nameof(AuthResponse.UserId).ToSnakeCase()).GetInt32();
var accessToken = root.GetProperty(nameof(AuthResponse.AccessToken).ToSnakeCase());
var token = accessToken.GetProperty(nameof(TokenInfo.Token).ToSnakeCase()).GetString();
var accessTokenExpiry = accessToken.GetProperty(nameof(TokenInfo.Expiry).ToSnakeCase()).GetInt64();

var accessTokenProperty = tokens.GetProperty(nameof(Tokens.AccessToken).ToSnakeCase());
var accessToken = accessTokenProperty.GetProperty(nameof(TokenInfo.Token).ToSnakeCase()).GetString();
var accessTokenExpiry = accessTokenProperty.GetProperty(nameof(TokenInfo.Expiry).ToSnakeCase()).GetInt64();

var refreshTokenProperty = tokens.GetProperty(nameof(Tokens.RefreshToken).ToSnakeCase());
var refreshToken = refreshTokenProperty.GetProperty(nameof(TokenInfo.Token).ToSnakeCase()).GetString();
var refreshTokenExpiry = refreshTokenProperty.GetProperty(nameof(TokenInfo.Expiry).ToSnakeCase()).GetInt64();

return new AuthResponse
{
UserId = userId,
Tokens = new Tokens
{
AccessToken = new TokenInfo
{
Token = accessToken!,
Expiry = DateTimeOffset.FromUnixTimeSeconds(accessTokenExpiry).LocalDateTime,
},
RefreshToken = new TokenInfo
{
Token = refreshToken!,
Expiry = DateTimeOffset.FromUnixTimeSeconds(refreshTokenExpiry).LocalDateTime,
}
}
};
return new AuthResponse(
userId,
new TokenInfo(token, DateTimeOffset.FromUnixTimeSeconds(accessTokenExpiry).LocalDateTime)

Check warning on line 22 in Iggy_SDK/JsonConfiguration/AuthResponseConverter.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Possible null reference argument for parameter 'Token' in 'TokenInfo.TokenInfo(string Token, DateTimeOffset Expiry)'.
);
}
public override void Write(Utf8JsonWriter writer, AuthResponse value, JsonSerializerOptions options)
{
Expand Down
Loading
Loading