Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
login.cpp 6.68 KiB
#include "login.h"

#include <QtDebug>

#include <mtx/identifiers.hpp>

#include "client.h"
#include "debug_out.h"
#include "settings.h"

Login::Login(QObject *parent) : QObject(parent) {}

void Login::tryReconnect() {
    Settings s;

    try {
        http::client().set_user(s.user().value());
        http::client().set_server(s.server().value());
        http::client().set_port(s.server_port().value());
        http::client().set_device_id(s.device_id().value());
        http::client().set_access_token(s.access_token().value());

        emit loginSuccess();
    } catch (std::exception &e) {
        qWarning() << "Relogin failed: " << QString::fromStdString(e.what());
    }
}

void Login::mxidEntered(QString mxid) {
    using namespace mtx::identifiers;
    std::cout << mxid.toStdString() << "\n";
    User user;

    try {
        user = parse<User>(mxid.toStdString());
    } catch (const std::exception &) {
        qDebug() << "Can't parse user!"
                 << "\n";

        emit userParseError("Can't parse User");
        return;
    }

    QString server = QString::fromStdString(user.hostname());

    http::client().well_known([this, server](const mtx::responses::WellKnown &well_known, mtx::http::RequestErr err) {
        if (err) {
            using namespace boost::beast::http;

            if (err->status_code == status::not_found) {
                qDebug() << "Autodiscovery: No .well-known.";
                this->validateServer(server);
                return;
            }

            if (!err->parse_error.empty()) {
                emit homeserverInvalid(server, tr("Autodiscovery failed. Received malformed response."));
                qDebug() << "Autodiscovery failed. Received malformed response." << *err;
                return;
            }

            emit homeserverInvalid(server, tr("Autodiscovery failed. Unknown error when requesting .well-known."));
            qDebug() << "Autodiscovery failed. Unknown error when requesting .weel-known.";
            return;
        }

        qDebug() << "Autodiscovery: Discovered '" << QString::fromStdString(well_known.homeserver.base_url) << "'";
        this->validateServer(QString::fromStdString(well_known.homeserver.base_url));
    });
}

void Login::homeserverEntered(QString server) { this->validateServer(server); }

void Login::validateServer(QString server) {
    http::client().set_server(server.toStdString());
    http::client().versions([this, server](const mtx::responses::Versions &, mtx::http::RequestErr err) {
        if (err) {
            using namespace boost::beast::http;

            if (err->status_code == status::not_found) {
                emit homeserverInvalid(server, tr("The required endpoints were not found. "
                                                  "Possibly not a Matrix server."));
                return;
            }

            if (!err->parse_error.empty()) {
                emit homeserverInvalid(server, tr("Received malformed response. Make sure "
                                                  "the homeserver domain is valid."));
                return;
            }

            emit homeserverInvalid(server, tr("An unknown error occured. Make sure "
                                              "the homeserver domain is valid."));
            return;
        }
    });
}

void Login::login(QString mxid, QString password, QString server) {
    qInfo() << "Logging in\n";

    using namespace mtx::identifiers;
    std::cout << mxid.toStdString() << "\n";
    User user;

    try {
        user = parse<User>(mxid.toStdString());
    } catch (const std::exception &) {
        qDebug() << "Can't parse user!"
                 << "\n";

        emit loginError("Can't parse User");
        return;
    }

    if (password.isEmpty()) {
        emit loginError(tr("Empty password"));
        return;
    }

    auto homeserver = user.hostname();
    if (server.size() > 0)
        homeserver = server.toStdString();

    http::client().login(user.localpart(), password.toStdString(), "Spoon",
                         [this, homeserver](const mtx::responses::Login &response, mtx::http::RequestErr error) {
                             if (error) {
                                 qDebug() << "Failed login!\n";
                                 if (!error->matrix_error.error.empty()) {
                                     emit loginError(QString::fromStdString(error->matrix_error.error));
                                     return;
                                 } else if (!error->parse_error.empty()) {
                                     emit loginError(QString::fromStdString(error->parse_error));
                                     return;
                                 } else if (error->error_code) {
                                     emit loginError(QString::fromStdString(error->error_code.message()));
                                     return;
                                 } else if (error->status_code != boost::beast::http::status::ok) {
                                     emit loginError(QString::fromStdString(
                                         "http status" + std::to_string((unsigned)error->status_code)));
                                     return;
                                 } else {
                                     emit loginError(tr("Failed to login"));
                                     return;
                                 }
                             }
                             qDebug() << "Access token:" << QString::fromStdString(response.access_token)
                                      << " , device: " << QString::fromStdString(response.device_id);

                             if (response.well_known) {
                                 qDebug() << "Login response requested to migrate to: "
                                          << QString::fromStdString(response.well_known->homeserver.base_url);
                                 http::client().set_server(response.well_known->homeserver.base_url);
                             }

                             Settings s;
                             s.access_token(response.access_token);
                             s.device_id(response.device_id);
                             s.user(response.user_id);
                             s.server(http::client().server());
                             s.server_port(http::client().port());

                             emit loginSuccess();
                         });
}

void Login::logout() {
    http::client().logout([this](const mtx::responses::Logout &response, mtx::http::RequestErr error) {
        if (error) {
            qWarning() << "Error logging out";
        }

        http::client().clear();

        Settings s;
        s.delete_access_token();
    });
}