From 76438ba95d16c7d007fc16ffc194889f937a19f7 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 19 Oct 2017 19:36:10 +0900 Subject: Introduce device_id and initial_device_name support; switch to generated LoginJob This is _almost_ a backwards-compatible change, except that connect*() and other relevant methods in Connection are no more virtual (that wasn't much useful anyway). Otherwise it's a matter of passing initial_device_name to connectToServer(), saving device_id (along with access_token) from the result of LoginJob and then passing device_id (along with access_token, again) to connectWithToken() upon the next run. --- connection.cpp | 50 ++++++++++++--------------- connection.h | 29 +++++++++------- connectiondata.cpp | 12 +++++++ connectiondata.h | 2 ++ examples/qmc-example.cpp | 2 +- jobs/generated/login.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ jobs/generated/login.h | 38 +++++++++++++++++++++ settings.cpp | 29 +++++++++++----- settings.h | 13 ++++--- 9 files changed, 209 insertions(+), 55 deletions(-) create mode 100644 jobs/generated/login.cpp create mode 100644 jobs/generated/login.h diff --git a/connection.cpp b/connection.cpp index 84a52149..427118c9 100644 --- a/connection.cpp +++ b/connection.cpp @@ -21,8 +21,8 @@ #include "user.h" #include "events/event.h" #include "room.h" +#include "jobs/generated/login.h" #include "jobs/generated/logout.h" -#include "jobs/passwordlogin.h" #include "jobs/sendeventjob.h" #include "jobs/postreceiptjob.h" #include "jobs/joinroomjob.h" @@ -61,8 +61,6 @@ class Connection::Private // Leave state of the same room. QHash, Room*> roomMap; QHash userMap; - QString username; - QString password; QString userId; SyncJob* syncJob; @@ -113,42 +111,33 @@ void Connection::resolveServer(const QString& domain) }); } -void Connection::connectToServer(const QString& user, const QString& password) +void Connection::connectToServer(const QString& user, const QString& password, + const QString& initialDeviceName, + const QString& deviceId) { - auto loginJob = callApi(user, password); - connect( loginJob, &PasswordLogin::success, [=] () { - connectWithToken(loginJob->id(), loginJob->token()); + auto loginJob = callApi(QStringLiteral("m.login.password"), user, + /*medium*/ "", /*address*/ "", password, /*token*/ "", + deviceId, initialDeviceName); + connect( loginJob, &BaseJob::success, [=] () { + connectWithToken(loginJob->user_id(), loginJob->access_token(), + loginJob->device_id()); }); - connect( loginJob, &PasswordLogin::failure, [=] () { + connect( loginJob, &BaseJob::failure, [=] () { emit loginError(loginJob->errorString()); }); - d->username = user; // to be able to reconnect - d->password = password; } -void Connection::connectWithToken(const QString& userId, const QString& token) +void Connection::connectWithToken(const QString& userId, + const QString& accessToken, const QString& deviceId) { d->userId = userId; - d->data->setToken(token); - qCDebug(MAIN) << "Accessing" << d->data->baseUrl() - << "by user" << userId - << "with the following access token:"; - qCDebug(MAIN) << token; + d->data->setToken(accessToken); + d->data->setDeviceId(deviceId); + qCDebug(MAIN) << "Using server" << d->data->baseUrl() << "by user" << userId + << "from device" << deviceId; emit connected(); } -void Connection::reconnect() -{ - auto loginJob = callApi(d->username, d->password); - connect( loginJob, &PasswordLogin::success, [=] () { - d->userId = loginJob->id(); - emit reconnected(); - }); - connect( loginJob, &PasswordLogin::failure, [=] () { - emit loginError(loginJob->errorString()); - }); -} - void Connection::logout() { auto job = callApi(); @@ -301,6 +290,11 @@ QString Connection::userId() const return d->userId; } +const QString& Connection::deviceId() const +{ + return d->data->deviceId(); +} + QString Connection::token() const { return accessToken(); diff --git a/connection.h b/connection.h index b7d049f1..2a107b43 100644 --- a/connection.h +++ b/connection.h @@ -61,19 +61,6 @@ namespace QMatrixClient QHash, Room*> roomMap() const; - Q_INVOKABLE virtual void resolveServer(const QString& domain); - Q_INVOKABLE virtual void connectToServer(const QString& user, - const QString& password); - Q_INVOKABLE virtual void connectWithToken(const QString& userId, - const QString& token); - Q_INVOKABLE virtual void reconnect(); - /** @deprecated Use stopSync() instead */ - Q_INVOKABLE virtual void disconnectFromServer() { stopSync(); } - Q_INVOKABLE virtual void logout(); - - Q_INVOKABLE void sync(int timeout = -1); - Q_INVOKABLE void stopSync(); - // Old API that will be abolished any time soon. DO NOT USE. /** @deprecated Use callApi() or Room::postMessage() instead */ @@ -113,6 +100,7 @@ namespace QMatrixClient Q_INVOKABLE User* user(const QString& userId); Q_INVOKABLE User* user(); Q_INVOKABLE QString userId() const; + Q_INVOKABLE const QString& deviceId() const; /** @deprecated Use accessToken() instead. */ Q_INVOKABLE QString token() const; Q_INVOKABLE QString accessToken() const; @@ -185,6 +173,21 @@ namespace QMatrixClient [](Connection* c, const QString& id) { return new T(id, c); }; } + public slots: + void resolveServer(const QString& domain); + void connectToServer(const QString& user, const QString& password, + const QString& initialDeviceName, + const QString& deviceId = {}); + void connectWithToken(const QString& userId, const QString& accessToken, + const QString& deviceId); + + /** @deprecated Use stopSync() instead */ + void disconnectFromServer() { stopSync(); } + void logout(); + + void sync(int timeout = -1); + void stopSync(); + signals: void resolved(); void connected(); diff --git a/connectiondata.cpp b/connectiondata.cpp index 6f15577e..9b9b6e04 100644 --- a/connectiondata.cpp +++ b/connectiondata.cpp @@ -35,6 +35,7 @@ struct ConnectionData::Private QUrl baseUrl; QString accessToken; QString lastEvent; + QString deviceId; mutable unsigned int txnCounter = 0; const qint64 id = QDateTime::currentMSecsSinceEpoch(); @@ -83,6 +84,17 @@ void ConnectionData::setPort(int port) qCDebug(MAIN) << "updated baseUrl to" << d->baseUrl; } +const QString& ConnectionData::deviceId() const +{ + return d->deviceId; +} + +void ConnectionData::setDeviceId(const QString& deviceId) +{ + d->deviceId = deviceId; + qCDebug(MAIN) << "updated deviceId to" << d->deviceId; +} + QString ConnectionData::lastEvent() const { return d->lastEvent; diff --git a/connectiondata.h b/connectiondata.h index 7b0097d6..52a7461c 100644 --- a/connectiondata.h +++ b/connectiondata.h @@ -32,11 +32,13 @@ namespace QMatrixClient QString accessToken() const; QUrl baseUrl() const; + const QString& deviceId() const; QNetworkAccessManager* nam() const; void setToken( QString accessToken ); void setHost( QString host ); void setPort( int port ); + void setDeviceId(const QString& deviceId); QString lastEvent() const; void setLastEvent( QString identifier ); diff --git a/examples/qmc-example.cpp b/examples/qmc-example.cpp index a6da6aba..dc0c94e4 100644 --- a/examples/qmc-example.cpp +++ b/examples/qmc-example.cpp @@ -35,7 +35,7 @@ int main(int argc, char* argv[]) return -1; auto conn = new Connection(QUrl("https://matrix.org")); - conn->connectToServer(argv[1], argv[2]); + conn->connectToServer(argv[1], argv[2], "QMatrixClient example application"); QObject::connect(conn, &Connection::connected, [=] { cout << "Connected" << endl; conn->sync(); diff --git a/jobs/generated/login.cpp b/jobs/generated/login.cpp new file mode 100644 index 00000000..6e8294e7 --- /dev/null +++ b/jobs/generated/login.cpp @@ -0,0 +1,89 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + + +#include "login.h" + +#include "jobs/converters.h" +#include + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +class LoginJob::Private +{ + public: + QString user_id; + QString access_token; + QString home_server; + QString device_id; + +}; + +LoginJob::LoginJob(QString type, QString user, QString medium, QString address, QString password, QString token, QString device_id, QString initial_device_display_name) + : BaseJob(HttpVerb::Post, "LoginJob", + basePath % "/login", + Query { }, Data { }, false + ), d(new Private) +{ + Data _data; + _data.insert("type", toJson(type)); + if (!user.isEmpty()) + _data.insert("user", toJson(user)); + if (!medium.isEmpty()) + _data.insert("medium", toJson(medium)); + if (!address.isEmpty()) + _data.insert("address", toJson(address)); + if (!password.isEmpty()) + _data.insert("password", toJson(password)); + if (!token.isEmpty()) + _data.insert("token", toJson(token)); + if (!device_id.isEmpty()) + _data.insert("device_id", toJson(device_id)); + if (!initial_device_display_name.isEmpty()) + _data.insert("initial_device_display_name", toJson(initial_device_display_name)); + setRequestData(_data); +} + +LoginJob::~LoginJob() +{ + delete d; +} + +const QString& LoginJob::user_id() const +{ + return d->user_id; +} + +const QString& LoginJob::access_token() const +{ + return d->access_token; +} + +const QString& LoginJob::home_server() const +{ + return d->home_server; +} + +const QString& LoginJob::device_id() const +{ + return d->device_id; +} + +BaseJob::Status LoginJob::parseJson(const QJsonDocument& data) +{ + auto json = data.object(); + + d->user_id = fromJson(json.value("user_id")); + + d->access_token = fromJson(json.value("access_token")); + + d->home_server = fromJson(json.value("home_server")); + + d->device_id = fromJson(json.value("device_id")); + + return Success; +} + diff --git a/jobs/generated/login.h b/jobs/generated/login.h new file mode 100644 index 00000000..dc89206d --- /dev/null +++ b/jobs/generated/login.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + + +#pragma once + +#include "../basejob.h" + +#include + + +namespace QMatrixClient +{ + + // Operations + + class LoginJob : public BaseJob + { + public: + explicit LoginJob(QString type, QString user = {}, QString medium = {}, QString address = {}, QString password = {}, QString token = {}, QString device_id = {}, QString initial_device_display_name = {}); + + ~LoginJob() override; + + const QString& user_id() const; + const QString& access_token() const; + const QString& home_server() const; + const QString& device_id() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + Private* d; + }; + +} // namespace QMatrixClient diff --git a/settings.cpp b/settings.cpp index fbcd845f..3a5f4d26 100644 --- a/settings.cpp +++ b/settings.cpp @@ -5,9 +5,6 @@ using namespace QMatrixClient; -Settings::~Settings() -{ } - void Settings::setValue(const QString& key, const QVariant& value) { // qCDebug() << "Setting" << key << "to" << value; @@ -19,9 +16,6 @@ QVariant Settings::value(const QString& key, const QVariant& defaultValue) const return QSettings::value(key, defaultValue); } -SettingsGroup::~SettingsGroup() -{ } - void SettingsGroup::setValue(const QString& key, const QVariant& value) { Settings::setValue(groupPath + "/" + key, value); @@ -58,9 +52,6 @@ void SettingsGroup::remove(const QString& key) Settings::remove(fullKey); } -AccountSettings::~AccountSettings() -{ } - bool AccountSettings::keepLoggedIn() const { return value("keep_logged_in", false).toBool(); @@ -86,6 +77,26 @@ QString AccountSettings::userId() const return group().section('/', -1); } +QString AccountSettings::deviceId() const +{ + return value("device_id").toString(); +} + +void AccountSettings::setDeviceId(const QString& deviceId) +{ + setValue("device_id", deviceId); +} + +QString AccountSettings::deviceName() const +{ + return value("device_name").toString(); +} + +void AccountSettings::setDeviceName(const QString& deviceName) +{ + setValue("device_name", deviceName); +} + QString AccountSettings::accessToken() const { return value("access_token").toString(); diff --git a/settings.h b/settings.h index eab0679a..a6c0420e 100644 --- a/settings.h +++ b/settings.h @@ -36,7 +36,6 @@ namespace QMatrixClient #else using QSettings::QSettings; #endif - virtual ~Settings(); Q_INVOKABLE void setValue(const QString &key, const QVariant &value); @@ -52,7 +51,6 @@ namespace QMatrixClient : Settings(qsettingsArgs...) , groupPath(path) { } - virtual ~SettingsGroup(); Q_INVOKABLE bool contains(const QString& key) const; Q_INVOKABLE QVariant value(const QString &key, @@ -72,6 +70,8 @@ namespace QMatrixClient { Q_OBJECT Q_PROPERTY(QString userId READ userId) + Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId) + Q_PROPERTY(QString deviceName READ deviceName WRITE setDeviceName) Q_PROPERTY(QUrl homeserver READ homeserver WRITE setHomeserver) Q_PROPERTY(bool keepLoggedIn READ keepLoggedIn WRITE setKeepLoggedIn) Q_PROPERTY(QString accessToken READ accessToken WRITE setAccessToken) @@ -80,10 +80,15 @@ namespace QMatrixClient explicit AccountSettings(const QString& accountId, ArgTs... qsettingsArgs) : SettingsGroup("Accounts/" + accountId, qsettingsArgs...) { } - virtual ~AccountSettings(); QString userId() const; + QString deviceId() const; + void setDeviceId(const QString& deviceId); + + QString deviceName() const; + void setDeviceName(const QString& deviceName); + QUrl homeserver() const; void setHomeserver(const QUrl& url); @@ -94,4 +99,4 @@ namespace QMatrixClient void setAccessToken(const QString& accessToken); Q_INVOKABLE void clearAccessToken(); }; -} +} // namespace QMatrixClient -- cgit v1.2.3