mirror of
https://github.com/streetwriters/notesnook-sync-server.git
synced 2026-08-13 12:00:20 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31c57f95b2 | ||
|
|
33413b0a5c |
@@ -63,7 +63,7 @@ namespace Notesnook.API.Controllers
|
|||||||
|
|
||||||
[HttpPost("api-keys")]
|
[HttpPost("api-keys")]
|
||||||
[Authorize(Policy = "Notesnook")]
|
[Authorize(Policy = "Notesnook")]
|
||||||
public async Task<IActionResult> CreateApiKeyAsync([FromBody] InboxApiKey request)
|
public async Task<IActionResult> CreateApiKeyAsync([FromBody] CreateInboxApiKeyRequest request)
|
||||||
{
|
{
|
||||||
var userId = User.GetUserId();
|
var userId = User.GetUserId();
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ using NanoidDotNet;
|
|||||||
|
|
||||||
namespace Notesnook.API.Models
|
namespace Notesnook.API.Models
|
||||||
{
|
{
|
||||||
|
public class CreateInboxApiKeyRequest
|
||||||
|
{
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public required string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("expiryDate")]
|
||||||
|
public long ExpiryDate { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class InboxApiKey
|
public class InboxApiKey
|
||||||
{
|
{
|
||||||
public InboxApiKey()
|
public InboxApiKey()
|
||||||
|
|||||||
@@ -18,28 +18,49 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Lib.AspNetCore.ServerSentEvents;
|
using Lib.AspNetCore.ServerSentEvents;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Streetwriters.Messenger.Helpers
|
namespace Streetwriters.Messenger.Helpers
|
||||||
{
|
{
|
||||||
public class SSEHelper
|
public class SSEHelper
|
||||||
{
|
{
|
||||||
public static async Task SendEventToUserAsync(string data, IServerSentEventsService sseService, string userId, string? originTokenId = null)
|
public static async Task SendEventToUserAsync(string data, IServerSentEventsService sseService, string userId, string? originTokenId = null, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var clients = sseService.GetClients().Where(c => c.User.FindFirstValue("sub") == userId);
|
var clients = sseService.GetClients()
|
||||||
foreach (var client in clients)
|
.Where(c => c.User?.FindFirstValue("sub") == userId)
|
||||||
{
|
.Where(c => originTokenId == null || c.User?.FindFirstValue("jti") != originTokenId);
|
||||||
if (originTokenId != null && client.User.FindFirstValue("jti") == originTokenId) continue;
|
|
||||||
if (!client.IsConnected) continue;
|
await SendEventToClientsAsync(clients, data, cancellationToken);
|
||||||
await client.SendEventAsync(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task SendEventToAllUsersAsync(string data, IServerSentEventsService sseService)
|
public static async Task SendEventToAllUsersAsync(string data, IServerSentEventsService sseService, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
await sseService.SendEventAsync(data);
|
await SendEventToClientsAsync(sseService.GetClients(), data, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task SendEventToClientsAsync(IEnumerable<IServerSentEventsClient> clients, string data, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
foreach (var client in clients)
|
||||||
|
{
|
||||||
|
if (!client.IsConnected) continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await client.SendEventAsync(data, cancellationToken);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ using System;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Lib.AspNetCore.ServerSentEvents;
|
using Lib.AspNetCore.ServerSentEvents;
|
||||||
using Streetwriters.Messenger.Helpers;
|
using Streetwriters.Messenger.Helpers;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -33,12 +34,14 @@ namespace Streetwriters.Messenger.Services
|
|||||||
private const string HEARTBEAT_MESSAGE_FORMAT = "Streetwriters Heartbeat ({0} UTC)";
|
private const string HEARTBEAT_MESSAGE_FORMAT = "Streetwriters Heartbeat ({0} UTC)";
|
||||||
|
|
||||||
private readonly IServerSentEventsService _serverSentEventsService;
|
private readonly IServerSentEventsService _serverSentEventsService;
|
||||||
|
private readonly ILogger<HeartbeatService> _logger;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructor
|
#region Constructor
|
||||||
public HeartbeatService(IServerSentEventsService serverSentEventsService)
|
public HeartbeatService(IServerSentEventsService serverSentEventsService, ILogger<HeartbeatService> logger)
|
||||||
{
|
{
|
||||||
_serverSentEventsService = serverSentEventsService;
|
_serverSentEventsService = serverSentEventsService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -47,15 +50,28 @@ namespace Streetwriters.Messenger.Services
|
|||||||
{
|
{
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
var message = JsonSerializer.Serialize(new
|
try
|
||||||
{
|
{
|
||||||
type = "heartbeat",
|
var message = JsonSerializer.Serialize(new
|
||||||
data = JsonSerializer.Serialize(new
|
|
||||||
{
|
{
|
||||||
t = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
type = "heartbeat",
|
||||||
})
|
data = JsonSerializer.Serialize(new
|
||||||
});
|
{
|
||||||
await SSEHelper.SendEventToAllUsersAsync(message, _serverSentEventsService);
|
t = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
await SSEHelper.SendEventToAllUsersAsync(message, _serverSentEventsService, stoppingToken);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to send SSE heartbeat to one or more clients.");
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DotNetEnv" Version="2.3.0" />
|
<PackageReference Include="DotNetEnv" Version="2.3.0" />
|
||||||
<PackageReference Include="Lib.AspNetCore.ServerSentEvents" Version="6.0.0" />
|
<PackageReference Include="Lib.AspNetCore.ServerSentEvents" Version="9.1.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0"
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0"
|
||||||
NoWarn="NU1605" />
|
NoWarn="NU1605" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.0"
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user