minor refactoring

This commit is contained in:
rootdarkarchon
2022-08-22 14:24:47 +02:00
parent 6c243d0247
commit f9e4fd4f2d
38 changed files with 1391 additions and 854 deletions

View File

@@ -0,0 +1,14 @@
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.SignalR;
namespace MareSynchronosServer.Hubs
{
public class IdBasedUserIdProvider : IUserIdProvider
{
public string GetUserId(HubConnectionContext context)
{
return context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
}
}
}

View File

@@ -18,7 +18,7 @@ namespace MareSynchronosServer.Hubs
private List<string> OnlineAdmins => _dbContext.Users.Where(u => !string.IsNullOrEmpty(u.CharacterIdentification) && (u.IsModerator || u.IsAdmin))
.Select(u => u.UID).ToList();
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendAdminChangeModeratorStatus)]
public async Task ChangeModeratorStatus(string uid, bool isModerator)
{
@@ -33,7 +33,7 @@ namespace MareSynchronosServer.Hubs
await Clients.Users(user.UID).SendAsync(Api.OnAdminForcedReconnect).ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendAdminDeleteBannedUser)]
public async Task DeleteBannedUser(BannedUserDto dto)
{
@@ -51,7 +51,7 @@ namespace MareSynchronosServer.Hubs
await Clients.Users(OnlineAdmins).SendAsync(Api.OnAdminDeleteBannedUser, dto).ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendAdminDeleteForbiddenFile)]
public async Task DeleteForbiddenFile(ForbiddenFileDto dto)
{
@@ -69,7 +69,7 @@ namespace MareSynchronosServer.Hubs
await Clients.Users(OnlineAdmins).SendAsync(Api.OnAdminDeleteForbiddenFile, dto).ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeAdminGetBannedUsers)]
public async Task<List<BannedUserDto>> GetBannedUsers()
{
@@ -82,7 +82,7 @@ namespace MareSynchronosServer.Hubs
}).ToListAsync().ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeAdminGetForbiddenFiles)]
public async Task<List<ForbiddenFileDto>> GetForbiddenFiles()
{
@@ -95,7 +95,7 @@ namespace MareSynchronosServer.Hubs
}).ToListAsync().ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeAdminGetOnlineUsers)]
public async Task<List<OnlineUserDto>> AdminGetOnlineUsers()
{
@@ -110,7 +110,7 @@ namespace MareSynchronosServer.Hubs
}).ToListAsync().ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendAdminUpdateOrAddBannedUser)]
public async Task UpdateOrAddBannedUser(BannedUserDto dto)
{
@@ -142,7 +142,7 @@ namespace MareSynchronosServer.Hubs
}
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendAdminUpdateOrAddForbiddenFile)]
public async Task UpdateOrAddForbiddenFile(ForbiddenFileDto dto)
{

View File

@@ -7,9 +7,10 @@ using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronosServer.Metrics;
using MareSynchronosShared.Authentication;
using MareSynchronosShared.Metrics;
using MareSynchronosShared.Models;
using MareSynchronosShared.Protos;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
@@ -21,7 +22,7 @@ namespace MareSynchronosServer.Hubs
{
private string BasePath => _configuration["CacheDirectory"];
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendFileAbortUpload)]
public async Task AbortUpload()
{
@@ -32,7 +33,7 @@ namespace MareSynchronosServer.Hubs
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendFileDeleteAllFiles)]
public async Task DeleteAllFiles()
{
@@ -44,8 +45,10 @@ namespace MareSynchronosServer.Hubs
var fi = new FileInfo(Path.Combine(BasePath, file.Hash));
if (fi.Exists)
{
MareMetrics.FilesTotalSize.Dec(fi.Length);
MareMetrics.FilesTotal.Dec();
await _metricsClient.DecGaugeAsync(new GaugeRequest()
{GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = fi.Length}).ConfigureAwait(false);
await _metricsClient.DecGaugeAsync(new GaugeRequest()
{ GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1}).ConfigureAwait(false);
fi.Delete();
}
}
@@ -53,7 +56,7 @@ namespace MareSynchronosServer.Hubs
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeGetFilesSizes)]
public async Task<List<DownloadFileDto>> GetFilesSizes(List<string> hashes)
{
@@ -97,7 +100,7 @@ namespace MareSynchronosServer.Hubs
return response;
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeFileIsUploadFinished)]
public async Task<bool> IsUploadFinished()
{
@@ -106,7 +109,7 @@ namespace MareSynchronosServer.Hubs
.AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded).ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeFileSendFiles)]
public async Task<List<UploadFileDto>> SendFiles(List<string> fileListHashes)
{
@@ -156,7 +159,7 @@ namespace MareSynchronosServer.Hubs
return notCoveredFiles.Values.ToList();
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendFileUploadFileStreamAsync)]
public async Task UploadFileStreamAsync(string hash, IAsyncEnumerable<byte[]> fileContent)
{
@@ -224,8 +227,10 @@ namespace MareSynchronosServer.Hubs
relatedFile = _dbContext.Files.Single(f => f.Hash == hash);
relatedFile.Uploaded = true;
MareMetrics.FilesTotal.Inc();
MareMetrics.FilesTotalSize.Inc(length);
await _metricsClient.IncGaugeAsync(new GaugeRequest()
{ GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = length }).ConfigureAwait(false);
await _metricsClient.IncGaugeAsync(new GaugeRequest()
{ GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1 }).ConfigureAwait(false);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
_logger.LogInformation("File {hash} added to DB", hash);

View File

@@ -2,9 +2,10 @@
using System.Linq;
using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronosServer.Metrics;
using MareSynchronosShared.Authentication;
using MareSynchronosShared.Metrics;
using MareSynchronosShared.Models;
using MareSynchronosShared.Protos;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
@@ -14,7 +15,7 @@ namespace MareSynchronosServer.Hubs
{
public partial class MareHub
{
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendUserDeleteAccount)]
public async Task DeleteAccount()
{
@@ -37,10 +38,8 @@ namespace MareSynchronosServer.Hubs
await Task.Delay(1000).ConfigureAwait(false);
}
SecretKeyAuthenticationHandler.RemoveAuthentication(userid);
await _authServiceClient.RemoveAuthAsync(new RemoveAuthRequest() { Uid = userid }).ConfigureAwait(false);
MareMetrics.Pairs.Dec(ownPairData.Count);
MareMetrics.PairsPaused.Dec(ownPairData.Count(c => c.IsPaused));
_dbContext.RemoveRange(ownPairData);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
@@ -56,9 +55,12 @@ namespace MareSynchronosServer.Hubs
}, userEntry.CharacterIdentification).ConfigureAwait(false);
}
MareMetrics.Pairs.Dec(otherPairData.Count);
MareMetrics.PairsPaused.Dec(otherPairData.Count(c => c.IsPaused));
MareMetrics.UsersRegistered.Dec();
await _metricsClient.DecGaugeAsync(new GaugeRequest()
{ GaugeName = MetricsAPI.GaugePairs, Value = ownPairData.Count + otherPairData.Count }).ConfigureAwait(false);
await _metricsClient.DecGaugeAsync(new GaugeRequest()
{ GaugeName = MetricsAPI.GaugePairsPaused, Value = ownPairData.Count(c => c.IsPaused) }).ConfigureAwait(false);
await _metricsClient.DecGaugeAsync(new GaugeRequest()
{ GaugeName = MetricsAPI.GaugeUsersRegistered, Value = 1 }).ConfigureAwait(false);
_dbContext.RemoveRange(otherPairData);
_dbContext.Remove(userEntry);
@@ -66,7 +68,7 @@ namespace MareSynchronosServer.Hubs
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeUserGetOnlineCharacters)]
public async Task<List<string>> GetOnlineCharacters()
{
@@ -88,7 +90,7 @@ namespace MareSynchronosServer.Hubs
return otherEntries.Select(e => e.User.CharacterIdentification).Distinct().ToList();
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeUserGetPairedClients)]
public async Task<List<ClientPairDto>> GetPairedClients()
{
@@ -126,7 +128,7 @@ namespace MareSynchronosServer.Hubs
}).ToList();
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.InvokeUserPushCharacterDataToVisibleClients)]
public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
{
@@ -158,11 +160,13 @@ namespace MareSynchronosServer.Hubs
await Clients.Users(otherEntries).SendAsync(Api.OnUserReceiveCharacterData, characterCache, user.CharacterIdentification).ConfigureAwait(false);
MareMetrics.UserPushData.Inc();
MareMetrics.UserPushDataTo.Inc(otherEntries.Count);
await _metricsClient.IncreaseCounterAsync(new IncreaseCounterRequest()
{ CounterName = MetricsAPI.CounterUserPushData, Value = 1 }).ConfigureAwait(false);
await _metricsClient.IncreaseCounterAsync(new IncreaseCounterRequest()
{ CounterName = MetricsAPI.CounterUserPushDataTo, Value = otherEntries.Count }).ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendUserPairedClientAddition)]
public async Task SendPairedClientAddition(string uid)
{
@@ -215,10 +219,10 @@ namespace MareSynchronosServer.Hubs
}
}
MareMetrics.Pairs.Inc();
await _metricsClient.IncGaugeAsync(new GaugeRequest() {GaugeName = MetricsAPI.GaugePairs, Value = 1}).ConfigureAwait(false);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendUserPairedClientPauseChange)]
public async Task SendPairedClientPauseChange(string otherUserUid, bool isPaused)
{
@@ -255,15 +259,15 @@ namespace MareSynchronosServer.Hubs
if (isPaused)
{
MareMetrics.PairsPaused.Inc();
await _metricsClient.IncGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugePairsPaused, Value = 1 }).ConfigureAwait(false);
}
else
{
MareMetrics.PairsPaused.Dec();
await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugePairsPaused, Value = 1 }).ConfigureAwait(false);
}
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
[HubMethodName(Api.SendUserPairedClientRemoval)]
public async Task SendPairedClientRemoval(string uid)
{
@@ -303,7 +307,7 @@ namespace MareSynchronosServer.Hubs
}
}
MareMetrics.Pairs.Dec();
await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugePairs, Value = 1 }).ConfigureAwait(false);
}
private ClientPair OppositeEntry(string otherUID) =>

