Do a .well-known lookup during registration

This commit is contained in:
Callum Brown 2021-06-03 14:52:41 +01:00
parent b8b0b5c618
commit 78607a7e59
2 changed files with 110 additions and 31 deletions

View file

@ -11,6 +11,7 @@
#include <QtMath> #include <QtMath>
#include <mtx/responses/register.hpp> #include <mtx/responses/register.hpp>
#include <mtx/responses/well-known.hpp>
#include "Config.h" #include "Config.h"
#include "Logging.h" #include "Logging.h"
@ -145,6 +146,17 @@ RegisterPage::RegisterPage(QWidget *parent)
top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter); top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
top_layout_->addStretch(1); 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(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked())); connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
@ -414,51 +426,113 @@ RegisterPage::onRegisterButtonClicked()
http::client()->set_server(server); http::client()->set_server(server);
http::client()->verify_certificates( http::client()->verify_certificates(
!UserSettings::instance()->disableCertificateValidation()); !UserSettings::instance()->disableCertificateValidation());
http::client()->registration(
username, http::client()->well_known(
password, [this, username, password](const mtx::responses::WellKnown &res,
[this, username, password](const mtx::responses::Register &res,
mtx::http::RequestErr err) { mtx::http::RequestErr err) {
if (!err) { if (err) {
http::client()->set_user(res.user_id); using namespace boost::beast::http;
http::client()->set_access_token(res.access_token);
emit registerOk(); if (err->status_code == status::not_found) {
return; nhlog::net()->info("Autodiscovery: No .well-known.");
} checkVersionAndRegister(username, password);
// 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<int>(err->status_code),
err->matrix_error.error);
emit errorOccurred();
emit registerErrorCb(
QString::fromStdString(err->matrix_error.error));
return; return;
} }
emit registrationFlow( if (!err->parse_error.empty()) {
username, password, err->matrix_error.unauthorized); 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; return;
} }
nhlog::net()->error( nhlog::net()->info("Autodiscovery: Discovered '" +
"failed to register: status_code ({}), matrix_error({})", res.homeserver.base_url + "'");
static_cast<int>(err->status_code), http::client()->set_server(res.homeserver.base_url);
err->matrix_error.error); checkVersionAndRegister(username, password);
emit registerErrorCb(QString::fromStdString(err->matrix_error.error));
emit errorOccurred();
}); });
emit registering(); 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<int>(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<int>(err->status_code),
err->matrix_error.error);
emit registerErrorCb(QString::fromStdString(err->matrix_error.error));
emit errorOccurred();
});
});
}
void void
RegisterPage::paintEvent(QPaintEvent *) RegisterPage::paintEvent(QPaintEvent *)
{ {

View file

@ -31,6 +31,10 @@ protected:
signals: signals:
void backButtonClicked(); void backButtonClicked();
void errorOccurred(); void errorOccurred();
//! Used to trigger the corresponding slot outside of the main thread.
void versionErrorCb(const QString &err);
void registering(); void registering();
void registerOk(); void registerOk();
void registerErrorCb(const QString &msg); void registerErrorCb(const QString &msg);
@ -52,6 +56,7 @@ private:
bool checkOneField(QLabel *label, const TextField *t_field, const QString &msg); bool checkOneField(QLabel *label, const TextField *t_field, const QString &msg);
bool checkFields(); bool checkFields();
void showError(QLabel *label, const QString &msg); void showError(QLabel *label, const QString &msg);
void checkVersionAndRegister(const std::string &username, const std::string &password);
QVBoxLayout *top_layout_; QVBoxLayout *top_layout_;
QHBoxLayout *back_layout_; QHBoxLayout *back_layout_;