2using System.Collections.Concurrent;
3using System.Collections.Generic;
6using System.Threading.Tasks;
8using Microsoft.AspNetCore.SignalR;
9using Microsoft.Extensions.Logging;
23 where THubMethods : class
39 readonly ILogger<ComprehensiveHubContext<THub, THubMethods>>
logger;
44 readonly ConcurrentDictionary<long, Dictionary<string, HubCallerContext>>
userConnections;
47 public event Func<IAuthenticationContext, Func<IEnumerable<string>, Task>, CancellationToken, ValueTask>?
OnConnectionMapGroups;
59 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
61 userConnections =
new ConcurrentDictionary<long, Dictionary<string, HubCallerContext>>();
67 ArgumentNullException.ThrowIfNull(user);
68 var connectionIds =
userConnections.GetOrAdd(user.Require(x => x.Id), _ =>
new Dictionary<string, HubCallerContext>());
70 return connectionIds.Keys.ToList();
76 ArgumentNullException.ThrowIfNull(authenticationContext);
77 ArgumentNullException.ThrowIfNull(hub);
79 var userId = authenticationContext.
User.Require(x => x.Id);
80 var context = hub.Context;
82 "Mapping user {userId} to hub connection ID: {connectionId}",
84 context.ConnectionId);
87 authenticationContext,
90 mappedGroups = mappedGroups.ToList();
92 "Mapping connection ID {connectionId} with groups: {mappedGroups}",
94 String.Join(
", ", mappedGroups));
97 group => hub.Groups.AddToGroupAsync(context.ConnectionId, group, cancellationToken)));
100 ?? ValueTask.CompletedTask;
103 _ =>
new Dictionary<string, HubCallerContext>
105 { context.ConnectionId, context },
110 old[context.ConnectionId] = context;
121 ArgumentNullException.ThrowIfNull(connectionId);
124 if (kvp.Value.Remove(connectionId))
125 logger.LogTrace(
"User {userId} disconnected connection ID: {connectionId}", kvp.Key, connectionId);
131 ArgumentNullException.ThrowIfNull(user);
132 var uid = user.Require(x => x.Id);
133 logger.LogTrace(
"NotifyAndAbortUnauthedConnections. UID {userId}", uid);
135 List<HubCallerContext>? connections =
null;
138 _ =>
new Dictionary<string, HubCallerContext>(),
143 connections = old.Values.ToList();
150 if (connections !=
null)
151 foreach (var context
in connections)
An implementation of IHubContext<THub> with User connection ID mapping.
IHubClients< THubMethods > Clients
readonly ILogger< ComprehensiveHubContext< THub, THubMethods > > logger
The ILogger for the ComprehensiveHubContext<THub, THubMethods>.
ValueTask UserConnected(IAuthenticationContext authenticationContext, THub hub, CancellationToken cancellationToken)
To be called when a hub connection is made.A ValueTask representing the running operation.
readonly IHubContext< THub, THubMethods > wrappedHubContext
The IHubContext<THub> being wrapped.
ComprehensiveHubContext(IHubContext< THub, THubMethods > wrappedHubContext, ILogger< ComprehensiveHubContext< THub, THubMethods > > logger)
Initializes a new instance of the ComprehensiveHubContext<THub, THubMethods> class.
readonly ConcurrentDictionary< long, Dictionary< string, HubCallerContext > > userConnections
Map of User Api.Models.EntityId.Ids to their associated HubCallerContexts.
List< string > UserConnectionIds(User user)
Gets a List<T> of current connection IDs for a given user .A List<T> representing the active connecti...
Func< IAuthenticationContext, Func< IEnumerable< string >, Task >, CancellationToken, ValueTask >? OnConnectionMapGroups
void AbortUnauthedConnections(User user)
Aborts the connections associated with the given user .
void UserDisconnected(string connectionId)
To be called when a hub connection is terminated.
Base class for Hub<T>s that want to map their connection IDs to Models.PermissionSets.
For creating and accessing authentication contexts.
User User
The authenticated user.
A IHubContext<THub> that maps Users to their connection IDs.
Handles mapping connection IDs to Users for a given THub .