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;
};
|