add renew and refresh oauth buttons
This commit is contained in:
@@ -202,7 +202,8 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
s.GetRequiredService<MareMediator>(), s.GetRequiredService<MareConfigService>()));
|
s.GetRequiredService<MareMediator>(), s.GetRequiredService<MareConfigService>()));
|
||||||
collection.AddScoped((s) => new UiSharedService(s.GetRequiredService<ILogger<UiSharedService>>(), s.GetRequiredService<IpcManager>(), s.GetRequiredService<ApiController>(),
|
collection.AddScoped((s) => new UiSharedService(s.GetRequiredService<ILogger<UiSharedService>>(), s.GetRequiredService<IpcManager>(), s.GetRequiredService<ApiController>(),
|
||||||
s.GetRequiredService<CacheMonitor>(), s.GetRequiredService<FileDialogManager>(), s.GetRequiredService<MareConfigService>(), s.GetRequiredService<DalamudUtilService>(),
|
s.GetRequiredService<CacheMonitor>(), s.GetRequiredService<FileDialogManager>(), s.GetRequiredService<MareConfigService>(), s.GetRequiredService<DalamudUtilService>(),
|
||||||
pluginInterface, textureProvider, s.GetRequiredService<Dalamud.Localization>(), s.GetRequiredService<ServerConfigurationManager>(), s.GetRequiredService<MareMediator>()));
|
pluginInterface, textureProvider, s.GetRequiredService<Dalamud.Localization>(), s.GetRequiredService<ServerConfigurationManager>(), s.GetRequiredService<TokenProvider>(),
|
||||||
|
s.GetRequiredService<MareMediator>()));
|
||||||
|
|
||||||
collection.AddHostedService(p => p.GetRequiredService<ConfigurationSaveService>());
|
collection.AddHostedService(p => p.GetRequiredService<ConfigurationSaveService>());
|
||||||
collection.AddHostedService(p => p.GetRequiredService<MareMediator>());
|
collection.AddHostedService(p => p.GetRequiredService<MareMediator>());
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ using MareSynchronos.Services.Mediator;
|
|||||||
using MareSynchronos.Services.ServerConfiguration;
|
using MareSynchronos.Services.ServerConfiguration;
|
||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using MareSynchronos.WebAPI;
|
using MareSynchronos.WebAPI;
|
||||||
|
using MareSynchronos.WebAPI.SignalR;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -56,6 +58,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
private readonly ITextureProvider _textureProvider;
|
private readonly ITextureProvider _textureProvider;
|
||||||
private readonly Dictionary<string, object?> _selectedComboItems = new(StringComparer.Ordinal);
|
private readonly Dictionary<string, object?> _selectedComboItems = new(StringComparer.Ordinal);
|
||||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||||
|
private readonly TokenProvider _tokenProvider;
|
||||||
private bool _cacheDirectoryHasOtherFilesThanCache = false;
|
private bool _cacheDirectoryHasOtherFilesThanCache = false;
|
||||||
|
|
||||||
private bool _cacheDirectoryIsValidPath = true;
|
private bool _cacheDirectoryIsValidPath = true;
|
||||||
@@ -79,13 +82,14 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
private bool _petNamesExists = false;
|
private bool _petNamesExists = false;
|
||||||
|
|
||||||
private int _serverSelectionIndex = -1;
|
private int _serverSelectionIndex = -1;
|
||||||
|
private Dictionary<string, DateTime> _oauthTokenExpiry = new();
|
||||||
|
|
||||||
public UiSharedService(ILogger<UiSharedService> logger, IpcManager ipcManager, ApiController apiController,
|
public UiSharedService(ILogger<UiSharedService> logger, IpcManager ipcManager, ApiController apiController,
|
||||||
CacheMonitor cacheMonitor, FileDialogManager fileDialogManager,
|
CacheMonitor cacheMonitor, FileDialogManager fileDialogManager,
|
||||||
MareConfigService configService, DalamudUtilService dalamudUtil, IDalamudPluginInterface pluginInterface,
|
MareConfigService configService, DalamudUtilService dalamudUtil, IDalamudPluginInterface pluginInterface,
|
||||||
ITextureProvider textureProvider,
|
ITextureProvider textureProvider,
|
||||||
Dalamud.Localization localization,
|
Dalamud.Localization localization,
|
||||||
ServerConfigurationManager serverManager, MareMediator mediator) : base(logger, mediator)
|
ServerConfigurationManager serverManager, TokenProvider tokenProvider, MareMediator mediator) : base(logger, mediator)
|
||||||
{
|
{
|
||||||
_ipcManager = ipcManager;
|
_ipcManager = ipcManager;
|
||||||
_apiController = apiController;
|
_apiController = apiController;
|
||||||
@@ -97,6 +101,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
_textureProvider = textureProvider;
|
_textureProvider = textureProvider;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_serverConfigurationManager = serverManager;
|
_serverConfigurationManager = serverManager;
|
||||||
|
_tokenProvider = tokenProvider;
|
||||||
_localization.SetupWithLangCode("en");
|
_localization.SetupWithLangCode("en");
|
||||||
|
|
||||||
_isDirectoryWritable = IsDirectoryWritable(_configService.Current.CacheFolder);
|
_isDirectoryWritable = IsDirectoryWritable(_configService.Current.CacheFolder);
|
||||||
@@ -912,7 +917,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
public void DrawOAuth(ServerStorage selectedServer)
|
public void DrawOAuth(ServerStorage selectedServer)
|
||||||
{
|
{
|
||||||
var oauthToken = selectedServer.OAuthToken;
|
var oauthToken = selectedServer.OAuthToken;
|
||||||
using var _ = ImRaii.PushIndent(10f);
|
_ = ImRaii.PushIndent(10f);
|
||||||
if (oauthToken == null)
|
if (oauthToken == null)
|
||||||
{
|
{
|
||||||
if (_discordOAuthCheck == null)
|
if (_discordOAuthCheck == null)
|
||||||
@@ -977,34 +982,84 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
if (oauthToken != null)
|
if (oauthToken != null)
|
||||||
{
|
{
|
||||||
ColorTextWrapped($"OAuth2 is enabled, linked to: Discord User {_serverConfigurationManager.GetDiscordUserFromToken(selectedServer)}", ImGuiColors.HealerGreen);
|
if (!_oauthTokenExpiry.TryGetValue(oauthToken, out DateTime tokenExpiry))
|
||||||
if ((_discordOAuthUIDs == null || _discordOAuthUIDs.IsCompleted)
|
|
||||||
&& IconTextButton(FontAwesomeIcon.Question, "Check Discord Connection"))
|
|
||||||
{
|
{
|
||||||
_discordOAuthUIDs = _serverConfigurationManager.GetUIDsWithDiscordToken(selectedServer.ServerUri, oauthToken);
|
try
|
||||||
}
|
|
||||||
else if (_discordOAuthUIDs != null)
|
|
||||||
{
|
|
||||||
if (!_discordOAuthUIDs.IsCompleted)
|
|
||||||
{
|
{
|
||||||
ColorTextWrapped("Checking UIDs on Server", ImGuiColors.DalamudYellow);
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var jwt = handler.ReadJwtToken(oauthToken);
|
||||||
|
tokenExpiry = _oauthTokenExpiry[oauthToken] = jwt.ValidTo;
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var foundUids = _discordOAuthUIDs.Result?.Count ?? 0;
|
Logger.LogWarning(ex, "Could not parse OAuth token, deleting");
|
||||||
var primaryUid = _discordOAuthUIDs.Result?.FirstOrDefault() ?? new KeyValuePair<string, string>(string.Empty, string.Empty);
|
selectedServer.OAuthToken = null;
|
||||||
var vanity = string.IsNullOrEmpty(primaryUid.Value) ? "-" : primaryUid.Value;
|
_serverConfigurationManager.Save();
|
||||||
if (foundUids > 0)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenExpiry > DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
ColorTextWrapped($"OAuth2 is enabled, linked to: Discord User {_serverConfigurationManager.GetDiscordUserFromToken(selectedServer)}", ImGuiColors.HealerGreen);
|
||||||
|
TextWrapped($"The OAuth2 token will expire on {tokenExpiry:yyyy-MM-dd} and automatically renew itself during login on or after {(tokenExpiry - TimeSpan.FromDays(7)):yyyy-MM-dd}.");
|
||||||
|
using (ImRaii.Disabled(!CtrlPressed()))
|
||||||
|
{
|
||||||
|
if (IconTextButton(FontAwesomeIcon.Exclamation, "Renew OAuth2 token manually") && CtrlPressed())
|
||||||
{
|
{
|
||||||
ColorTextWrapped($"Found {foundUids} associated UIDs on the server, Primary UID: {primaryUid.Key} (Vanity UID: {vanity})",
|
_ = _tokenProvider.TryUpdateOAuth2LoginTokenAsync(selectedServer, forced: true)
|
||||||
ImGuiColors.HealerGreen);
|
.ContinueWith((_) => _apiController.CreateConnectionsAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawHelpText("Hold CTRL to manually refresh your OAuth2 token. Normally you do not need to do this.");
|
||||||
|
ImGuiHelpers.ScaledDummy(10f);
|
||||||
|
|
||||||
|
if ((_discordOAuthUIDs == null || _discordOAuthUIDs.IsCompleted)
|
||||||
|
&& IconTextButton(FontAwesomeIcon.Question, "Check Discord Connection"))
|
||||||
|
{
|
||||||
|
_discordOAuthUIDs = _serverConfigurationManager.GetUIDsWithDiscordToken(selectedServer.ServerUri, oauthToken);
|
||||||
|
}
|
||||||
|
else if (_discordOAuthUIDs != null)
|
||||||
|
{
|
||||||
|
if (!_discordOAuthUIDs.IsCompleted)
|
||||||
|
{
|
||||||
|
ColorTextWrapped("Checking UIDs on Server", ImGuiColors.DalamudYellow);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ColorTextWrapped($"Found no UIDs associated to this linked OAuth2 account", ImGuiColors.DalamudRed);
|
var foundUids = _discordOAuthUIDs.Result?.Count ?? 0;
|
||||||
|
var primaryUid = _discordOAuthUIDs.Result?.FirstOrDefault() ?? new KeyValuePair<string, string>(string.Empty, string.Empty);
|
||||||
|
var vanity = string.IsNullOrEmpty(primaryUid.Value) ? "-" : primaryUid.Value;
|
||||||
|
if (foundUids > 0)
|
||||||
|
{
|
||||||
|
ColorTextWrapped($"Found {foundUids} associated UIDs on the server, Primary UID: {primaryUid.Key} (Vanity UID: {vanity})",
|
||||||
|
ImGuiColors.HealerGreen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ColorTextWrapped($"Found no UIDs associated to this linked OAuth2 account", ImGuiColors.DalamudRed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ColorTextWrapped("The OAuth2 token is stale and expired. Please renew the OAuth2 connection.", ImGuiColors.DalamudRed);
|
||||||
|
if (IconTextButton(FontAwesomeIcon.Exclamation, "Renew OAuth2 connection"))
|
||||||
|
{
|
||||||
|
selectedServer.OAuthToken = null;
|
||||||
|
_serverConfigurationManager.Save();
|
||||||
|
_ = _serverConfigurationManager.CheckDiscordOAuth(selectedServer.ServerUri)
|
||||||
|
.ContinueWith(async (urlTask) =>
|
||||||
|
{
|
||||||
|
var url = await urlTask.ConfigureAwait(false);
|
||||||
|
var token = await _serverConfigurationManager.GetDiscordOAuthToken(url!, selectedServer.ServerUri, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
selectedServer.OAuthToken = token;
|
||||||
|
_serverConfigurationManager.Save();
|
||||||
|
await _apiController.CreateConnectionsAsync().ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DrawUnlinkOAuthButton(selectedServer);
|
DrawUnlinkOAuthButton(selectedServer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await _tokenProvider.TryUpdateOAuth2LoginTokenAsync().ConfigureAwait(false))
|
if (!await _tokenProvider.TryUpdateOAuth2LoginTokenAsync(_serverManager.CurrentServer).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
Logger.LogWarning("OAuth2 login token could not be updated");
|
Logger.LogWarning("OAuth2 login token could not be updated");
|
||||||
_connectionDto = null;
|
_connectionDto = null;
|
||||||
|
|||||||
@@ -235,21 +235,23 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
|
|||||||
return await GetNewToken(renewal, jwtIdentifier, ct).ConfigureAwait(false);
|
return await GetNewToken(renewal, jwtIdentifier, ct).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryUpdateOAuth2LoginTokenAsync()
|
public async Task<bool> TryUpdateOAuth2LoginTokenAsync(ServerStorage currentServer, bool forced = false)
|
||||||
{
|
{
|
||||||
var oauth2 = _serverManager.GetOAuth2(out _);
|
var oauth2 = _serverManager.GetOAuth2(out _);
|
||||||
if (oauth2 == null) return false;
|
if (oauth2 == null) return false;
|
||||||
|
|
||||||
var handler = new JwtSecurityTokenHandler();
|
var handler = new JwtSecurityTokenHandler();
|
||||||
var jwt = handler.ReadJwtToken(oauth2.Value.OAuthToken);
|
var jwt = handler.ReadJwtToken(oauth2.Value.OAuthToken);
|
||||||
if (jwt.ValidTo == DateTime.MinValue || jwt.ValidTo.Subtract(TimeSpan.FromDays(7)) > DateTime.Now)
|
if (!forced)
|
||||||
return true;
|
{
|
||||||
|
if (jwt.ValidTo == DateTime.MinValue || jwt.ValidTo.Subtract(TimeSpan.FromDays(7)) > DateTime.Now)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (jwt.ValidTo < DateTime.UtcNow)
|
if (jwt.ValidTo < DateTime.UtcNow)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenUri = MareAuth.RenewOAuthTokenFullPath(new Uri(currentServer.ServerUri
|
||||||
var tokenUri = MareAuth.RenewOAuthTokenFullPath(new Uri(_serverManager.CurrentApiUrl
|
|
||||||
.Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase)
|
.Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase)
|
||||||
.Replace("ws://", "http://", StringComparison.OrdinalIgnoreCase)));
|
.Replace("ws://", "http://", StringComparison.OrdinalIgnoreCase)));
|
||||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, tokenUri.ToString());
|
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, tokenUri.ToString());
|
||||||
@@ -260,13 +262,13 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
|
|||||||
if (!result.IsSuccessStatusCode)
|
if (!result.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Could not renew OAuth2 Login token, error code {error}", result.StatusCode);
|
_logger.LogWarning("Could not renew OAuth2 Login token, error code {error}", result.StatusCode);
|
||||||
_serverManager.CurrentServer.OAuthToken = null;
|
currentServer.OAuthToken = null;
|
||||||
_serverManager.Save();
|
_serverManager.Save();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newToken = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
var newToken = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
_serverManager.CurrentServer.OAuthToken = newToken;
|
currentServer.OAuthToken = newToken;
|
||||||
_serverManager.Save();
|
_serverManager.Save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user