From f28f8c392d669ff35c13b96adc03d35eb1469903 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 5 Sep 2022 16:14:07 -0400 Subject: [PATCH] Add LauncherCore::autoLogin function, remove separate impls Previously there was two separate auto-login functions, one in the cli interface and one for the desktop interface. If I didn't stop myself, there would probably be one in the tablet interface too! --- launcher/cli/src/cmdinterface.cpp | 40 +------------- launcher/core/CMakeLists.txt | 4 +- launcher/core/include/launchercore.h | 9 ++++ launcher/core/src/launchercore.cpp | 67 ++++++++++++++++++++++++ launcher/desktop/CMakeLists.txt | 4 +- launcher/desktop/src/autologinwindow.cpp | 60 +-------------------- 6 files changed, 82 insertions(+), 102 deletions(-) diff --git a/launcher/cli/src/cmdinterface.cpp b/launcher/cli/src/cmdinterface.cpp index 07351f1..998177f 100644 --- a/launcher/cli/src/cmdinterface.cpp +++ b/launcher/cli/src/cmdinterface.cpp @@ -21,45 +21,7 @@ bool CMDInterface::parse(QCommandLineParser& parser, LauncherCore& core) { if (parser.isSet(autologinOption)) { auto& profile = core.getProfile(core.defaultProfileIndex); - if (!profile.rememberUsername || !profile.rememberPassword) { - qInfo() << "Profile does not have a username and/or password saved, autologin disabled."; - - return false; - } - - auto loop = new QEventLoop(); - QString username, password; - - auto usernameJob = new QKeychain::ReadPasswordJob("LauncherWindow"); - usernameJob->setKey(profile.name + "-username"); - usernameJob->start(); - - core.connect( - usernameJob, &QKeychain::ReadPasswordJob::finished, [loop, usernameJob, &username](QKeychain::Job* j) { - username = usernameJob->textData(); - loop->quit(); - }); - - loop->exec(); - - auto passwordJob = new QKeychain::ReadPasswordJob("LauncherWindow"); - passwordJob->setKey(profile.name + "-password"); - passwordJob->start(); - - core.connect( - passwordJob, &QKeychain::ReadPasswordJob::finished, [loop, passwordJob, &password](QKeychain::Job* j) { - password = passwordJob->textData(); - loop->quit(); - }); - - loop->exec(); - - auto info = new LoginInformation(); - info->settings = &profile; - info->username = username; - info->password = password; - - core.login(*info); + return core.autoLogin(profile); } return true; diff --git a/launcher/core/CMakeLists.txt b/launcher/core/CMakeLists.txt index ed6dc17..2592dcf 100644 --- a/launcher/core/CMakeLists.txt +++ b/launcher/core/CMakeLists.txt @@ -53,7 +53,9 @@ target_link_libraries(astra_core PUBLIC Qt5::Widgets # widgets is required by watchdog, to be fixed/removed later Qt5::Quick # required for some type registrations PRIVATE - astra_desktop) # desktop is currently required by the core, to be fixed/removed later + astra_desktop + cotp + crypto) # desktop is currently required by the core, to be fixed/removed later if (ENABLE_WATCHDOG) target_include_directories(astra_core PUBLIC ${TESSERACT_INCLUDE_DIRS} ${LEPTONICA_INCLUDE_DIRS}) diff --git a/launcher/core/include/launchercore.h b/launcher/core/include/launchercore.h index 62e788b..393a86c 100755 --- a/launcher/core/include/launchercore.h +++ b/launcher/core/include/launchercore.h @@ -161,6 +161,15 @@ public: */ void login(LoginInformation& loginInformation); + /* + * Attempts to log into a profile without LoginInformation, which may or may not work depending on a combination of + * the password failing, OTP not being available to auto-generate, among other things. + * + * The launcher will still warn the user about any possible errors, however the call site will need to check the + * result to see whether they need to "reset" or show a failed state or not. + */ + bool autoLogin(ProfileSettings& settings); + /* * Launches the game using the provided authentication. */ diff --git a/launcher/core/src/launchercore.cpp b/launcher/core/src/launchercore.cpp index 7b84c6a..ea20fd6 100755 --- a/launcher/core/src/launchercore.cpp +++ b/launcher/core/src/launchercore.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "assetupdater.h" #include "encryptedarg.h" @@ -731,3 +732,69 @@ void LauncherCore::login(LoginInformation& loginInformation) { squareBoot->checkGateStatus(&loginInformation); } } + +bool LauncherCore::autoLogin(ProfileSettings& profile) { + auto loop = new QEventLoop(); + + QString username, password; + QString otpSecret; + + auto usernameJob = new QKeychain::ReadPasswordJob("LauncherWindow"); + usernameJob->setKey(profile.name + "-username"); + usernameJob->start(); + + QObject::connect( + usernameJob, &QKeychain::ReadPasswordJob::finished, [loop, usernameJob, &username](QKeychain::Job* j) { + username = usernameJob->textData(); + loop->quit(); + }); + + loop->exec(); + + auto passwordJob = new QKeychain::ReadPasswordJob("LauncherWindow"); + passwordJob->setKey(profile.name + "-password"); + passwordJob->start(); + + QObject::connect( + passwordJob, &QKeychain::ReadPasswordJob::finished, [loop, passwordJob, &password](QKeychain::Job* j) { + password = passwordJob->textData(); + loop->quit(); + }); + + loop->exec(); + + // TODO: handle cases where the user doesn't want to store their OTP secret, so we have to manually prompt them + if(profile.useOneTimePassword && profile.rememberOTPSecret) { + auto otpJob = new QKeychain::ReadPasswordJob("LauncherWindow"); + otpJob->setKey(profile.name + "-otpsecret"); + otpJob->start(); + + QObject::connect( + otpJob, &QKeychain::ReadPasswordJob::finished, [loop, otpJob, &otpSecret](QKeychain::Job* j) { + otpSecret = otpJob->textData(); + loop->quit(); + }); + + loop->exec(); + } + + auto info = new LoginInformation(); + info->settings = &profile; + info->username = username; + info->password = password; + + if(profile.useOneTimePassword && !profile.rememberOTPSecret) + return false; + + if(profile.useOneTimePassword && profile.rememberOTPSecret) { + // generate otp + char* totp = get_totp (otpSecret.toStdString().c_str(), 6, 30, SHA1, nullptr); + info->oneTimePassword = totp; + free (totp); + } + + // TODO: when login fails, we need some way to propagate this back? or not? + login(*info); + + return true; +} diff --git a/launcher/desktop/CMakeLists.txt b/launcher/desktop/CMakeLists.txt index ec09198..ee94b4c 100644 --- a/launcher/desktop/CMakeLists.txt +++ b/launcher/desktop/CMakeLists.txt @@ -24,6 +24,4 @@ target_link_libraries(astra_desktop PUBLIC astra_core Qt5::Core Qt5::Widgets - Qt5::Network - cotp - crypto) \ No newline at end of file + Qt5::Network) \ No newline at end of file diff --git a/launcher/desktop/src/autologinwindow.cpp b/launcher/desktop/src/autologinwindow.cpp index 396b1d3..2d818bd 100644 --- a/launcher/desktop/src/autologinwindow.cpp +++ b/launcher/desktop/src/autologinwindow.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include "launchercore.h" #include "launcherwindow.h" @@ -36,64 +35,7 @@ AutoLoginWindow::AutoLoginWindow(ProfileSettings& profile, LauncherCore& core, Q auto autologinTimer = new QTimer(); connect(autologinTimer, &QTimer::timeout, [&, this, autologinTimer] { - // TODO: this is the second place where I have implemented this. this is a good idea to abstract, maybe? :-) - auto loop = new QEventLoop(); - - QString username, password; - QString otpSecret; - - auto usernameJob = new QKeychain::ReadPasswordJob("LauncherWindow"); - usernameJob->setKey(profile.name + "-username"); - usernameJob->start(); - - QObject::connect( - usernameJob, &QKeychain::ReadPasswordJob::finished, [loop, usernameJob, &username](QKeychain::Job* j) { - username = usernameJob->textData(); - loop->quit(); - }); - - loop->exec(); - - auto passwordJob = new QKeychain::ReadPasswordJob("LauncherWindow"); - passwordJob->setKey(profile.name + "-password"); - passwordJob->start(); - - QObject::connect( - passwordJob, &QKeychain::ReadPasswordJob::finished, [loop, passwordJob, &password](QKeychain::Job* j) { - password = passwordJob->textData(); - loop->quit(); - }); - - loop->exec(); - - // TODO: handle cases where the user doesn't want to store their OTP secret, so we have to manually prompt them - if(profile.useOneTimePassword && profile.rememberOTPSecret) { - auto otpJob = new QKeychain::ReadPasswordJob("LauncherWindow"); - otpJob->setKey(profile.name + "-otpsecret"); - otpJob->start(); - - QObject::connect( - otpJob, &QKeychain::ReadPasswordJob::finished, [loop, otpJob, &otpSecret](QKeychain::Job* j) { - otpSecret = otpJob->textData(); - loop->quit(); - }); - - loop->exec(); - } - - auto info = new LoginInformation(); - info->settings = &profile; - info->username = username; - info->password = password; - - if(profile.useOneTimePassword && profile.rememberOTPSecret) { - // generate otp - char *totp = get_totp (otpSecret.toStdString().c_str(), 6, 30, SHA1, nullptr); - info->oneTimePassword = totp; - free (totp); - } - - core.login(*info); + core.autoLogin(profile); close(); autologinTimer->stop();