From b8b0b5c618b2c4251902cda91bee53eef11c4f3f Mon Sep 17 00:00:00 2001 From: Callum Brown Date: Thu, 3 Jun 2021 13:56:43 +0100 Subject: [PATCH 1/2] Give registration server input its own error label --- src/RegisterPage.cpp | 10 +++++++++- src/RegisterPage.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/RegisterPage.cpp b/src/RegisterPage.cpp index 5c5545ec..fdc1be80 100644 --- a/src/RegisterPage.cpp +++ b/src/RegisterPage.cpp @@ -108,6 +108,10 @@ RegisterPage::RegisterPage(QWidget *parent) error_password_confirmation_label_->setWordWrap(true); error_password_confirmation_label_->hide(); + error_server_label_ = new QLabel(this); + error_server_label_->setWordWrap(true); + error_server_label_->hide(); + form_layout_->addWidget(username_input_, Qt::AlignHCenter); form_layout_->addWidget(error_username_label_, Qt::AlignHCenter); form_layout_->addWidget(password_input_, Qt::AlignHCenter); @@ -115,6 +119,7 @@ RegisterPage::RegisterPage(QWidget *parent) form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter); form_layout_->addWidget(error_password_confirmation_label_, Qt::AlignHCenter); form_layout_->addWidget(server_input_, Qt::AlignHCenter); + form_layout_->addWidget(error_server_label_, Qt::AlignHCenter); button_layout_ = new QHBoxLayout(); button_layout_->setSpacing(0); @@ -351,10 +356,12 @@ RegisterPage::checkFields() error_username_label_->setText(""); error_password_label_->setText(""); error_password_confirmation_label_->setText(""); + error_server_label_->setText(""); error_username_label_->hide(); error_password_label_->hide(); error_password_confirmation_label_->hide(); + error_server_label_->hide(); password_confirmation_->setValid(true); server_input_->setValid(true); @@ -379,7 +386,8 @@ RegisterPage::checkFields() all_fields_good = false; } else if (server_input_->isModified() && (!server_input_->hasAcceptableInput() || server_input_->text().isEmpty())) { - showError(tr("Invalid server name")); + error_server_label_->show(); + showError(error_server_label_, tr("Invalid server name")); server_input_->setValid(false); all_fields_good = false; } diff --git a/src/RegisterPage.h b/src/RegisterPage.h index 2f05d04c..75d524c9 100644 --- a/src/RegisterPage.h +++ b/src/RegisterPage.h @@ -63,6 +63,7 @@ private: QLabel *error_username_label_; QLabel *error_password_label_; QLabel *error_password_confirmation_label_; + QLabel *error_server_label_; FlatButton *back_button_; RaisedButton *register_button_; From 78607a7e59b15edc6b203d7f9226bedfa5dfcf3b Mon Sep 17 00:00:00 2001 From: Callum Brown Date: Thu, 3 Jun 2021 14:52:41 +0100 Subject: [PATCH 2/2] Do a .well-known lookup during registration --- src/RegisterPage.cpp | 136 +++++++++++++++++++++++++++++++++---------- src/RegisterPage.h | 5 ++ 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/src/RegisterPage.cpp b/src/RegisterPage.cpp index fdc1be80..36fd71a8 100644 --- a/src/RegisterPage.cpp +++ b/src/RegisterPage.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "Config.h" #include "Logging.h" @@ -145,6 +146,17 @@ RegisterPage::RegisterPage(QWidget *parent) top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter); top_layout_->addStretch(1); + connect( + this, + &RegisterPage::versionErrorCb, + this, + [this](const QString &msg) { + error_server_label_->show(); + server_input_->setValid(false); + showError(error_server_label_, msg); + }, + Qt::QueuedConnection); + connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked())); connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked())); @@ -414,51 +426,113 @@ RegisterPage::onRegisterButtonClicked() http::client()->set_server(server); http::client()->verify_certificates( !UserSettings::instance()->disableCertificateValidation()); - http::client()->registration( - username, - password, - [this, username, password](const mtx::responses::Register &res, + + http::client()->well_known( + [this, username, password](const mtx::responses::WellKnown &res, mtx::http::RequestErr err) { - if (!err) { - http::client()->set_user(res.user_id); - http::client()->set_access_token(res.access_token); + if (err) { + using namespace boost::beast::http; - emit registerOk(); - return; - } - - // The server requires registration flows. - if (err->status_code == boost::beast::http::status::unauthorized) { - if (err->matrix_error.unauthorized.flows.empty()) { - nhlog::net()->warn( - "failed to retrieve registration flows1: ({}) " - "{}", - static_cast(err->status_code), - err->matrix_error.error); - emit errorOccurred(); - emit registerErrorCb( - QString::fromStdString(err->matrix_error.error)); + if (err->status_code == status::not_found) { + nhlog::net()->info("Autodiscovery: No .well-known."); + checkVersionAndRegister(username, password); return; } - emit registrationFlow( - username, password, err->matrix_error.unauthorized); + if (!err->parse_error.empty()) { + emit versionErrorCb(tr( + "Autodiscovery failed. Received malformed response.")); + nhlog::net()->error( + "Autodiscovery failed. Received malformed response."); + return; + } + + emit versionErrorCb(tr("Autodiscovery failed. Unknown error when " + "requesting .well-known.")); + nhlog::net()->error("Autodiscovery failed. Unknown error when " + "requesting .well-known. {}", + err->error_code.message()); return; } - nhlog::net()->error( - "failed to register: status_code ({}), matrix_error({})", - static_cast(err->status_code), - err->matrix_error.error); - - emit registerErrorCb(QString::fromStdString(err->matrix_error.error)); - emit errorOccurred(); + nhlog::net()->info("Autodiscovery: Discovered '" + + res.homeserver.base_url + "'"); + http::client()->set_server(res.homeserver.base_url); + checkVersionAndRegister(username, password); }); emit registering(); } } +void +RegisterPage::checkVersionAndRegister(const std::string &username, const std::string &password) +{ + http::client()->versions( + [this, username, password](const mtx::responses::Versions &, mtx::http::RequestErr err) { + if (err) { + using namespace boost::beast::http; + + if (err->status_code == status::not_found) { + emit versionErrorCb(tr("The required endpoints were not found. " + "Possibly not a Matrix server.")); + return; + } + + if (!err->parse_error.empty()) { + emit versionErrorCb(tr("Received malformed response. Make sure " + "the homeserver domain is valid.")); + return; + } + + emit versionErrorCb(tr( + "An unknown error occured. Make sure the homeserver domain is valid.")); + return; + } + + http::client()->registration( + username, + password, + [this, username, password](const mtx::responses::Register &res, + mtx::http::RequestErr err) { + if (!err) { + http::client()->set_user(res.user_id); + http::client()->set_access_token(res.access_token); + + emit registerOk(); + return; + } + + // The server requires registration flows. + if (err->status_code == boost::beast::http::status::unauthorized) { + if (err->matrix_error.unauthorized.flows.empty()) { + nhlog::net()->warn( + "failed to retrieve registration flows1: ({}) " + "{}", + static_cast(err->status_code), + err->matrix_error.error); + emit errorOccurred(); + emit registerErrorCb( + QString::fromStdString(err->matrix_error.error)); + return; + } + + emit registrationFlow( + username, password, err->matrix_error.unauthorized); + return; + } + + nhlog::net()->error( + "failed to register: status_code ({}), matrix_error({})", + static_cast(err->status_code), + err->matrix_error.error); + + emit registerErrorCb(QString::fromStdString(err->matrix_error.error)); + emit errorOccurred(); + }); + }); +} + void RegisterPage::paintEvent(QPaintEvent *) { diff --git a/src/RegisterPage.h b/src/RegisterPage.h index 75d524c9..0e4a45d0 100644 --- a/src/RegisterPage.h +++ b/src/RegisterPage.h @@ -31,6 +31,10 @@ protected: signals: void backButtonClicked(); void errorOccurred(); + + //! Used to trigger the corresponding slot outside of the main thread. + void versionErrorCb(const QString &err); + void registering(); void registerOk(); void registerErrorCb(const QString &msg); @@ -52,6 +56,7 @@ private: bool checkOneField(QLabel *label, const TextField *t_field, const QString &msg); bool checkFields(); void showError(QLabel *label, const QString &msg); + void checkVersionAndRegister(const std::string &username, const std::string &password); QVBoxLayout *top_layout_; QHBoxLayout *back_layout_;