Files
Govor/Govor.API/Hubs/PresenceHub.cs
T
Artemy be0edb0f94 Refactor user ID access in SignalR hubs and add online user tracking
Introduces IHubUserAccessor and its implementation to centralize user ID retrieval from SignalR HubCallerContext, replacing duplicated logic in ChatsHub, FriendsHub, and PresenceHub. Moves extension and mapping files to a Common directory, adds UserToUserDtoMappingAction for online status mapping, and implements OnlineUserStore with tests for tracking online users. Updates dependency injection and test code to use the new abstractions.
2025-07-23 22:21:51 +07:00

71 lines
2.2 KiB
C#

using Govor.API.Common.SignalR.Helpers;
using Govor.Application.Interfaces.UserOnlineStatus;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR;
namespace Govor.API.Hubs;
[Authorize(Roles = "Admin, User")]
[Route("hubs/presence")]
public class PresenceHub : Hub
{
private readonly ILogger<PresenceHub> _logger;
private readonly IUserNotificationScopeService _notificationScopeService;
private readonly IOnlineUserStore _onlineUserStore;
private readonly IHubUserAccessor _userAccessor;
public PresenceHub(
ILogger<PresenceHub> logger,
IUserNotificationScopeService notificationScopeService,
IOnlineUserStore onlineUserStore,
IHubUserAccessor userAccessor)
{
_logger = logger;
_notificationScopeService = notificationScopeService;
_onlineUserStore = onlineUserStore;
_userAccessor = userAccessor;
}
public override async Task OnConnectedAsync()
{
var userId = _userAccessor.GetUserId(Context);
if (userId == Guid.Empty)
{
_logger.LogWarning("User connected with invalid UserID claim.");
Context.Abort();
return;
}
_onlineUserStore.SetOnlineUser(userId);
await Groups.AddToGroupAsync(Context.ConnectionId, userId.ToString());
var friends = await _notificationScopeService.GetNotifiedUsers(userId);
foreach (var recipient in friends)
{
await Clients.Group(recipient.ToString())
.SendAsync("UserOnline", userId);
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
var userId = _userAccessor.GetUserId(Context, true);
if (userId == Guid.Empty) return;
_onlineUserStore.SetOfflineUser(userId);
var friends = await _notificationScopeService.GetNotifiedUsers(userId);
foreach (var recipient in friends)
{
await Clients.Group(recipient.ToString())
.SendAsync("UserOffline", userId);
}
await base.OnDisconnectedAsync(exception);
}
}