Can log into the Nexus via the internal browser, and can cancel via the back button.

This commit is contained in:
Timothy Baldridge 2019-12-06 22:40:57 -07:00
parent a8a344d4be
commit 101d45f20c
8 changed files with 149 additions and 21 deletions

View File

@ -3,9 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Alphaleonis.Win32.Filesystem;
using Wabbajack.Common;
using Xilium.CefGlue;
namespace Wabbajack.Lib.LibCefHelpers
{
@ -29,5 +31,51 @@ namespace Wabbajack.Lib.LibCefHelpers
FileExtractor.ExtractAll(wq, "cefglue.7z", ".");
}
public static async Task<Cookie[]> GetCookies(string domainEnding)
{
var manager = CefCookieManager.GetGlobal(null);
var visitor = new CookieVisitor();
if (!manager.VisitAllCookies(visitor))
return new Cookie[0];
var cc = await visitor.Task;
return (await visitor.Task).Where(c => c.Domain.EndsWith(domainEnding)).ToArray();
}
private class CookieVisitor : CefCookieVisitor
{
TaskCompletionSource<List<Cookie>> _source = new TaskCompletionSource<List<Cookie>>();
public Task<List<Cookie>> Task => _source.Task;
public List<Cookie> Cookies { get; } = new List<Cookie>();
protected override bool Visit(CefCookie cookie, int count, int total, out bool delete)
{
Cookies.Add(new Cookie
{
Name = cookie.Name,
Value = cookie.Value,
Domain = cookie.Domain,
Path = cookie.Path
});
if (count == total)
_source.SetResult(Cookies);
delete = false;
return true;
}
protected override void Dispose(bool disposing)
{
if (disposing)
_source.SetResult(Cookies);
}
}
public class Cookie
{
public string Name { get; set; }
public string Value { get; set; }
public string Domain { get; set; }
public string Path { get; set; }
}
}
}

View File

@ -40,6 +40,10 @@ namespace Wabbajack.Lib
ConfigureProcessor(18, RecommendQueueSize());
var game = GameRegistry.Games[ModList.GameType];
// TODO: TESTING
var api = new NexusApiClient();
api.GetUserStatus();
if (GameFolder == null)
GameFolder = game.GameLocation;

View File

@ -12,10 +12,16 @@ using System.Security.Authentication;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
using Syroot.Windows.IO;
using Wabbajack.Common;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.LibCefHelpers;
using WebSocketSharp;
using Xilium.CefGlue;
using Xilium.CefGlue.Common;
using Xilium.CefGlue.Common.Handlers;
using Xilium.CefGlue.WPF;
using static Wabbajack.Lib.NexusApi.NexusApiUtils;
namespace Wabbajack.Lib.NexusApi
@ -66,17 +72,11 @@ namespace Wabbajack.Lib.NexusApi
File.Delete(API_KEY_CACHE_FILE);
}
var cacheFolder = Path.Combine(new KnownFolder(KnownFolderType.LocalAppData).Path, "Wabbajack");
if (!Directory.Exists(cacheFolder))
{
Directory.CreateDirectory(cacheFolder);
}
try
{
return Utils.FromEncryptedJson<string>("nexusapikey");
}
catch (CryptographicException)
catch (Exception)
{
}
@ -92,8 +92,36 @@ namespace Wabbajack.Lib.NexusApi
}
}
public async Task<string> SetupNexusLogin(Action<Uri> browserNavigate)
class RefererHandler : RequestHandler
{
private string _referer;
public RefererHandler(string referer)
{
_referer = referer;
}
protected override bool OnBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, bool userGesture, bool isRedirect)
{
base.OnBeforeBrowse(browser, frame, request, userGesture, isRedirect);
if (request.ReferrerURL == null)
request.SetReferrer(_referer, CefReferrerPolicy.Default);
return false;
}
}
public static async Task<string> SetupNexusLogin(BaseCefBrowser browser, Action<string> updateStatus)
{
updateStatus("Please Log Into the Nexus");
browser.Address = "https://users.nexusmods.com/auth/continue?client_id=nexus&redirect_uri=https://www.nexusmods.com/oauth/callback&response_type=code&referrer=//www.nexusmods.com";
while (true)
{
var cookies = (await Helpers.GetCookies("nexusmods.com"));
if (cookies.FirstOrDefault(c => c.Name == "member_id") != null)
break;
await Task.Delay(500);
}
// open a web socket to receive the api key
var guid = Guid.NewGuid();
var _websocket = new WebSocket("wss://sso.nexusmods.com")
@ -104,14 +132,16 @@ namespace Wabbajack.Lib.NexusApi
}
};
updateStatus("Please Authorize Wabbajack to Download Mods");
var api_key = new TaskCompletionSource<string>();
_websocket.OnMessage += (sender, msg) => { api_key.SetResult(msg.Data); };
_websocket.Connect();
_websocket.Send("{\"id\": \"" + guid + "\", \"appid\": \"" + Consts.AppName + "\"}");
await Task.Delay(1000);
// open a web browser to get user permission
browserNavigate(new Uri($"https://www.nexusmods.com/sso?id={guid}&application=" + Consts.AppName));
browser.Address = $"https://www.nexusmods.com/sso?id={guid}&application={Consts.AppName}";
return await api_key.Task;
}