View File

@@ -4,10 +4,11 @@ using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronosServer.Metrics;
using MareSynchronosShared.Authentication;
using MareSynchronosShared.Data;
using MareSynchronosShared.Metrics;
using MareSynchronosShared.Models;
using MareSynchronosShared.Protos;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
@@ -19,14 +20,19 @@ namespace MareSynchronosServer.Hubs
{
public partial class MareHub : Hub
{
private readonly MetricsService.MetricsServiceClient _metricsClient;
private readonly AuthService.AuthServiceClient _authServiceClient;
private readonly SystemInfoService _systemInfoService;
private readonly IConfiguration _configuration;
private readonly IHttpContextAccessor contextAccessor;
private readonly ILogger<MareHub> _logger;
private readonly MareDbContext _dbContext;
public MareHub(MareDbContext mareDbContext, ILogger<MareHub> logger, SystemInfoService systemInfoService, IConfiguration configuration, IHttpContextAccessor contextAccessor)
public MareHub(MetricsService.MetricsServiceClient metricsClient, AuthService.AuthServiceClient authServiceClient,
MareDbContext mareDbContext, ILogger<MareHub> logger, SystemInfoService systemInfoService, IConfiguration configuration, IHttpContextAccessor contextAccessor)
{
_metricsClient = metricsClient;
_authServiceClient = authServiceClient;
_systemInfoService = systemInfoService;
_configuration = configuration;
this.contextAccessor = contextAccessor;
@@ -35,10 +41,10 @@ namespace MareSynchronosServer.Hubs
}
[HubMethodName(Api.InvokeHeartbeat)]
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
public async Task<ConnectionDto> Heartbeat(string characterIdentification)
{
MareMetrics.InitializedConnections.Inc();
await _metricsClient.IncreaseCounterAsync(new() { CounterName = MetricsAPI.CounterInitializedConnections, Value = 1 }).ConfigureAwait(false);
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
@@ -60,7 +66,7 @@ namespace MareSynchronosServer.Hubs
}
else if (string.IsNullOrEmpty(user.CharacterIdentification))
{
MareMetrics.AuthorizedConnections.Inc();
await _metricsClient.IncGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeAuthorizedConnections, Value = 1 }).ConfigureAwait(false);
}
user.LastLoggedIn = DateTime.UtcNow;
@@ -81,32 +87,34 @@ namespace MareSynchronosServer.Hubs
};
}
public override Task OnConnectedAsync()
public override async Task OnConnectedAsync()
{
_logger.LogInformation("Connection from {ip}", contextAccessor.GetIpAddress());
MareMetrics.Connections.Inc();
return base.OnConnectedAsync();
await _metricsClient.IncGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeConnections, Value = 1 }).ConfigureAwait(false);
await base.OnConnectedAsync().ConfigureAwait(false);
}
public override async Task OnDisconnectedAsync(Exception exception)
{
MareMetrics.Connections.Dec();
await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeConnections, Value = 1 }).ConfigureAwait(false);
var user = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == AuthenticatedUserId).ConfigureAwait(false);
if (user != null && !string.IsNullOrEmpty(user.CharacterIdentification))
{
MareMetrics.AuthorizedConnections.Dec();
await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeAuthorizedConnections, Value = 1 }).ConfigureAwait(false);
_logger.LogInformation("Disconnect from {id}", AuthenticatedUserId);
var query =
from userToOther in _dbContext.ClientPairs
join otherToUser in _dbContext.ClientPairs
on new {
on new
{
user = userToOther.UserUID,
other = userToOther.OtherUserUID
} equals new {
} equals new
{
user = otherToUser.OtherUserUID,
other = otherToUser.UserUID
}
@@ -118,7 +126,7 @@ namespace MareSynchronosServer.Hubs
var otherEntries = await query.ToListAsync().ConfigureAwait(false);
await Clients.Users(otherEntries).SendAsync(Api.OnUserRemoveOnlinePairedPlayer, user.CharacterIdentification).ConfigureAwait(false);
_dbContext.RemoveRange(_dbContext.Files.Where(f => !f.Uploaded && f.UploaderUID == user.UID));
user.CharacterIdentification = null;
@@ -128,24 +136,6 @@ namespace MareSynchronosServer.Hubs
await base.OnDisconnectedAsync(exception).ConfigureAwait(false);
}
public static string GenerateRandomString(int length, string allowableChars = null)
{
if (string.IsNullOrEmpty(allowableChars))
allowableChars = @"ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
// Generate random data
var rnd = RandomNumberGenerator.GetBytes(length);
// Generate the output string
var allowable = allowableChars.ToCharArray();
var l = allowable.Length;
var chars = new char[length];
for (var i = 0; i < length; i++)
chars[i] = allowable[rnd[i] % l];
return new string(chars);
}
protected string AuthenticatedUserId => Context.User?.Claims?.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown";
protected async Task<User> GetAuthenticatedUserUntrackedAsync()

