Files
EchoHub/src/EchoHub.Client/Services/EchoHubConnection.cs
T
HueByte 287270b26d feat: Refactor authentication and token management
- Updated EchoHubConnection to use ApiClient for token retrieval.
- Introduced ValidationConstants for common validation patterns and limits.
- Enhanced AuthDtos with refresh token support and expiration details.
- Added new ChatDtos for channel creation and topic updates.
- Created CommonDtos for error and paginated responses.
- Implemented RefreshToken model for managing refresh tokens.
- Modified JwtTokenService to generate and hash refresh tokens.
- Updated AuthController to handle registration, login, token refresh, and logout with improved error handling.
- Enhanced ChannelsController with channel creation, topic updates, and pagination for channel retrieval.
- Added FilesController for file management with rate limiting.
- Improved UsersController for profile updates and avatar uploads with validation.
- Integrated rate limiting across controllers to manage request load.
- Introduced FileValidationHelper for validating uploaded image files.
- Updated database context to include RefreshToken and enforce unique constraints.
- Enhanced ChatHub for improved channel and message handling with validation.
- Updated Program.cs to configure rate limiting and CORS policies.
2026-02-19 03:25:01 +01:00

136 lines
4.2 KiB
C#

using EchoHub.Core.Constants;
using EchoHub.Core.DTOs;
using EchoHub.Core.Models;
using Microsoft.AspNetCore.SignalR.Client;
namespace EchoHub.Client.Services;
public sealed class EchoHubConnection : IAsyncDisposable
{
private readonly HubConnection _connection;
public event Action<MessageDto>? OnMessageReceived;
public event Action<string, string>? OnUserJoined;
public event Action<string, string>? OnUserLeft;
public event Action<ChannelDto>? OnChannelUpdated;
public event Action<UserPresenceDto>? OnUserStatusChanged;
public event Action<string>? OnError;
public event Action<string>? OnConnectionStateChanged;
public bool IsConnected => _connection.State == HubConnectionState.Connected;
public EchoHubConnection(string serverUrl, ApiClient apiClient)
{
var hubUrl = serverUrl.TrimEnd('/') + HubConstants.ChatHubPath;
_connection = new HubConnectionBuilder()
.WithUrl(hubUrl, options =>
{
options.AccessTokenProvider = () => apiClient.GetValidTokenAsync();
})
.WithAutomaticReconnect()
.Build();
RegisterHandlers();
_connection.Reconnecting += _ =>
{
OnConnectionStateChanged?.Invoke("Reconnecting...");
return Task.CompletedTask;
};
_connection.Reconnected += _ =>
{
OnConnectionStateChanged?.Invoke("Connected");
return Task.CompletedTask;
};
_connection.Closed += _ =>
{
OnConnectionStateChanged?.Invoke("Disconnected");
return Task.CompletedTask;
};
}
private void RegisterHandlers()
{
_connection.On<MessageDto>(nameof(Core.Contracts.IEchoHubClient.ReceiveMessage), message =>
{
OnMessageReceived?.Invoke(message);
});
_connection.On<string, string>(nameof(Core.Contracts.IEchoHubClient.UserJoined), (channelName, username) =>
{
OnUserJoined?.Invoke(channelName, username);
});
_connection.On<string, string>(nameof(Core.Contracts.IEchoHubClient.UserLeft), (channelName, username) =>
{
OnUserLeft?.Invoke(channelName, username);
});
_connection.On<ChannelDto>(nameof(Core.Contracts.IEchoHubClient.ChannelUpdated), channel =>
{
OnChannelUpdated?.Invoke(channel);
});
_connection.On<UserPresenceDto>(nameof(Core.Contracts.IEchoHubClient.UserStatusChanged), presence =>
{
OnUserStatusChanged?.Invoke(presence);
});
_connection.On<string>(nameof(Core.Contracts.IEchoHubClient.Error), message =>
{
OnError?.Invoke(message);
});
}
public async Task ConnectAsync()
{
OnConnectionStateChanged?.Invoke("Connecting...");
await _connection.StartAsync();
OnConnectionStateChanged?.Invoke("Connected");
}
public async Task DisconnectAsync()
{
await _connection.StopAsync();
OnConnectionStateChanged?.Invoke("Disconnected");
}
public async Task<List<MessageDto>> JoinChannelAsync(string channelName)
{
return await _connection.InvokeAsync<List<MessageDto>>("JoinChannel", channelName);
}
public async Task LeaveChannelAsync(string channelName)
{
await _connection.InvokeAsync("LeaveChannel", channelName);
}
public async Task SendMessageAsync(string channelName, string content)
{
await _connection.InvokeAsync("SendMessage", channelName, content);
}
public async Task<List<MessageDto>> GetHistoryAsync(string channelName, int count = HubConstants.DefaultHistoryCount)
{
return await _connection.InvokeAsync<List<MessageDto>>("GetChannelHistory", channelName, count);
}
public async Task UpdateStatusAsync(UserStatus status, string? statusMessage = null)
{
await _connection.InvokeAsync("UpdateStatus", status, statusMessage);
}
public async Task<List<UserPresenceDto>> GetOnlineUsersAsync(string channelName)
{
return await _connection.InvokeAsync<List<UserPresenceDto>>("GetOnlineUsers", channelName);
}
public async ValueTask DisposeAsync()
{
await _connection.DisposeAsync();
}
}