View File

@ -102,10 +102,14 @@ namespace Wabbajack
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
_listBox.ScrollIntoView(e.NewItems[0]);
_listBox.SelectedItem = e.NewItems[0];
try
{
_listBox.ScrollIntoView(e.NewItems[0]);
_listBox.SelectedItem = e.NewItems[0];
}
catch (ArgumentOutOfRangeException) { }
}
}
}
}
}
}

View File

@ -6,10 +6,13 @@ using System;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using Wabbajack.Common;
using Wabbajack.Common.StatusFeed;
using Wabbajack.Lib;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.StatusMessages;
namespace Wabbajack
@ -34,10 +37,12 @@ namespace Wabbajack
public readonly Lazy<ModListGalleryVM> Gallery;
public readonly ModeSelectionVM ModeSelectionVM;
public readonly WebBrowserVM WebBrowserVM;
public Dispatcher ViewDispatcher { get; set; }
public MainWindowVM(MainWindow mainWindow, MainSettings settings)
{
MainWindow = mainWindow;
ViewDispatcher = MainWindow.Dispatcher;
Settings = settings;
Installer = new Lazy<InstallerVM>(() => new InstallerVM(this));
Compiler = new Lazy<CompilerVM>(() => new CompilerVM(this));
@ -61,6 +66,10 @@ namespace Wabbajack
.OfType<ConfirmUpdateOfExistingInstall>()
.Subscribe(msg => ConfirmUpdate(msg));
Utils.LogMessages
.OfType<RequestNexusAuthorization>()
.Subscribe(HandleRequestNexusAuthorization);
if (IsStartingFromModlist(out var path))
{
Installer.Value.ModListLocation.TargetPath = path;
@ -69,11 +78,42 @@ namespace Wabbajack
else
{
// Start on mode selection
//ActivePane = ModeSelectionVM;
ActivePane = WebBrowserVM;
ActivePane = ModeSelectionVM;
}
}
private void HandleRequestNexusAuthorization(RequestNexusAuthorization msg)
{
ViewDispatcher.InvokeAsync(async () =>
{
var oldPane = ActivePane;
var vm = new WebBrowserVM();
ActivePane = vm;
try
{
vm.BackCommand = ReactiveCommand.Create(() =>
{
ActivePane = oldPane;
msg.Cancel();
});
}
catch (Exception e)
{ }
try
{
var key = await NexusApiClient.SetupNexusLogin(vm.Browser, m => vm.Instructions = m);
msg.Resume(key);
}
catch (Exception ex)
{
msg.Cancel();
}
ActivePane = oldPane;
});
}
private void ConfirmUpdate(ConfirmUpdateOfExistingInstall msg)
{
var result = MessageBox.Show(msg.ExtendedDescription, msg.ShortDescription, MessageBoxButton.OKCancel);

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Wabbajack.Lib;
using Xilium.CefGlue.Common;
@ -12,16 +13,17 @@ namespace Wabbajack
{
public class WebBrowserVM : ViewModel
{
[Reactive]
public string Address { get; set; }
[Reactive]
public string Instructions { get; set; }
public BaseCefBrowser Browser { get; internal set; }
public WpfCefBrowser Browser { get; }
public WebBrowserVM()
[Reactive]
public IReactiveCommand BackCommand { get; set; }
public WebBrowserVM(string url = "http://www.wabbajack.org")
{
Browser = new WpfCefBrowser();
Browser.Address = url;
Instructions = "Wabbajack Web Browser";
}
}

View File

@ -65,6 +65,7 @@
ToolTip="Back to main menu">
<iconPacks:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
</Button>
<wpf:WpfCefBrowser Grid.Row="1" Address="http://www.wabbajack.org" Name="Browser"></wpf:WpfCefBrowser>
<!-- Do it this way so we can access the browser directly from the VM -->
<ContentControl Grid.Row="1" Content="{Binding Browser}"></ContentControl>
</Grid>
</UserControl>

View File

@ -23,7 +23,6 @@ namespace Wabbajack
public WebBrowserView()
{
InitializeComponent();
((WebBrowserVM)DataContext).Browser = Browser;
}
}
}