Merge branch 'dev' into V6

This commit is contained in:
Jordan Dominion
2023-11-07 08:26:38 -05:00
8 changed files with 84 additions and 8 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- This is in it's own file to help incremental building, changing it causes a complete rebuild of the web panel -->
<TgsControlPanelVersion>4.26.0</TgsControlPanelVersion>
<TgsControlPanelVersion>4.26.2</TgsControlPanelVersion>
</PropertyGroup>
</Project>
+1 -1
View File
@@ -8,7 +8,7 @@
<TgsApiVersion>10.0.0</TgsApiVersion>
<TgsCommonLibraryVersion>7.0.0</TgsCommonLibraryVersion>
<TgsApiLibraryVersion>13.0.0</TgsApiLibraryVersion>
<TgsClientVersion>16.0.0</TgsClientVersion>
<TgsClientVersion>15.0.0</TgsClientVersion>
<TgsDmapiVersion>6.6.2</TgsDmapiVersion>
<TgsInteropVersion>5.6.2</TgsInteropVersion>
<TgsHostWatchdogVersion>1.4.0</TgsHostWatchdogVersion>
@@ -27,7 +27,7 @@
<!-- Usage: HTTP constants reference -->
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<!-- Usage: Decoding the 'nbf' property of JWTs -->
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.0.2" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.0.3" />
<!-- Usage: Primary JSON library -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!-- Usage: Data model annotating -->
+6 -1
View File
@@ -372,13 +372,15 @@ namespace Tgstation.Server.Client
retryPolicy ??= new InfiniteThirtySecondMaxRetryPolicy();
var wrappedPolicy = new ApiClientTokenRefreshRetryPolicy(this, retryPolicy);
HubConnection? hubConnection = null;
var hubConnectionBuilder = new HubConnectionBuilder()
.AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings = SerializerSettings;
})
.WithAutomaticReconnect(retryPolicy)
.WithAutomaticReconnect(wrappedPolicy)
.WithUrl(
new Uri(Url, Routes.JobsHub),
HttpTransportType.ServerSentEvents,
@@ -480,6 +482,9 @@ namespace Tgstation.Server.Client
if (content == null && (method == HttpMethod.Post || method == HttpMethod.Put))
throw new InvalidOperationException("content cannot be null for POST or PUT!");
if (disposed)
throw new ObjectDisposedException(nameof(ApiClient));
HttpResponseMessage response;
var fullUri = new Uri(Url, route);
var serializerSettings = SerializerSettings;
@@ -0,0 +1,61 @@
using System;
using System.Threading;
using Microsoft.AspNetCore.SignalR.Client;
namespace Tgstation.Server.Client
{
/// <summary>
/// A <see cref="IRetryPolicy"/> that attempts to refresh a given <see cref="apiClient"/>'s token on the first disconnect.
/// </summary>
sealed class ApiClientTokenRefreshRetryPolicy : IRetryPolicy
{
/// <summary>
/// The backing <see cref="ApiClient"/>.
/// </summary>
readonly ApiClient apiClient;
/// <summary>
/// The wrapped <see cref="IRetryPolicy"/>.
/// </summary>
readonly IRetryPolicy wrappedPolicy;
/// <summary>
/// Initializes a new instance of the <see cref="ApiClientTokenRefreshRetryPolicy"/> class.
/// </summary>
/// <param name="apiClient">The value of <see cref="apiClient"/>.</param>
/// <param name="wrappedPolicy">The value of <see cref="wrappedPolicy"/>.</param>
public ApiClientTokenRefreshRetryPolicy(ApiClient apiClient, IRetryPolicy wrappedPolicy)
{
this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
this.wrappedPolicy = wrappedPolicy ?? throw new ArgumentNullException(nameof(wrappedPolicy));
}
/// <inheritdoc />
public TimeSpan? NextRetryDelay(RetryContext retryContext)
{
if (retryContext == null)
throw new ArgumentNullException(nameof(retryContext));
if (retryContext.PreviousRetryCount == 0)
AttemptTokenRefresh();
return wrappedPolicy.NextRetryDelay(retryContext);
}
/// <summary>
/// Attempt to refresh the <see cref="apiClient"/>s token asynchronously.
/// </summary>
async void AttemptTokenRefresh()
{
try
{
await apiClient.RefreshToken(CancellationToken.None);
}
catch
{
// intentionally ignored
}
}
}
}
@@ -403,7 +403,9 @@ namespace Tgstation.Server.Host.Core
services.AddSingleton<IJobService>(provider => provider.GetRequiredService<JobService>());
services.AddSingleton<IJobsHubUpdater>(provider => provider.GetRequiredService<JobService>());
services.AddSingleton<IJobManager>(x => x.GetRequiredService<IJobService>());
services.AddSingleton<IPermissionsUpdateNotifyee, JobsHubGroupMapper>();
services.AddSingleton<JobsHubGroupMapper>();
services.AddSingleton<IPermissionsUpdateNotifyee>(provider => provider.GetRequiredService<JobsHubGroupMapper>());
services.AddSingleton<IHostedService>(x => x.GetRequiredService<JobsHubGroupMapper>()); // bit of a hack, but we need this to load immediated
services.AddSingleton<InstanceManager>();
services.AddSingleton<IBridgeDispatcher>(x => x.GetRequiredService<InstanceManager>());
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Hubs;
@@ -19,7 +20,7 @@ namespace Tgstation.Server.Host.Jobs
/// <summary>
/// Handles mapping groups for the <see cref="JobsHub"/>.
/// </summary>
sealed class JobsHubGroupMapper : IPermissionsUpdateNotifyee
sealed class JobsHubGroupMapper : IPermissionsUpdateNotifyee, IHostedService
{
/// <summary>
/// The <see cref="IHubContext"/> for the <see cref="JobsHub"/>.
@@ -96,6 +97,12 @@ namespace Tgstation.Server.Host.Jobs
cancellationToken);
}
/// <inheritdoc />
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
/// <inheritdoc />
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
/// <summary>
/// Implementation of <see cref="IConnectionMappedHubContext{THub, THubMethods}.OnConnectionMapGroups"/>.
/// </summary>
@@ -83,12 +83,13 @@ namespace Tgstation.Server.Host.Utils.SignalR
userId,
context.ConnectionId);
var mappingTask = OnConnectionMapGroups(
var mappingTask = OnConnectionMapGroups?.Invoke(
authenticationContext,
mappedGroups => Task.WhenAll(
mappedGroups.Select(
group => hub.Groups.AddToGroupAsync(context.ConnectionId, group, cancellationToken))),
cancellationToken);
cancellationToken)
?? ValueTask.CompletedTask;
userConnections.AddOrUpdate(
userId,
_ => new Dictionary<string, HubCallerContext>