diff --git a/Database/Session.cpp b/Database/Session.cpp index e74b0e5..88b2669 100644 --- a/Database/Session.cpp +++ b/Database/Session.cpp @@ -1,10 +1,10 @@ #include "Session.h" #include "BoostLog.h" #include -#include -#include #include #include +#include +#include namespace Database { std::unique_ptr sqlConnectionPool; diff --git a/WebApplication/Application.cpp b/WebApplication/Application.cpp index 65defc7..f61133c 100644 --- a/WebApplication/Application.cpp +++ b/WebApplication/Application.cpp @@ -51,6 +51,7 @@ Application::Application(const Wt::WEnvironment &env, bool embedded) : Wt::WAppl bindWidget(std::move(topPtr), *div); } else { LOG(error) << "Missing: parameter: 'div'"; + m_root = nullptr; } auto externalPath = env.getParameter("path"); if (externalPath != nullptr) { @@ -67,10 +68,16 @@ Application::Application(const Wt::WEnvironment &env, bool embedded) : Wt::WAppl LOG(info) << "relative resources url: " << relativeResourcesUrl(); LOG(info) << "resources url: " << resourcesUrl(); LOG(info) << "internal path: " << internalPath(); + LOG(info) << "bookmark url: " << bookmarkUrl("/"); + LOG(info) << "relative url: " << resolveRelativeUrl("/"); auto app = Amass::Singleton::instance(); m_loginPage = std::make_unique(app->authService(), m_session->users(), m_session->login()); - m_loginPage->processEnvironment(); + if (m_externalPath.empty()) { + m_loginPage->processEnvironment(); + } else { + m_loginPage->processExternalEnvironment(m_externalPath, app->authService()); + } handlePathChange(m_externalPath.empty() ? internalPath() : m_externalPath); internalPathChanged().connect(this, &Application::handlePathChange); @@ -116,9 +123,13 @@ void Application::authEvent() { void Application::handlePathChange(const std::string &path) { LOG(info) << "handlePathChange: " << path; + if (m_root == nullptr) { + LOG(error) << "root container is null."; + return; + } if (path.starts_with("/wt/login")) { if (m_session->login().loggedIn()) { - std::exit(0); + LOG(info) << "already logged in."; } else { if (m_loginPage) { m_root->clear(); diff --git a/WebApplication/LoginPage.cpp b/WebApplication/LoginPage.cpp index 74ea8f7..29adc04 100644 --- a/WebApplication/LoginPage.cpp +++ b/WebApplication/LoginPage.cpp @@ -2,6 +2,7 @@ #include "Application.h" #include #include +#include #include LoginPage::LoginPage(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUserDatabase &users, Wt::Auth::Login &login) @@ -12,3 +13,53 @@ LoginPage::LoginPage(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUs setRegistrationEnabled(true); // setAttributeValue("style", "transform: translateY(-100px);"); } + +void LoginPage::processExternalEnvironment(const std::string &externalPath, Wt::Auth::AuthService &service) { + using namespace Wt::Auth; + std::string emailToken; + if (service.emailVerificationEnabled()) { + auto redirectPath = service.emailRedirectInternalPath(); + auto pos = externalPath.find(redirectPath); + if (pos != std::string::npos) { + emailToken = externalPath.substr(pos + redirectPath.size()); + } + } + if (!emailToken.empty()) { + EmailTokenResult result = model()->processEmailToken(emailToken); + switch (result.state()) { + case EmailTokenState::Invalid: + displayError(tr("Wt.Auth.error-invalid-token")); + break; + case EmailTokenState::Expired: + displayError(tr("Wt.Auth.error-token-expired")); + break; + case EmailTokenState::UpdatePassword: + letUpdatePassword(result.user(), false); + break; + case EmailTokenState::EmailConfirmed: + displayInfo(tr("Wt.Auth.info-email-confirmed")); + User user = result.user(); + + LoginState state = LoginState::Strong; + if (model()->hasMfaStep(user)) { + state = LoginState::RequiresMfa; + } + model()->loginUser(login(), user, state); + } + + /* + * In progressive bootstrap mode, this would cause a redirect w/o + * session ID, losing the dialog. + */ + if (Wt::WApplication::instance()->environment().ajax()) Wt::WApplication::instance()->setInternalPath("/"); + + return; + } + + User user = model()->processAuthToken(); + LoginState state = LoginState::Weak; + if (model()->hasMfaStep(user)) { + state = LoginState::RequiresMfa; + } + model()->loginUser(login(), user, state); +} \ No newline at end of file diff --git a/WebApplication/LoginPage.h b/WebApplication/LoginPage.h index 9b4d9da..58be829 100644 --- a/WebApplication/LoginPage.h +++ b/WebApplication/LoginPage.h @@ -6,6 +6,7 @@ class LoginPage : public Wt::Auth::AuthWidget { public: LoginPage(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUserDatabase &users, Wt::Auth::Login &login); + void processExternalEnvironment(const std::string &externalPath, Wt::Auth::AuthService &service); }; #endif // __LOGINWIDGET_H__ \ No newline at end of file