feat: add password protection for channels

- Updated IChatService to include password parameter in JoinChannelAsync method.
- Modified ChannelDto and related models to support password functionality.
- Implemented password handling in ChannelService for channel creation and membership validation.
- Enhanced IrcCommandHandler to manage channel join requests with passwords.
- Added ChannelPasswordDialog for user input when joining protected channels.
- Created database migration to add PasswordHash column to Channels table.
- Updated tests to cover new password functionality in channel joining and management.
This commit is contained in:
HueByte
2026-07-16 03:13:03 +02:00
parent 15187c4665
commit 3ca9dbfd91
31 changed files with 1056 additions and 96 deletions
@@ -5,6 +5,20 @@ using Microsoft.AspNetCore.SignalR.Client;
namespace EchoHub.Client.Services;
/// <summary>
/// Thrown when joining a channel fails because a password is required or incorrect.
/// The UI catches this to prompt the user and retry.
/// </summary>
public sealed class ChannelPasswordRequiredException : Exception
{
public string ChannelName { get; }
public ChannelPasswordRequiredException(string channelName, string message) : base(message)
{
ChannelName = channelName;
}
}
public sealed class EchoHubConnection : IAsyncDisposable
{
private readonly HubConnection _connection;
@@ -134,11 +148,15 @@ public sealed class EchoHubConnection : IAsyncDisposable
OnConnectionStateChanged?.Invoke("Disconnected");
}
public async Task<List<MessageDto>> JoinChannelAsync(string channelName)
public async Task<List<MessageDto>> JoinChannelAsync(string channelName, string? password = null)
{
var result = await _connection.InvokeAsync<JoinChannelResult>("JoinChannel", channelName);
var result = await _connection.InvokeAsync<JoinChannelResult>("JoinChannel", channelName, password);
if (!result.Success)
{
if (result.PasswordRequired)
throw new ChannelPasswordRequiredException(channelName, result.Error ?? "Channel is password protected.");
throw new InvalidOperationException(result.Error ?? "Failed to join channel.");
}
return DecryptMessages(result.History);
}