Compare commits
14 Commits
bf12c889f3
...
5aab46a221
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5aab46a221 | ||
|
|
9fee7ea381 | ||
|
|
cfe5df4b1d | ||
|
|
31ccd93b0d | ||
|
|
48970a1e13 | ||
|
|
0614b205bd | ||
|
|
b533634e14 | ||
|
|
766e4e6d27 | ||
|
|
878e927be9 | ||
|
|
24a0efb979 | ||
|
|
8e450f7934 | ||
|
|
77bbcfe4f1 | ||
|
|
c8eacc1d54 | ||
|
|
bea08ce06c |
6
DigitalData.Auth.Abstractions/ClientExtensions.cs
Normal file
6
DigitalData.Auth.Abstractions/ClientExtensions.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace DigitalData.Auth.Abstractions;
|
||||||
|
|
||||||
|
public static class ClientExtensions
|
||||||
|
{
|
||||||
|
public static bool IsConnectionFailed(this IAuthClient client) => client.ConnectionError is not null;
|
||||||
|
}
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
namespace DigitalData.Auth.Abstractions;
|
namespace DigitalData.Auth.Abstractions;
|
||||||
|
|
||||||
public interface IAuthClient
|
public interface IAuthClient : IAuthClientHandler
|
||||||
{
|
{
|
||||||
Task ReceiveMessage(string user, string message);
|
bool IsConnected { get; }
|
||||||
|
|
||||||
|
Exception? ConnectionError { get; }
|
||||||
|
|
||||||
|
bool IsConnectionFailed => ConnectionError is not null;
|
||||||
|
|
||||||
|
Task StartAsync();
|
||||||
|
|
||||||
|
Task<bool> TryStartAsync();
|
||||||
}
|
}
|
||||||
6
DigitalData.Auth.Abstractions/IAuthClientHandler.cs
Normal file
6
DigitalData.Auth.Abstractions/IAuthClientHandler.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace DigitalData.Auth.Abstractions;
|
||||||
|
|
||||||
|
public interface IAuthClientHandler
|
||||||
|
{
|
||||||
|
Task ReceiveMessageAsync(string user, string message);
|
||||||
|
}
|
||||||
@@ -9,6 +9,8 @@ public class AuthClient : IAuthClient
|
|||||||
{
|
{
|
||||||
private readonly HubConnection _connection;
|
private readonly HubConnection _connection;
|
||||||
|
|
||||||
|
private readonly Lazy<Task<bool>> _lazyInitiator;
|
||||||
|
|
||||||
private readonly ILogger? _logger;
|
private readonly ILogger? _logger;
|
||||||
|
|
||||||
private readonly ClientParams _params;
|
private readonly ClientParams _params;
|
||||||
@@ -19,14 +21,45 @@ public class AuthClient : IAuthClient
|
|||||||
.WithUrl(paramsOptions.Value.Url)
|
.WithUrl(paramsOptions.Value.Url)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_connection.On<string, string>(nameof(ReceiveMessage), ReceiveMessage);
|
_connection.On<string, string>(nameof(ReceiveMessageAsync), ReceiveMessageAsync);
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
_params = paramsOptions.Value;
|
_params = paramsOptions.Value;
|
||||||
|
|
||||||
|
_lazyInitiator = new(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _connection.StartAsync();
|
||||||
|
IsConnected = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
ConnectionError = ex;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartAsync() => await _connection.StartAsync();
|
public bool IsConnected { get; private set; } = false;
|
||||||
|
|
||||||
public Task ReceiveMessage(string user, string message) => _params.Events.OnMessageReceived(user, message, _logger);
|
public Exception? ConnectionError { get; private set; }
|
||||||
|
|
||||||
|
public async Task StartAsync() => await _lazyInitiator.Value;
|
||||||
|
|
||||||
|
public async Task<bool> TryStartAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _lazyInitiator.Value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ReceiveMessageAsync(string user, string message) => Task.Run(() => _params.Events.OnMessageReceived(user, message, _logger));
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,7 @@ namespace DigitalData.Auth.Client
|
|||||||
{
|
{
|
||||||
public class ClientEvents
|
public class ClientEvents
|
||||||
{
|
{
|
||||||
public Func<string, string, ILogger?, Task> OnMessageReceived { get; set; } = (user, message, logger)
|
public Action<string, string, ILogger?> OnMessageReceived { get; set; } = (user, message, logger)
|
||||||
=> Task.Run(
|
=> logger?.LogInformation("{user}: {message}", user, message);
|
||||||
() => logger?.LogInformation("{user}: {message}", user, message)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
public class ClientParams
|
public class ClientParams
|
||||||
{
|
{
|
||||||
public required string Url { get; init; }
|
#pragma warning disable CS8618 // throw exception in DI extension if it not set
|
||||||
|
public string Url { get; set; }
|
||||||
|
#pragma warning restore CS8618
|
||||||
|
|
||||||
public readonly ClientEvents Events = new();
|
public readonly ClientEvents Events = new();
|
||||||
}
|
}
|
||||||
19
DigitalData.Auth.Client/DIExtensions.cs
Normal file
19
DigitalData.Auth.Client/DIExtensions.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using DigitalData.Auth.Abstractions;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
|
namespace DigitalData.Auth.Client;
|
||||||
|
|
||||||
|
public static class DIExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddAuthHubClient(this IServiceCollection services, Action<ClientParams> options)
|
||||||
|
{
|
||||||
|
services
|
||||||
|
.Configure(options)
|
||||||
|
.AddSingleton<IAuthClient, AuthClient>()
|
||||||
|
.TryAddSingleton<HubConnectionBuilder>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
78
DigitalData.Auth.Tests/Client/AuthClientTests.cs
Normal file
78
DigitalData.Auth.Tests/Client/AuthClientTests.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using DigitalData.Auth.Abstractions;
|
||||||
|
using DigitalData.Auth.Client;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace DigitalData.Auth.Tests.Client;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class AuthClientTests
|
||||||
|
{
|
||||||
|
private static readonly string HubUrl = "https://localhost:7192/auth-hub";
|
||||||
|
|
||||||
|
private Func<Action<ClientParams>, ServiceProvider> Build;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Build = options => new ServiceCollection()
|
||||||
|
.AddAuthHubClient(options)
|
||||||
|
.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task StartAsync_ShouldConnectSuccessfully()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var provider = Build(opt => opt.Url = HubUrl);
|
||||||
|
var client = provider.GetRequiredService<IAuthClient>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await client.TryStartAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(client.IsConnected);
|
||||||
|
Assert.That(!client.IsConnectionFailed);
|
||||||
|
Assert.That(client.ConnectionError, Is.Null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ReceiveMessage_ShouldCallOnMessageReceived()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string rcv_user = string.Empty;
|
||||||
|
string rcv_msg = string.Empty;
|
||||||
|
|
||||||
|
// Sender client
|
||||||
|
using var provider_sender = Build(opt => opt.Url = HubUrl);
|
||||||
|
var sender_client = provider_sender.GetRequiredService<IAuthClient>();
|
||||||
|
await sender_client.TryStartAsync();
|
||||||
|
|
||||||
|
// Receiver client
|
||||||
|
using var provider_receiver = Build(opt =>
|
||||||
|
{
|
||||||
|
opt.Url = HubUrl;
|
||||||
|
opt.Events.OnMessageReceived = (user, message, logger) =>
|
||||||
|
{
|
||||||
|
rcv_user = user;
|
||||||
|
rcv_msg = message;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
var client_receiver = provider_receiver.GetRequiredService<IAuthClient>();
|
||||||
|
|
||||||
|
string user = "user";
|
||||||
|
string message = "message";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await client_receiver.ReceiveMessageAsync(user, message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(rcv_user, Is.EqualTo(user));
|
||||||
|
Assert.That(rcv_msg, Is.EqualTo(message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
@@ -9,12 +9,6 @@
|
|||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="NewFolder\**" />
|
|
||||||
<EmbeddedResource Remove="NewFolder\**" />
|
|
||||||
<None Remove="NewFolder\**" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
@@ -25,6 +19,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\DigitalData.Auth.Client\DigitalData.Auth.Client.csproj" />
|
<ProjectReference Include="..\DigitalData.Auth.Client\DigitalData.Auth.Client.csproj" />
|
||||||
|
<ProjectReference Include="..\src\DigitalData.Auth.API\DigitalData.Auth.API.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ using Microsoft.AspNetCore.SignalR;
|
|||||||
|
|
||||||
namespace DigitalData.Auth.API.Hubs;
|
namespace DigitalData.Auth.API.Hubs;
|
||||||
|
|
||||||
public class AuthHub : Hub<IAuthClient>
|
public class AuthHub : Hub<IAuthClientHandler>
|
||||||
{
|
{
|
||||||
public async Task SendMessage(string user, string message)
|
public async Task SendMessage(string user, string message)
|
||||||
=> await Clients.All.ReceiveMessage(user, message);
|
=> await Clients.All.ReceiveMessageAsync(user, message);
|
||||||
|
|
||||||
public async Task SendMessageToCaller(string user, string message)
|
public async Task SendMessageToCaller(string user, string message)
|
||||||
=> await Clients.Caller.ReceiveMessage(user, message);
|
=> await Clients.Caller.ReceiveMessageAsync(user, message);
|
||||||
|
|
||||||
public async Task SendMessageToGroup(string user, string message)
|
public async Task SendMessageToGroup(string user, string message)
|
||||||
=> await Clients.Group("Auth.API Consumers").ReceiveMessage(user, message);
|
=> await Clients.Group("Auth.API Consumers").ReceiveMessageAsync(user, message);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user