View File

@@ -0,0 +1,116 @@
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using AspNetCoreRateLimit;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace MareSynchronosServer.Hubs;
public class SignalRLimitFilter : IHubFilter
{
private readonly IRateLimitProcessor _processor;
private readonly IHttpContextAccessor accessor;
private readonly ILogger<SignalRLimitFilter> logger;
private static readonly SemaphoreSlim ConnectionLimiterSemaphore = new(20);
private static readonly SemaphoreSlim DisconnectLimiterSemaphore = new(20);
public SignalRLimitFilter(
IOptions<IpRateLimitOptions> options, IProcessingStrategy processing, IIpPolicyStore policyStore, IHttpContextAccessor accessor, ILogger<SignalRLimitFilter> logger)
{
_processor = new IpRateLimitProcessor(options?.Value, policyStore, processing);
this.accessor = accessor;
this.logger = logger;
}
public async ValueTask<object> InvokeMethodAsync(
HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
{
var ip = accessor.GetIpAddress();
var client = new ClientRequestIdentity
{
ClientIp = ip,
Path = invocationContext.HubMethodName,
HttpVerb = "ws",
ClientId = invocationContext.Context.UserIdentifier
};
foreach (var rule in await _processor.GetMatchingRulesAsync(client).ConfigureAwait(false))
{
var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false);
if (counter.Count > rule.Limit)
{
var authUserId = invocationContext.Context.User.Claims?.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown";
var retry = counter.Timestamp.RetryAfterFrom(rule);
logger.LogWarning("Method rate limit triggered from {ip}/{authUserId}: {method}", ip, authUserId, invocationContext.HubMethodName);
throw new HubException($"call limit {retry}");
}
}
return await next(invocationContext).ConfigureAwait(false);
}
// Optional method
public async Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next)
{
await ConnectionLimiterSemaphore.WaitAsync().ConfigureAwait(false);
var ip = accessor.GetIpAddress();
var client = new ClientRequestIdentity
{
ClientIp = ip,
Path = "Connect",
HttpVerb = "ws",
};
foreach (var rule in await _processor.GetMatchingRulesAsync(client).ConfigureAwait(false))
{
var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false);
if (counter.Count > rule.Limit)
{
var retry = counter.Timestamp.RetryAfterFrom(rule);
logger.LogWarning("Connection rate limit triggered from {ip}", ip);
ConnectionLimiterSemaphore.Release();
throw new HubException($"Connection rate limit {retry}");
}
}
try
{
await Task.Delay(250).ConfigureAwait(false);
await next(context).ConfigureAwait(false);
}
catch (Exception ex)
{
logger.LogWarning(ex, "Error on OnConnectedAsync");
}
finally
{
ConnectionLimiterSemaphore.Release();
}
}
public async Task OnDisconnectedAsync(
HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next)
{
await DisconnectLimiterSemaphore.WaitAsync().ConfigureAwait(false);
if (exception != null)
{
logger.LogWarning(exception, "InitialException on OnDisconnectedAsync");
}
try
{
await next(context, exception).ConfigureAwait(false);
await Task.Delay(250).ConfigureAwait(false);
}
catch (Exception e)
{
logger.LogWarning(e, "ThrownException on OnDisconnectedAsync");
}
finally
{
DisconnectLimiterSemaphore.Release();
}
}
}