Merge tag '0.9.17' into mare-classic
* tag '0.9.17': add census popup on connection api update census update heave fewer redraws as main method for data application, minor fixes remove unnecessary exists check add visibility for loaded mods size for pair, use menu bar for settings, remove settings button fix staging issues add download throttling, change header of mare, fix reverting players when going offline/paused when not visible use name for glamourer revert fix startup breaking add inner exception stacktraces calc correct button size wording add permission popup ui fix getting identifier during zoning indent nonscaled remove unnecessary usings ui icon boogaloo fix cache dict wtf add normalized icons add owner/moderator/pinned user icons check tokentime more precisely in both directions more cleanup fix sorting and cleanup make local groups more usable for pause/resume fix outlined font rework creation of popout windows into factory and some refactoring in general make syncshell admin ui to standalone window remove close button on intro ui do not allow to open main ui without finishing setup readonly bla wait for plugin disposal fix palette wording fix palette application and add experimental less redraws option some minor fixes check for timezone idk adjust token handling fix total user count in syncshell (distinct by UIDs) fix text alignment fix some shit maybe idk some fixes I guess fix offset for transfer bar at the bottom, use async collections, clear filter on tab change + add button to clear, require ctrl for align syncshells blah Some display options for DTR tooltip (#66) add ordering adjust api to latest rework main ui add total count on mouseover, make syncshell windows non-blocking fix token for character change, add online count to syncshells and groups argh fix broken font in header add more options for the compactui fix icons and text of buttons being static in place remove logspam
This commit is contained in:
@@ -103,6 +103,7 @@ public partial class ApiController
|
||||
sb.AppendLine($"GlamourerData for {item.Key}: {!string.IsNullOrEmpty(item.Value)}");
|
||||
}
|
||||
Logger.LogDebug("Chara data contained: {nl} {data}", Environment.NewLine, sb.ToString());
|
||||
|
||||
await UserPushData(new(visibleCharacters, character)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MareSynchronos.API.Data.Extensions;
|
||||
using MareSynchronos.API.Dto;
|
||||
using MareSynchronos.API.Dto.User;
|
||||
using MareSynchronos.API.SignalR;
|
||||
using MareSynchronos.PlayerData.Pairs;
|
||||
using MareSynchronos.Services;
|
||||
@@ -33,6 +34,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
private bool _initialized;
|
||||
private HubConnection? _mareHub;
|
||||
private ServerState _serverState;
|
||||
private CensusUpdateMessage? _lastCensus;
|
||||
|
||||
public ApiController(ILogger<ApiController> logger, HubFactory hubFactory, DalamudUtilService dalamudUtil,
|
||||
PairManager pairManager, ServerConfigurationManager serverManager, MareMediator mediator,
|
||||
@@ -48,9 +50,10 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
Mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn());
|
||||
Mediator.Subscribe<DalamudLogoutMessage>(this, (_) => DalamudUtilOnLogOut());
|
||||
Mediator.Subscribe<HubClosedMessage>(this, (msg) => MareHubOnClosed(msg.Exception));
|
||||
Mediator.Subscribe<HubReconnectedMessage>(this, (msg) => _ = Task.Run(MareHubOnReconnected));
|
||||
Mediator.Subscribe<HubReconnectedMessage>(this, async (msg) => await MareHubOnReconnected().ConfigureAwait(false));
|
||||
Mediator.Subscribe<HubReconnectingMessage>(this, (msg) => MareHubOnReconnecting(msg.Exception));
|
||||
Mediator.Subscribe<CyclePauseMessage>(this, (msg) => _ = CyclePause(msg.UserData));
|
||||
Mediator.Subscribe<CensusUpdateMessage>(this, (msg) => _lastCensus = msg);
|
||||
|
||||
ServerState = ServerState.Offline;
|
||||
|
||||
@@ -185,7 +188,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
$"Your client is outdated ({currentClientVer.Major}.{currentClientVer.Minor}.{currentClientVer.Build}), current is: " +
|
||||
$"{_connectionDto.CurrentClientVersion.Major}.{_connectionDto.CurrentClientVersion.Minor}.{_connectionDto.CurrentClientVersion.Build}. " +
|
||||
$"Please keep your Mare Synchronos client up-to-date.",
|
||||
Dalamud.Interface.Internal.Notifications.NotificationType.Error));
|
||||
Dalamud.Interface.Internal.Notifications.NotificationType.Warning));
|
||||
}
|
||||
|
||||
await LoadIninitialPairs().ConfigureAwait(false);
|
||||
@@ -210,6 +213,12 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
Logger.LogInformation("Failed to establish connection, retrying");
|
||||
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(5, 20)), token).ConfigureAwait(false);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "InvalidOperationException on connection");
|
||||
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Exception on Connection");
|
||||
@@ -369,13 +378,13 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
try
|
||||
{
|
||||
InitializeApiHooks();
|
||||
await LoadIninitialPairs().ConfigureAwait(false);
|
||||
_connectionDto = await GetConnectionDto().ConfigureAwait(false);
|
||||
if (_connectionDto.ServerVersion != IMareHub.ApiVersion)
|
||||
{
|
||||
await StopConnection(ServerState.VersionMisMatch).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
await LoadIninitialPairs().ConfigureAwait(false);
|
||||
await LoadOnlinePairs().ConfigureAwait(false);
|
||||
ServerState = ServerState.Connected;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using Dalamud.Plugin.Services;
|
||||
using MareSynchronos.API.SignalR;
|
||||
using MareSynchronos.Interop;
|
||||
using MareSynchronos.MareConfiguration;
|
||||
using MareSynchronos.API.SignalR;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using MareSynchronos.Services.ServerConfiguration;
|
||||
using MareSynchronos.WebAPI.SignalR.Utils;
|
||||
@@ -16,21 +13,19 @@ namespace MareSynchronos.WebAPI.SignalR;
|
||||
|
||||
public class HubFactory : MediatorSubscriberBase
|
||||
{
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly IPluginLog _pluginLog;
|
||||
private readonly ILoggerProvider _loggingProvider;
|
||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||
private readonly TokenProvider _tokenProvider;
|
||||
private HubConnection? _instance;
|
||||
private bool _isDisposed = false;
|
||||
|
||||
public HubFactory(ILogger<HubFactory> logger, MareMediator mediator,
|
||||
ServerConfigurationManager serverConfigurationManager, MareConfigService configService,
|
||||
TokenProvider tokenProvider, IPluginLog pluginLog) : base(logger, mediator)
|
||||
ServerConfigurationManager serverConfigurationManager,
|
||||
TokenProvider tokenProvider, ILoggerProvider pluginLog) : base(logger, mediator)
|
||||
{
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
_configService = configService;
|
||||
_tokenProvider = tokenProvider;
|
||||
_pluginLog = pluginLog;
|
||||
_loggingProvider = pluginLog;
|
||||
}
|
||||
|
||||
public async Task DisposeHubAsync()
|
||||
@@ -92,7 +87,7 @@ public class HubFactory : MediatorSubscriberBase
|
||||
.WithAutomaticReconnect(new ForeverRetryPolicy(Mediator))
|
||||
.ConfigureLogging(a =>
|
||||
{
|
||||
a.ClearProviders().AddProvider(new DalamudLoggingProvider(_configService, _pluginLog));
|
||||
a.ClearProviders().AddProvider(_loggingProvider);
|
||||
a.SetMinimumLevel(LogLevel.Information);
|
||||
})
|
||||
.Build();
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
namespace MareSynchronos.WebAPI.SignalR;
|
||||
|
||||
public record JwtIdentifier(string ApiUrl, string SecretKey);
|
||||
public record JwtIdentifier(string ApiUrl, string CharaHash, string SecretKey)
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return "{JwtIdentifier; Url: " + ApiUrl + ", Chara: " + CharaHash + ", HasSecretKey: " + !string.IsNullOrEmpty(SecretKey) + "}";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using MareSynchronos.API.Routes;
|
||||
using MareSynchronos.Services;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using MareSynchronos.Services.ServerConfiguration;
|
||||
using MareSynchronos.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -10,7 +11,7 @@ using System.Reflection;
|
||||
|
||||
namespace MareSynchronos.WebAPI.SignalR;
|
||||
|
||||
public sealed class TokenProvider : IDisposable
|
||||
public sealed class TokenProvider : IDisposable, IMediatorSubscriber
|
||||
{
|
||||
private readonly DalamudUtilService _dalamudUtil;
|
||||
private readonly HttpClient _httpClient;
|
||||
@@ -18,24 +19,38 @@ public sealed class TokenProvider : IDisposable
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly ConcurrentDictionary<JwtIdentifier, string> _tokenCache = new();
|
||||
|
||||
public TokenProvider(ILogger<TokenProvider> logger, ServerConfigurationManager serverManager, DalamudUtilService dalamudUtil)
|
||||
public TokenProvider(ILogger<TokenProvider> logger, ServerConfigurationManager serverManager, DalamudUtilService dalamudUtil, MareMediator mareMediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_serverManager = serverManager;
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_httpClient = new();
|
||||
var ver = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
Mediator = mareMediator;
|
||||
Mediator.Subscribe<DalamudLogoutMessage>(this, (_) =>
|
||||
{
|
||||
_lastJwtIdentifier = null;
|
||||
_tokenCache.Clear();
|
||||
});
|
||||
Mediator.Subscribe<DalamudLoginMessage>(this, (_) =>
|
||||
{
|
||||
_lastJwtIdentifier = null;
|
||||
_tokenCache.Clear();
|
||||
});
|
||||
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MareSynchronos", ver!.Major + "." + ver!.Minor + "." + ver!.Build));
|
||||
}
|
||||
|
||||
private JwtIdentifier CurrentIdentifier => new(_serverManager.CurrentApiUrl, _serverManager.GetSecretKey()!);
|
||||
public MareMediator Mediator { get; }
|
||||
|
||||
private JwtIdentifier? _lastJwtIdentifier;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Mediator.UnsubscribeAll(this);
|
||||
_httpClient.Dispose();
|
||||
}
|
||||
|
||||
public async Task<string> GetNewToken(CancellationToken token)
|
||||
public async Task<string> GetNewToken(JwtIdentifier identifier, CancellationToken token)
|
||||
{
|
||||
Uri tokenUri;
|
||||
string response = string.Empty;
|
||||
@@ -58,16 +73,19 @@ public sealed class TokenProvider : IDisposable
|
||||
|
||||
response = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
result.EnsureSuccessStatusCode();
|
||||
_tokenCache[CurrentIdentifier] = response;
|
||||
_tokenCache[identifier] = response;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_tokenCache.TryRemove(CurrentIdentifier, out _);
|
||||
_tokenCache.TryRemove(identifier, out _);
|
||||
|
||||
_logger.LogError(ex, "GetNewToken: Failure to get token");
|
||||
|
||||
if (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Error refreshing token", "Your authentication token could not be renewed. Try reconnecting to Mare manually.",
|
||||
Dalamud.Interface.Internal.Notifications.NotificationType.Error));
|
||||
Mediator.Publish(new DisconnectedMessage());
|
||||
throw new MareAuthFailureException(response);
|
||||
}
|
||||
|
||||
@@ -78,12 +96,54 @@ public sealed class TokenProvider : IDisposable
|
||||
return response;
|
||||
}
|
||||
|
||||
private JwtIdentifier? GetIdentifier()
|
||||
{
|
||||
JwtIdentifier jwtIdentifier;
|
||||
try
|
||||
{
|
||||
jwtIdentifier = new(_serverManager.CurrentApiUrl,
|
||||
_dalamudUtil.GetPlayerNameHashedAsync().GetAwaiter().GetResult(),
|
||||
_serverManager.GetSecretKey()!);
|
||||
_lastJwtIdentifier = jwtIdentifier;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (_lastJwtIdentifier == null)
|
||||
{
|
||||
_logger.LogError("GetOrUpdate: No last identifier found, aborting");
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.LogWarning(ex, "GetOrUpdate: Could not get JwtIdentifier for some reason or another, reusing last identifier {identifier}", _lastJwtIdentifier);
|
||||
jwtIdentifier = _lastJwtIdentifier;
|
||||
}
|
||||
|
||||
_logger.LogDebug("GetOrUpdate: Using identifier {identifier}", jwtIdentifier);
|
||||
return jwtIdentifier;
|
||||
}
|
||||
|
||||
public string? GetToken()
|
||||
{
|
||||
JwtIdentifier? jwtIdentifier = GetIdentifier();
|
||||
if (jwtIdentifier == null) return null;
|
||||
|
||||
if (_tokenCache.TryGetValue(jwtIdentifier, out var token))
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("No token present");
|
||||
}
|
||||
|
||||
public async Task<string?> GetOrUpdateToken(CancellationToken ct)
|
||||
{
|
||||
if (_tokenCache.TryGetValue(CurrentIdentifier, out var token))
|
||||
JwtIdentifier? jwtIdentifier = GetIdentifier();
|
||||
if (jwtIdentifier == null) return null;
|
||||
|
||||
if (_tokenCache.TryGetValue(jwtIdentifier, out var token))
|
||||
return token;
|
||||
|
||||
_logger.LogTrace("GetOrUpdate: Getting new token");
|
||||
return await GetNewToken(ct).ConfigureAwait(false);
|
||||
return await GetNewToken(jwtIdentifier, ct).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user