diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-11-03 18:36:12 +0100 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-11-03 18:39:51 +0100 |
commit | 211fd9d76cfd691eceb8c77297ee20fd0fde4bbb (patch) | |
tree | 287451ffac2b9eb556dd6d57578a6fbdee591913 /src | |
parent | Merge branch 'macos_api_updates' into 'master' (diff) | |
download | nheko-211fd9d76cfd691eceb8c77297ee20fd0fde4bbb.tar.xz |
Fix registration on matrix.org
This was a bit of a journey: https://github.com/matrix-org/matrix-doc/pull/3471 But it should work now and we now use the UIAHandler everywhere. fixes #670
Diffstat (limited to '')
-rw-r--r-- | src/RegisterPage.cpp | 123 | ||||
-rw-r--r-- | src/RegisterPage.h | 4 | ||||
-rw-r--r-- | src/ui/UIA.cpp | 146 | ||||
-rw-r--r-- | src/ui/UIA.h | 17 |
4 files changed, 168 insertions, 122 deletions
diff --git a/src/RegisterPage.cpp b/src/RegisterPage.cpp index 0204a307..271a7fc2 100644 --- a/src/RegisterPage.cpp +++ b/src/RegisterPage.cpp @@ -23,6 +23,7 @@ #include "ui/FlatButton.h" #include "ui/RaisedButton.h" #include "ui/TextField.h" +#include "ui/UIA.h" #include "dialogs/FallbackAuth.h" #include "dialogs/ReCaptcha.h" @@ -178,8 +179,6 @@ RegisterPage::RegisterPage(QWidget *parent) connect(this, &RegisterPage::wellKnownLookup, this, &RegisterPage::doWellKnownLookup); connect(this, &RegisterPage::versionsCheck, this, &RegisterPage::doVersionsCheck); connect(this, &RegisterPage::registration, this, &RegisterPage::doRegistration); - connect(this, &RegisterPage::UIA, this, &RegisterPage::doUIA); - connect(this, &RegisterPage::registrationWithAuth, this, &RegisterPage::doRegistrationWithAuth); } void @@ -277,18 +276,11 @@ RegisterPage::onRegisterButtonClicked() // // The sequence of events looks something like this: // - // dowellKnownLookup + // doKnownLookup // v // doVersionsCheck // v - // doRegistration - // v - // doUIA <-----------------+ - // v | More auth required - // doRegistrationWithAuth -+ - // | Success - // v - // registering + // doRegistration -> loops the UIAHandler until complete emit wellKnownLookup(); @@ -367,18 +359,12 @@ RegisterPage::doRegistration() if (checkUsername() && checkPassword() && checkPasswordConfirmation()) { auto username = username_input_->text().toStdString(); auto password = password_input_->text().toStdString(); - http::client()->registration(username, password, registrationCb()); - } -} - -void -RegisterPage::doRegistrationWithAuth(const mtx::user_interactive::Auth &auth) -{ - // These inputs should still be alright, but check just in case - if (checkUsername() && checkPassword() && checkPasswordConfirmation()) { - auto username = username_input_->text().toStdString(); - auto password = password_input_->text().toStdString(); - http::client()->registration(username, password, auth, registrationCb()); + connect(UIA::instance(), &UIA::error, this, [this](QString msg) { + showError(msg); + disconnect(UIA::instance(), &UIA::error, this, nullptr); + }); + http::client()->registration( + username, password, ::UIA::instance()->genericHandler("Registration"), registrationCb()); } } @@ -392,6 +378,7 @@ RegisterPage::registrationCb() http::client()->set_user(res.user_id); http::client()->set_access_token(res.access_token); emit registerOk(); + disconnect(UIA::instance(), &UIA::error, this, nullptr); return; } @@ -403,11 +390,7 @@ RegisterPage::registrationCb() static_cast<int>(err->status_code), err->matrix_error.error); showError(QString::fromStdString(err->matrix_error.error)); - return; } - - // Attempt to complete a UIA stage - emit UIA(err->matrix_error.unauthorized); return; } @@ -420,92 +403,6 @@ RegisterPage::registrationCb() } void -RegisterPage::doUIA(const mtx::user_interactive::Unauthorized &unauthorized) -{ - auto completed_stages = unauthorized.completed; - auto flows = unauthorized.flows; - auto session = - unauthorized.session.empty() ? http::client()->generate_txn_id() : unauthorized.session; - - nhlog::ui()->info("Completed stages: {}", completed_stages.size()); - - if (!completed_stages.empty()) { - // Get rid of all flows which don't start with the sequence of - // stages that have already been completed. - flows.erase(std::remove_if(flows.begin(), - flows.end(), - [completed_stages](auto flow) { - if (completed_stages.size() > flow.stages.size()) - return true; - for (size_t f = 0; f < completed_stages.size(); f++) - if (completed_stages[f] != flow.stages[f]) - return true; - return false; - }), - flows.end()); - } - - if (flows.empty()) { - nhlog::ui()->error("No available registration flows!"); - showError(tr("No supported registration flows!")); - return; - } - - auto current_stage = flows.front().stages.at(completed_stages.size()); - - if (current_stage == mtx::user_interactive::auth_types::recaptcha) { - auto captchaDialog = new dialogs::ReCaptcha(QString::fromStdString(session), this); - - connect( - captchaDialog, &dialogs::ReCaptcha::confirmation, this, [this, session, captchaDialog]() { - captchaDialog->close(); - captchaDialog->deleteLater(); - doRegistrationWithAuth( - mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Fallback{}}); - }); - - connect(captchaDialog, &dialogs::ReCaptcha::cancel, this, &RegisterPage::errorOccurred); - - QTimer::singleShot(1000, this, [captchaDialog]() { captchaDialog->show(); }); - - } else if (current_stage == mtx::user_interactive::auth_types::dummy) { - doRegistrationWithAuth( - mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Dummy{}}); - - } else if (current_stage == mtx::user_interactive::auth_types::registration_token) { - bool ok; - QString token = QInputDialog::getText(this, - tr("Registration token"), - tr("Please enter a valid registration token."), - QLineEdit::Normal, - QString(), - &ok); - - if (ok) { - emit registrationWithAuth(mtx::user_interactive::Auth{ - session, mtx::user_interactive::auth::RegistrationToken{token.toStdString()}}); - } else { - emit errorOccurred(); - } - } else { - // use fallback - auto dialog = new dialogs::FallbackAuth( - QString::fromStdString(current_stage), QString::fromStdString(session), this); - - connect(dialog, &dialogs::FallbackAuth::confirmation, this, [this, session, dialog]() { - dialog->close(); - dialog->deleteLater(); - emit registrationWithAuth( - mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Fallback{}}); - }); - - connect(dialog, &dialogs::FallbackAuth::cancel, this, &RegisterPage::errorOccurred); - - dialog->show(); - } -} - -void RegisterPage::paintEvent(QPaintEvent *) { QStyleOption opt; diff --git a/src/RegisterPage.h b/src/RegisterPage.h index b88808f9..0d7da9ad 100644 --- a/src/RegisterPage.h +++ b/src/RegisterPage.h @@ -39,8 +39,6 @@ signals: void wellKnownLookup(); void versionsCheck(); void registration(); - void UIA(const mtx::user_interactive::Unauthorized &unauthorized); - void registrationWithAuth(const mtx::user_interactive::Auth &auth); void registering(); void registerOk(); @@ -62,8 +60,6 @@ private slots: void doWellKnownLookup(); void doVersionsCheck(); void doRegistration(); - void doUIA(const mtx::user_interactive::Unauthorized &unauthorized); - void doRegistrationWithAuth(const mtx::user_interactive::Auth &auth); mtx::http::Callback<mtx::responses::Register> registrationCb(); private: diff --git a/src/ui/UIA.cpp b/src/ui/UIA.cpp index 29161382..c157ea0f 100644 --- a/src/ui/UIA.cpp +++ b/src/ui/UIA.cpp @@ -9,6 +9,8 @@ #include <QInputDialog> #include <QTimer> +#include <mtx/responses/common.hpp> + #include "Logging.h" #include "MainWindow.h" #include "dialogs/FallbackAuth.h" @@ -54,6 +56,7 @@ UIA::genericHandler(QString context) if (flows.empty()) { nhlog::ui()->error("No available registration flows!"); + emit error(tr("No available registration flows!")); return; } @@ -61,6 +64,10 @@ UIA::genericHandler(QString context) if (current_stage == mtx::user_interactive::auth_types::password) { emit password(); + } else if (current_stage == mtx::user_interactive::auth_types::email_identity) { + emit email(); + } else if (current_stage == mtx::user_interactive::auth_types::msisdn) { + emit phoneNumber(); } else if (current_stage == mtx::user_interactive::auth_types::recaptcha) { auto captchaDialog = new dialogs::ReCaptcha(QString::fromStdString(u.session), MainWindow::instance()); @@ -74,8 +81,9 @@ UIA::genericHandler(QString context) mtx::user_interactive::auth::Fallback{}}); }); - // connect( - // captchaDialog, &dialogs::ReCaptcha::cancel, this, &RegisterPage::errorOccurred); + connect(captchaDialog, &dialogs::ReCaptcha::cancel, this, [this]() { + emit error(tr("Registration aborted")); + }); QTimer::singleShot(0, this, [captchaDialog]() { captchaDialog->show(); }); @@ -98,7 +106,7 @@ UIA::genericHandler(QString context) u.session, mtx::user_interactive::auth::RegistrationToken{token.toStdString()}}); } else { - // emit errorOccurred(); + emit error(tr("Registration aborted")); } } else { // use fallback @@ -114,8 +122,9 @@ UIA::genericHandler(QString context) mtx::user_interactive::auth::Fallback{}}); }); - // connect(dialog, &dialogs::FallbackAuth::cancel, this, - // &RegisterPage::errorOccurred); + connect(dialog, &dialogs::FallbackAuth::cancel, this, [this]() { + emit error(tr("Registration aborted")); + }); dialog->show(); } @@ -134,3 +143,130 @@ UIA::continuePassword(QString password) if (currentHandler) currentHandler->next(mtx::user_interactive::Auth{currentStatus.session, p}); } + +void +UIA::continueEmail(QString email) +{ + mtx::requests::RequestEmailToken r{}; + r.client_secret = this->client_secret = mtx::client::utils::random_token(128, false); + r.email = email.toStdString(); + r.send_attempt = 0; + http::client()->register_email_request_token( + r, [this](const mtx::responses::RequestToken &token, mtx::http::RequestErr e) { + if (!e) { + this->sid = token.sid; + this->submit_url = token.submit_url; + this->email_ = true; + + if (submit_url.empty()) { + nhlog::ui()->debug("Got no submit url."); + emit confirm3pidToken(); + } else { + nhlog::ui()->debug("Got submit url: {}", token.submit_url); + emit prompt3pidToken(); + } + } else { + nhlog::ui()->debug("Registering email failed! ({},{},{},{})", + e->status_code, + e->status_code, + e->parse_error, + e->matrix_error.error); + emit error(QString::fromStdString(e->matrix_error.error)); + } + }); +} +void +UIA::continuePhoneNumber(QString countryCode, QString phoneNumber) +{ + mtx::requests::RequestMSISDNToken r{}; + r.client_secret = this->client_secret = mtx::client::utils::random_token(128, false); + r.country = countryCode.toStdString(); + r.phone_number = phoneNumber.toStdString(); + r.send_attempt = 0; + http::client()->register_phone_request_token( + r, [this](const mtx::responses::RequestToken &token, mtx::http::RequestErr e) { + if (!e) { + this->sid = token.sid; + this->submit_url = token.submit_url; + this->email_ = false; + if (submit_url.empty()) { + nhlog::ui()->debug("Got no submit url."); + emit confirm3pidToken(); + } else { + nhlog::ui()->debug("Got submit url: {}", token.submit_url); + emit prompt3pidToken(); + } + } else { + nhlog::ui()->debug("Registering phone number failed! ({},{},{},{})", + e->status_code, + e->status_code, + e->parse_error, + e->matrix_error.error); + emit error(QString::fromStdString(e->matrix_error.error)); + } + }); +} + +void +UIA::continue3pidReceived() +{ + mtx::user_interactive::auth::ThreePIDCred c{}; + c.client_secret = this->client_secret; + c.sid = this->sid; + + if (this->email_) { + mtx::user_interactive::auth::EmailIdentity i{}; + i.threepidCred = c; + this->currentHandler->next(mtx::user_interactive::Auth{currentStatus.session, i}); + } else { + mtx::user_interactive::auth::MSISDN i{}; + i.threepidCred = c; + this->currentHandler->next(mtx::user_interactive::Auth{currentStatus.session, i}); + } +} + +void +UIA::submit3pidToken(QString token) +{ + mtx::requests::IdentitySubmitToken t{}; + t.client_secret = this->client_secret; + t.sid = this->sid; + t.token = token.toStdString(); + + http::client()->validate_submit_token( + submit_url, t, [this](const mtx::responses::Success &success, mtx::http::RequestErr e) { + if (!e && success.success) { + mtx::user_interactive::auth::ThreePIDCred c{}; + c.client_secret = this->client_secret; + c.sid = this->sid; + + nhlog::ui()->debug("Submit token success"); + + if (this->email_) { + mtx::user_interactive::auth::EmailIdentity i{}; + i.threepidCred = c; + this->currentHandler->next(mtx::user_interactive::Auth{currentStatus.session, i}); + } else { + mtx::user_interactive::auth::MSISDN i{}; + i.threepidCred = c; + this->currentHandler->next(mtx::user_interactive::Auth{currentStatus.session, i}); + } + } else { + if (e) { + nhlog::ui()->debug("Submit token invalid! ({},{},{},{})", + e->status_code, + e->status_code, + e->parse_error, + e->matrix_error.error); + emit error(QString::fromStdString(e->matrix_error.error)); + } else { + nhlog::ui()->debug("Submit token invalid!"); + emit error(tr("Invalid token")); + } + } + + this->client_secret.clear(); + this->sid.clear(); + this->submit_url.clear(); + }); +} diff --git a/src/ui/UIA.h b/src/ui/UIA.h index fb047451..0db23897 100644 --- a/src/ui/UIA.h +++ b/src/ui/UIA.h @@ -27,14 +27,31 @@ public: public slots: void continuePassword(QString password); + void continueEmail(QString email); + void continuePhoneNumber(QString countryCode, QString phoneNumber); + void submit3pidToken(QString token); + void continue3pidReceived(); signals: void password(); + void email(); + void phoneNumber(); + + void confirm3pidToken(); + void prompt3pidToken(); + void tokenAccepted(); void titleChanged(); + void error(QString msg); private: std::optional<mtx::http::UIAHandler> currentHandler; mtx::user_interactive::Unauthorized currentStatus; QString title_; + + // for 3pids like email and phone number + std::string client_secret; + std::string sid; + std::string submit_url; + bool email_ = true; }; |