mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 16:42:50 -05:00
Run formatting (#2230)
This commit is contained in:
@ -3,91 +3,90 @@ using Bit.Core.Settings;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public class AzureQueueHostedService : IHostedService, IDisposable
|
||||
{
|
||||
public class AzureQueueHostedService : IHostedService, IDisposable
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHubContext<NotificationsHub> _hubContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
private Task _executingTask;
|
||||
private CancellationTokenSource _cts;
|
||||
private QueueClient _queueClient;
|
||||
|
||||
public AzureQueueHostedService(
|
||||
ILogger<AzureQueueHostedService> logger,
|
||||
IHubContext<NotificationsHub> hubContext,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHubContext<NotificationsHub> _hubContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
_logger = logger;
|
||||
_hubContext = hubContext;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
private Task _executingTask;
|
||||
private CancellationTokenSource _cts;
|
||||
private QueueClient _queueClient;
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
_executingTask = ExecuteAsync(_cts.Token);
|
||||
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
|
||||
}
|
||||
|
||||
public AzureQueueHostedService(
|
||||
ILogger<AzureQueueHostedService> logger,
|
||||
IHubContext<NotificationsHub> hubContext,
|
||||
GlobalSettings globalSettings)
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_executingTask == null)
|
||||
{
|
||||
_logger = logger;
|
||||
_hubContext = hubContext;
|
||||
_globalSettings = globalSettings;
|
||||
return;
|
||||
}
|
||||
_logger.LogWarning("Stopping service.");
|
||||
_cts.Cancel();
|
||||
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
_executingTask = ExecuteAsync(_cts.Token);
|
||||
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
|
||||
}
|
||||
public void Dispose()
|
||||
{ }
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
private async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_queueClient = new QueueClient(_globalSettings.Notifications.ConnectionString, "notifications");
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (_executingTask == null)
|
||||
try
|
||||
{
|
||||
return;
|
||||
}
|
||||
_logger.LogWarning("Stopping service.");
|
||||
_cts.Cancel();
|
||||
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{ }
|
||||
|
||||
private async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_queueClient = new QueueClient(_globalSettings.Notifications.ConnectionString, "notifications");
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
var messages = await _queueClient.ReceiveMessagesAsync(32);
|
||||
if (messages.Value?.Any() ?? false)
|
||||
{
|
||||
var messages = await _queueClient.ReceiveMessagesAsync(32);
|
||||
if (messages.Value?.Any() ?? false)
|
||||
foreach (var message in messages.Value)
|
||||
{
|
||||
foreach (var message in messages.Value)
|
||||
try
|
||||
{
|
||||
try
|
||||
await HubHelpers.SendNotificationToHubAsync(
|
||||
message.DecodeMessageText(), _hubContext, cancellationToken);
|
||||
await _queueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("Error processing dequeued message: " +
|
||||
$"{message.MessageId} x{message.DequeueCount}. {e.Message}", e);
|
||||
if (message.DequeueCount > 2)
|
||||
{
|
||||
await HubHelpers.SendNotificationToHubAsync(
|
||||
message.DecodeMessageText(), _hubContext, cancellationToken);
|
||||
await _queueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("Error processing dequeued message: " +
|
||||
$"{message.MessageId} x{message.DequeueCount}. {e.Message}", e);
|
||||
if (message.DequeueCount > 2)
|
||||
{
|
||||
await _queueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
else
|
||||
{
|
||||
_logger.LogError("Error processing messages.", e);
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogWarning("Done processing.");
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("Error processing messages.", e);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogWarning("Done processing.");
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,26 @@
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public class ConnectionCounter
|
||||
{
|
||||
public class ConnectionCounter
|
||||
private int _count = 0;
|
||||
|
||||
public void Increment()
|
||||
{
|
||||
private int _count = 0;
|
||||
Interlocked.Increment(ref _count);
|
||||
}
|
||||
|
||||
public void Increment()
|
||||
{
|
||||
Interlocked.Increment(ref _count);
|
||||
}
|
||||
public void Decrement()
|
||||
{
|
||||
Interlocked.Decrement(ref _count);
|
||||
}
|
||||
|
||||
public void Decrement()
|
||||
{
|
||||
Interlocked.Decrement(ref _count);
|
||||
}
|
||||
public void Reset()
|
||||
{
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
public int GetCount()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
public int GetCount()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Notifications.Controllers
|
||||
{
|
||||
public class InfoController : Controller
|
||||
{
|
||||
[HttpGet("~/alive")]
|
||||
[HttpGet("~/now")]
|
||||
public DateTime GetAlive()
|
||||
{
|
||||
return DateTime.UtcNow;
|
||||
}
|
||||
namespace Bit.Notifications.Controllers;
|
||||
|
||||
[HttpGet("~/version")]
|
||||
public JsonResult GetVersion()
|
||||
{
|
||||
return Json(CoreHelpers.GetVersion());
|
||||
}
|
||||
public class InfoController : Controller
|
||||
{
|
||||
[HttpGet("~/alive")]
|
||||
[HttpGet("~/now")]
|
||||
public DateTime GetAlive()
|
||||
{
|
||||
return DateTime.UtcNow;
|
||||
}
|
||||
|
||||
[HttpGet("~/version")]
|
||||
public JsonResult GetVersion()
|
||||
{
|
||||
return Json(CoreHelpers.GetVersion());
|
||||
}
|
||||
}
|
||||
|
@ -4,29 +4,28 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
[Authorize("Internal")]
|
||||
public class SendController : Controller
|
||||
{
|
||||
[Authorize("Internal")]
|
||||
public class SendController : Controller
|
||||
private readonly IHubContext<NotificationsHub> _hubContext;
|
||||
|
||||
public SendController(IHubContext<NotificationsHub> hubContext)
|
||||
{
|
||||
private readonly IHubContext<NotificationsHub> _hubContext;
|
||||
_hubContext = hubContext;
|
||||
}
|
||||
|
||||
public SendController(IHubContext<NotificationsHub> hubContext)
|
||||
[HttpPost("~/send")]
|
||||
[SelfHosted(SelfHostedOnly = true)]
|
||||
public async Task PostSend()
|
||||
{
|
||||
using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
|
||||
{
|
||||
_hubContext = hubContext;
|
||||
}
|
||||
|
||||
[HttpPost("~/send")]
|
||||
[SelfHosted(SelfHostedOnly = true)]
|
||||
public async Task PostSend()
|
||||
{
|
||||
using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
|
||||
var notificationJson = await reader.ReadToEndAsync();
|
||||
if (!string.IsNullOrWhiteSpace(notificationJson))
|
||||
{
|
||||
var notificationJson = await reader.ReadToEndAsync();
|
||||
if (!string.IsNullOrWhiteSpace(notificationJson))
|
||||
{
|
||||
await HubHelpers.SendNotificationToHubAsync(notificationJson, _hubContext);
|
||||
}
|
||||
await HubHelpers.SendNotificationToHubAsync(notificationJson, _hubContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,56 @@
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public class HeartbeatHostedService : IHostedService, IDisposable
|
||||
{
|
||||
public class HeartbeatHostedService : IHostedService, IDisposable
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHubContext<NotificationsHub> _hubContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
private Task _executingTask;
|
||||
private CancellationTokenSource _cts;
|
||||
|
||||
public HeartbeatHostedService(
|
||||
ILogger<AzureQueueHostedService> logger,
|
||||
IHubContext<NotificationsHub> hubContext,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHubContext<NotificationsHub> _hubContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
_logger = logger;
|
||||
_hubContext = hubContext;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
private Task _executingTask;
|
||||
private CancellationTokenSource _cts;
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
_executingTask = ExecuteAsync(_cts.Token);
|
||||
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
|
||||
}
|
||||
|
||||
public HeartbeatHostedService(
|
||||
ILogger<AzureQueueHostedService> logger,
|
||||
IHubContext<NotificationsHub> hubContext,
|
||||
GlobalSettings globalSettings)
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_executingTask == null)
|
||||
{
|
||||
_logger = logger;
|
||||
_hubContext = hubContext;
|
||||
_globalSettings = globalSettings;
|
||||
return;
|
||||
}
|
||||
_logger.LogWarning("Stopping service.");
|
||||
_cts.Cancel();
|
||||
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
public void Dispose()
|
||||
{ }
|
||||
|
||||
private async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
_executingTask = ExecuteAsync(_cts.Token);
|
||||
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_executingTask == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_logger.LogWarning("Stopping service.");
|
||||
_cts.Cancel();
|
||||
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{ }
|
||||
|
||||
private async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
await _hubContext.Clients.All.SendAsync("Heartbeat");
|
||||
await Task.Delay(120000);
|
||||
}
|
||||
_logger.LogWarning("Done with heartbeat.");
|
||||
await _hubContext.Clients.All.SendAsync("Heartbeat");
|
||||
await Task.Delay(120000);
|
||||
}
|
||||
_logger.LogWarning("Done with heartbeat.");
|
||||
}
|
||||
}
|
||||
|
@ -3,67 +3,66 @@ using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public static class HubHelpers
|
||||
{
|
||||
public static class HubHelpers
|
||||
public static async Task SendNotificationToHubAsync(string notificationJson,
|
||||
IHubContext<NotificationsHub> hubContext, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
public static async Task SendNotificationToHubAsync(string notificationJson,
|
||||
IHubContext<NotificationsHub> hubContext, CancellationToken cancellationToken = default(CancellationToken))
|
||||
var notification = JsonSerializer.Deserialize<PushNotificationData<object>>(notificationJson);
|
||||
switch (notification.Type)
|
||||
{
|
||||
var notification = JsonSerializer.Deserialize<PushNotificationData<object>>(notificationJson);
|
||||
switch (notification.Type)
|
||||
{
|
||||
case PushType.SyncCipherUpdate:
|
||||
case PushType.SyncCipherCreate:
|
||||
case PushType.SyncCipherDelete:
|
||||
case PushType.SyncLoginDelete:
|
||||
var cipherNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncCipherPushNotification>>(
|
||||
case PushType.SyncCipherUpdate:
|
||||
case PushType.SyncCipherCreate:
|
||||
case PushType.SyncCipherDelete:
|
||||
case PushType.SyncLoginDelete:
|
||||
var cipherNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncCipherPushNotification>>(
|
||||
notificationJson);
|
||||
if (cipherNotification.Payload.UserId.HasValue)
|
||||
{
|
||||
await hubContext.Clients.User(cipherNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", cipherNotification, cancellationToken);
|
||||
}
|
||||
else if (cipherNotification.Payload.OrganizationId.HasValue)
|
||||
{
|
||||
await hubContext.Clients.Group(
|
||||
$"Organization_{cipherNotification.Payload.OrganizationId}")
|
||||
.SendAsync("ReceiveMessage", cipherNotification, cancellationToken);
|
||||
}
|
||||
break;
|
||||
case PushType.SyncFolderUpdate:
|
||||
case PushType.SyncFolderCreate:
|
||||
case PushType.SyncFolderDelete:
|
||||
var folderNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncFolderPushNotification>>(
|
||||
notificationJson);
|
||||
await hubContext.Clients.User(folderNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", folderNotification, cancellationToken);
|
||||
break;
|
||||
case PushType.SyncCiphers:
|
||||
case PushType.SyncVault:
|
||||
case PushType.SyncOrgKeys:
|
||||
case PushType.SyncSettings:
|
||||
case PushType.LogOut:
|
||||
var userNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<UserPushNotification>>(
|
||||
notificationJson);
|
||||
await hubContext.Clients.User(userNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", userNotification, cancellationToken);
|
||||
break;
|
||||
case PushType.SyncSendCreate:
|
||||
case PushType.SyncSendUpdate:
|
||||
case PushType.SyncSendDelete:
|
||||
var sendNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncSendPushNotification>>(
|
||||
notificationJson);
|
||||
if (cipherNotification.Payload.UserId.HasValue)
|
||||
{
|
||||
await hubContext.Clients.User(cipherNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", cipherNotification, cancellationToken);
|
||||
}
|
||||
else if (cipherNotification.Payload.OrganizationId.HasValue)
|
||||
{
|
||||
await hubContext.Clients.Group(
|
||||
$"Organization_{cipherNotification.Payload.OrganizationId}")
|
||||
.SendAsync("ReceiveMessage", cipherNotification, cancellationToken);
|
||||
}
|
||||
break;
|
||||
case PushType.SyncFolderUpdate:
|
||||
case PushType.SyncFolderCreate:
|
||||
case PushType.SyncFolderDelete:
|
||||
var folderNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncFolderPushNotification>>(
|
||||
notificationJson);
|
||||
await hubContext.Clients.User(folderNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", folderNotification, cancellationToken);
|
||||
break;
|
||||
case PushType.SyncCiphers:
|
||||
case PushType.SyncVault:
|
||||
case PushType.SyncOrgKeys:
|
||||
case PushType.SyncSettings:
|
||||
case PushType.LogOut:
|
||||
var userNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<UserPushNotification>>(
|
||||
notificationJson);
|
||||
await hubContext.Clients.User(userNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", userNotification, cancellationToken);
|
||||
break;
|
||||
case PushType.SyncSendCreate:
|
||||
case PushType.SyncSendUpdate:
|
||||
case PushType.SyncSendDelete:
|
||||
var sendNotification =
|
||||
JsonSerializer.Deserialize<PushNotificationData<SyncSendPushNotification>>(
|
||||
notificationJson);
|
||||
await hubContext.Clients.User(sendNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", sendNotification, cancellationToken);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
await hubContext.Clients.User(sendNotification.Payload.UserId.ToString())
|
||||
.SendAsync("ReceiveMessage", sendNotification, cancellationToken);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,36 +2,35 @@
|
||||
using Bit.Core.Settings;
|
||||
using Quartz;
|
||||
|
||||
namespace Bit.Notifications.Jobs
|
||||
namespace Bit.Notifications.Jobs;
|
||||
|
||||
public class JobsHostedService : BaseJobsHostedService
|
||||
{
|
||||
public class JobsHostedService : BaseJobsHostedService
|
||||
public JobsHostedService(
|
||||
GlobalSettings globalSettings,
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<JobsHostedService> logger,
|
||||
ILogger<JobListener> listenerLogger)
|
||||
: base(globalSettings, serviceProvider, logger, listenerLogger) { }
|
||||
|
||||
public override async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
public JobsHostedService(
|
||||
GlobalSettings globalSettings,
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<JobsHostedService> logger,
|
||||
ILogger<JobListener> listenerLogger)
|
||||
: base(globalSettings, serviceProvider, logger, listenerLogger) { }
|
||||
var everyFiveMinutesTrigger = TriggerBuilder.Create()
|
||||
.WithIdentity("EveryFiveMinutesTrigger")
|
||||
.StartNow()
|
||||
.WithCronSchedule("0 */30 * * * ?")
|
||||
.Build();
|
||||
|
||||
public override async Task StartAsync(CancellationToken cancellationToken)
|
||||
Jobs = new List<Tuple<Type, ITrigger>>
|
||||
{
|
||||
var everyFiveMinutesTrigger = TriggerBuilder.Create()
|
||||
.WithIdentity("EveryFiveMinutesTrigger")
|
||||
.StartNow()
|
||||
.WithCronSchedule("0 */30 * * * ?")
|
||||
.Build();
|
||||
new Tuple<Type, ITrigger>(typeof(LogConnectionCounterJob), everyFiveMinutesTrigger)
|
||||
};
|
||||
|
||||
Jobs = new List<Tuple<Type, ITrigger>>
|
||||
{
|
||||
new Tuple<Type, ITrigger>(typeof(LogConnectionCounterJob), everyFiveMinutesTrigger)
|
||||
};
|
||||
await base.StartAsync(cancellationToken);
|
||||
}
|
||||
|
||||
await base.StartAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public static void AddJobsServices(IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<LogConnectionCounterJob>();
|
||||
}
|
||||
public static void AddJobsServices(IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<LogConnectionCounterJob>();
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,24 @@
|
||||
using Bit.Core.Jobs;
|
||||
using Quartz;
|
||||
|
||||
namespace Bit.Notifications.Jobs
|
||||
namespace Bit.Notifications.Jobs;
|
||||
|
||||
public class LogConnectionCounterJob : BaseJob
|
||||
{
|
||||
public class LogConnectionCounterJob : BaseJob
|
||||
private readonly ConnectionCounter _connectionCounter;
|
||||
|
||||
public LogConnectionCounterJob(
|
||||
ILogger<LogConnectionCounterJob> logger,
|
||||
ConnectionCounter connectionCounter)
|
||||
: base(logger)
|
||||
{
|
||||
private readonly ConnectionCounter _connectionCounter;
|
||||
_connectionCounter = connectionCounter;
|
||||
}
|
||||
|
||||
public LogConnectionCounterJob(
|
||||
ILogger<LogConnectionCounterJob> logger,
|
||||
ConnectionCounter connectionCounter)
|
||||
: base(logger)
|
||||
{
|
||||
_connectionCounter = connectionCounter;
|
||||
}
|
||||
|
||||
protected override Task ExecuteJobAsync(IJobExecutionContext context)
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId,
|
||||
"Connection count for server {0}: {1}", Environment.MachineName, _connectionCounter.GetCount());
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
protected override Task ExecuteJobAsync(IJobExecutionContext context)
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId,
|
||||
"Connection count for server {0}: {1}", Environment.MachineName, _connectionCounter.GetCount());
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
@ -2,48 +2,47 @@
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
[Authorize("Application")]
|
||||
public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub
|
||||
{
|
||||
[Authorize("Application")]
|
||||
public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub
|
||||
private readonly ConnectionCounter _connectionCounter;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public NotificationsHub(ConnectionCounter connectionCounter, GlobalSettings globalSettings)
|
||||
{
|
||||
private readonly ConnectionCounter _connectionCounter;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
_connectionCounter = connectionCounter;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public NotificationsHub(ConnectionCounter connectionCounter, GlobalSettings globalSettings)
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
var currentContext = new CurrentContext(null);
|
||||
await currentContext.BuildAsync(Context.User, _globalSettings);
|
||||
if (currentContext.Organizations != null)
|
||||
{
|
||||
_connectionCounter = connectionCounter;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
var currentContext = new CurrentContext(null);
|
||||
await currentContext.BuildAsync(Context.User, _globalSettings);
|
||||
if (currentContext.Organizations != null)
|
||||
foreach (var org in currentContext.Organizations)
|
||||
{
|
||||
foreach (var org in currentContext.Organizations)
|
||||
{
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, $"Organization_{org.Id}");
|
||||
}
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, $"Organization_{org.Id}");
|
||||
}
|
||||
_connectionCounter.Increment();
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
_connectionCounter.Increment();
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception exception)
|
||||
public override async Task OnDisconnectedAsync(Exception exception)
|
||||
{
|
||||
var currentContext = new CurrentContext(null);
|
||||
await currentContext.BuildAsync(Context.User, _globalSettings);
|
||||
if (currentContext.Organizations != null)
|
||||
{
|
||||
var currentContext = new CurrentContext(null);
|
||||
await currentContext.BuildAsync(Context.User, _globalSettings);
|
||||
if (currentContext.Organizations != null)
|
||||
foreach (var org in currentContext.Organizations)
|
||||
{
|
||||
foreach (var org in currentContext.Organizations)
|
||||
{
|
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"Organization_{org.Id}");
|
||||
}
|
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"Organization_{org.Id}");
|
||||
}
|
||||
_connectionCounter.Decrement();
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
_connectionCounter.Decrement();
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +1,50 @@
|
||||
using Bit.Core.Utilities;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public class Program
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Host
|
||||
.CreateDefaultBuilder(args)
|
||||
.ConfigureCustomAppConfiguration(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
webBuilder.ConfigureLogging((hostingContext, logging) =>
|
||||
logging.AddSerilog(hostingContext, e =>
|
||||
Host
|
||||
.CreateDefaultBuilder(args)
|
||||
.ConfigureCustomAppConfiguration(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
webBuilder.ConfigureLogging((hostingContext, logging) =>
|
||||
logging.AddSerilog(hostingContext, e =>
|
||||
{
|
||||
var context = e.Properties["SourceContext"].ToString();
|
||||
if (context.Contains("IdentityServer4.Validation.TokenValidator") ||
|
||||
context.Contains("IdentityServer4.Validation.TokenRequestValidator"))
|
||||
{
|
||||
var context = e.Properties["SourceContext"].ToString();
|
||||
if (context.Contains("IdentityServer4.Validation.TokenValidator") ||
|
||||
context.Contains("IdentityServer4.Validation.TokenRequestValidator"))
|
||||
{
|
||||
return e.Level > LogEventLevel.Error;
|
||||
}
|
||||
return e.Level > LogEventLevel.Error;
|
||||
}
|
||||
|
||||
if (e.Level == LogEventLevel.Error &&
|
||||
e.MessageTemplate.Text == "Failed connection handshake.")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (e.Level == LogEventLevel.Error &&
|
||||
e.MessageTemplate.Text == "Failed connection handshake.")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Level == LogEventLevel.Error &&
|
||||
e.MessageTemplate.Text.StartsWith("Failed writing message."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (e.Level == LogEventLevel.Error &&
|
||||
e.MessageTemplate.Text.StartsWith("Failed writing message."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Level == LogEventLevel.Warning &&
|
||||
e.MessageTemplate.Text.StartsWith("Heartbeat took longer"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (e.Level == LogEventLevel.Warning &&
|
||||
e.MessageTemplate.Text.StartsWith("Heartbeat took longer"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return e.Level >= LogEventLevel.Warning;
|
||||
}));
|
||||
})
|
||||
.Build()
|
||||
.Run();
|
||||
}
|
||||
return e.Level >= LogEventLevel.Warning;
|
||||
}));
|
||||
})
|
||||
.Build()
|
||||
.Run();
|
||||
}
|
||||
}
|
||||
|
@ -6,115 +6,114 @@ using IdentityModel;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public class Startup
|
||||
public Startup(IWebHostEnvironment env, IConfiguration configuration)
|
||||
{
|
||||
public Startup(IWebHostEnvironment env, IConfiguration configuration)
|
||||
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
|
||||
Configuration = configuration;
|
||||
Environment = env;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IWebHostEnvironment Environment { get; set; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Options
|
||||
services.AddOptions();
|
||||
|
||||
// Settings
|
||||
var globalSettings = services.AddGlobalSettingsServices(Configuration, Environment);
|
||||
|
||||
// Identity
|
||||
services.AddIdentityAuthenticationServices(globalSettings, Environment, config =>
|
||||
{
|
||||
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
|
||||
Configuration = configuration;
|
||||
Environment = env;
|
||||
config.AddPolicy("Application", policy =>
|
||||
{
|
||||
policy.RequireAuthenticatedUser();
|
||||
policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external");
|
||||
policy.RequireClaim(JwtClaimTypes.Scope, "api");
|
||||
});
|
||||
config.AddPolicy("Internal", policy =>
|
||||
{
|
||||
policy.RequireAuthenticatedUser();
|
||||
policy.RequireClaim(JwtClaimTypes.Scope, "internal");
|
||||
});
|
||||
});
|
||||
|
||||
// SignalR
|
||||
var signalRServerBuilder = services.AddSignalR().AddMessagePackProtocol(options =>
|
||||
{
|
||||
options.SerializerOptions = MessagePack.MessagePackSerializerOptions.Standard
|
||||
.WithResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);
|
||||
});
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Notifications?.RedisConnectionString))
|
||||
{
|
||||
signalRServerBuilder.AddStackExchangeRedis(globalSettings.Notifications.RedisConnectionString,
|
||||
options =>
|
||||
{
|
||||
options.Configuration.ChannelPrefix = "Notifications";
|
||||
});
|
||||
}
|
||||
services.AddSingleton<IUserIdProvider, SubjectUserIdProvider>();
|
||||
services.AddSingleton<ConnectionCounter>();
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IWebHostEnvironment Environment { get; set; }
|
||||
// Mvc
|
||||
services.AddMvc();
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
services.AddHostedService<HeartbeatHostedService>();
|
||||
if (!globalSettings.SelfHosted)
|
||||
{
|
||||
// Options
|
||||
services.AddOptions();
|
||||
|
||||
// Settings
|
||||
var globalSettings = services.AddGlobalSettingsServices(Configuration, Environment);
|
||||
|
||||
// Identity
|
||||
services.AddIdentityAuthenticationServices(globalSettings, Environment, config =>
|
||||
// Hosted Services
|
||||
Jobs.JobsHostedService.AddJobsServices(services);
|
||||
services.AddHostedService<Jobs.JobsHostedService>();
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Notifications?.ConnectionString))
|
||||
{
|
||||
config.AddPolicy("Application", policy =>
|
||||
{
|
||||
policy.RequireAuthenticatedUser();
|
||||
policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external");
|
||||
policy.RequireClaim(JwtClaimTypes.Scope, "api");
|
||||
});
|
||||
config.AddPolicy("Internal", policy =>
|
||||
{
|
||||
policy.RequireAuthenticatedUser();
|
||||
policy.RequireClaim(JwtClaimTypes.Scope, "internal");
|
||||
});
|
||||
});
|
||||
|
||||
// SignalR
|
||||
var signalRServerBuilder = services.AddSignalR().AddMessagePackProtocol(options =>
|
||||
{
|
||||
options.SerializerOptions = MessagePack.MessagePackSerializerOptions.Standard
|
||||
.WithResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);
|
||||
});
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Notifications?.RedisConnectionString))
|
||||
{
|
||||
signalRServerBuilder.AddStackExchangeRedis(globalSettings.Notifications.RedisConnectionString,
|
||||
options =>
|
||||
{
|
||||
options.Configuration.ChannelPrefix = "Notifications";
|
||||
});
|
||||
services.AddHostedService<AzureQueueHostedService>();
|
||||
}
|
||||
services.AddSingleton<IUserIdProvider, SubjectUserIdProvider>();
|
||||
services.AddSingleton<ConnectionCounter>();
|
||||
|
||||
// Mvc
|
||||
services.AddMvc();
|
||||
|
||||
services.AddHostedService<HeartbeatHostedService>();
|
||||
if (!globalSettings.SelfHosted)
|
||||
{
|
||||
// Hosted Services
|
||||
Jobs.JobsHostedService.AddJobsServices(services);
|
||||
services.AddHostedService<Jobs.JobsHostedService>();
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Notifications?.ConnectionString))
|
||||
{
|
||||
services.AddHostedService<AzureQueueHostedService>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
IWebHostEnvironment env,
|
||||
IHostApplicationLifetime appLifetime,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
IdentityModelEventSource.ShowPII = true;
|
||||
app.UseSerilog(env, appLifetime, globalSettings);
|
||||
|
||||
// Add general security headers
|
||||
app.UseMiddleware<SecurityHeadersMiddleware>();
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
// Add routing
|
||||
app.UseRouting();
|
||||
|
||||
// Add Cors
|
||||
app.UseCors(policy => policy.SetIsOriginAllowed(o => CoreHelpers.IsCorsOriginAllowed(o, globalSettings))
|
||||
.AllowAnyMethod().AllowAnyHeader().AllowCredentials());
|
||||
|
||||
// Add authentication to the request pipeline.
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
// Add endpoints to the request pipeline.
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHub<NotificationsHub>("/hub", options =>
|
||||
{
|
||||
options.ApplicationMaxBufferSize = 2048; // client => server messages are not even used
|
||||
options.TransportMaxBufferSize = 4096;
|
||||
});
|
||||
endpoints.MapDefaultControllerRoute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
IApplicationBuilder app,
|
||||
IWebHostEnvironment env,
|
||||
IHostApplicationLifetime appLifetime,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
IdentityModelEventSource.ShowPII = true;
|
||||
app.UseSerilog(env, appLifetime, globalSettings);
|
||||
|
||||
// Add general security headers
|
||||
app.UseMiddleware<SecurityHeadersMiddleware>();
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
// Add routing
|
||||
app.UseRouting();
|
||||
|
||||
// Add Cors
|
||||
app.UseCors(policy => policy.SetIsOriginAllowed(o => CoreHelpers.IsCorsOriginAllowed(o, globalSettings))
|
||||
.AllowAnyMethod().AllowAnyHeader().AllowCredentials());
|
||||
|
||||
// Add authentication to the request pipeline.
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
// Add endpoints to the request pipeline.
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHub<NotificationsHub>("/hub", options =>
|
||||
{
|
||||
options.ApplicationMaxBufferSize = 2048; // client => server messages are not even used
|
||||
options.TransportMaxBufferSize = 4096;
|
||||
});
|
||||
endpoints.MapDefaultControllerRoute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
using IdentityModel;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Bit.Notifications
|
||||
namespace Bit.Notifications;
|
||||
|
||||
public class SubjectUserIdProvider : IUserIdProvider
|
||||
{
|
||||
public class SubjectUserIdProvider : IUserIdProvider
|
||||
public string GetUserId(HubConnectionContext connection)
|
||||
{
|
||||
public string GetUserId(HubConnectionContext connection)
|
||||
{
|
||||
return connection.User?.FindFirst(JwtClaimTypes.Subject)?.Value;
|
||||
}
|
||||
return connection.User?.FindFirst(JwtClaimTypes.Subject)?.Value;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user