diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2020-03-25 20:35:30 +0100 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2020-03-26 22:52:01 +0100 |
commit | 7033aa5ad8152f77164a4c644837d1fe44aa0430 (patch) | |
tree | 9d3465a3c3e90cee8b0f118efd8246a51aa67ad5 | |
parent | 16a0a88b3db9e8c3f1c8ff80139b77a31f2da287 (diff) | |
download | libquotient-7033aa5ad8152f77164a4c644837d1fe44aa0430.tar.gz libquotient-7033aa5ad8152f77164a4c644837d1fe44aa0430.zip |
Connection: support getting the list of login flows
Backport of #386.
-rw-r--r-- | lib/connection.cpp | 43 | ||||
-rw-r--r-- | lib/connection.h | 38 |
2 files changed, 70 insertions, 11 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index ddeaa883..99d5c04a 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -80,10 +80,10 @@ class Connection::Private std::unique_ptr<ConnectionData> data; // A complex key below is a pair of room name and whether its // state is Invited. The spec mandates to keep Invited room state - // separately so we should, e.g., keep objects for Invite and - // Leave state of the same room. + // separately; specifically, we should keep objects for Invite and + // Leave state of the same room if the two happen to co-exist. QHash<QPair<QString, bool>, Room*> roomMap; - // Mapping from aliases to room ids, as per the last sync + /// Mapping from aliases to room ids, as of the last sync QHash<QString, QString> roomAliasMap; QVector<QString> roomIdsToForget; QVector<Room*> firstTimeRooms; @@ -102,6 +102,8 @@ class Connection::Private GetCapabilitiesJob* capabilitiesJob = nullptr; GetCapabilitiesJob::Capabilities capabilities; + QVector<GetLoginFlowsJob::LoginFlow> loginFlows; + SyncJob* syncJob = nullptr; bool cacheState = true; @@ -109,7 +111,7 @@ class Connection::Private .value("cache_type").toString() != "json"; bool lazyLoading = false; - void connectWithToken(const QString& user, const QString& accessToken, + void connectWithToken(const QString& userId, const QString& accessToken, const QString& deviceId); template <typename EventT> @@ -859,6 +861,21 @@ QString Connection::domain() const return d->userId.section(':', 1); } +QVector<GetLoginFlowsJob::LoginFlow> Connection::loginFlows() const +{ + return d->loginFlows; +} + +bool Connection::supportsPasswordAuth() const +{ + return d->loginFlows.contains(LoginFlows::Password); +} + +bool Connection::supportsSso() const +{ + return d->loginFlows.contains(LoginFlows::SSO); +} + Room* Connection::room(const QString& roomId, JoinStates states) const { Room* room = d->roomMap.value({roomId, false}, nullptr); @@ -1253,11 +1270,21 @@ QByteArray Connection::generateTxnId() const void Connection::setHomeserver(const QUrl& url) { - if (homeserver() == url) - return; + if (homeserver() != url) { + d->data->setBaseUrl(url); + d->loginFlows.clear(); + emit homeserverChanged(homeserver()); + } - d->data->setBaseUrl(url); - emit homeserverChanged(homeserver()); + // Whenever a homeserver is updated, retrieve available login flows from it + auto* j = callApi<GetLoginFlowsJob>(BackgroundRequest); + connect(j, &BaseJob::finished, this, [this, j] { + if (j->status().good()) + d->loginFlows = j->flows(); + else + d->loginFlows.clear(); + emit loginFlowsChanged(); + }); } void Connection::saveRoomState(Room* r) const diff --git a/lib/connection.h b/lib/connection.h index ea5be51a..ad228bf0 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -18,6 +18,7 @@ #pragma once +#include "csapi/login.h" #include "csapi/create_room.h" #include "joinstate.h" #include "events/accountdataevents.h" @@ -30,6 +31,8 @@ #include <functional> #include <memory> +Q_DECLARE_METATYPE(QMatrixClient::GetLoginFlowsJob::LoginFlow) + namespace QMatrixClient { class Room; @@ -51,6 +54,28 @@ namespace QMatrixClient class SendMessageJob; class LeaveRoomJob; + // To simplify comparisons of LoginFlows + + inline bool operator==(const GetLoginFlowsJob::LoginFlow& lhs, + const GetLoginFlowsJob::LoginFlow& rhs) + { + return lhs.type == rhs.type; + } + + inline bool operator!=(const GetLoginFlowsJob::LoginFlow& lhs, + const GetLoginFlowsJob::LoginFlow& rhs) + { + return !(lhs == rhs); + } + + /// Predefined login flows + namespace LoginFlows { + using LoginFlow = GetLoginFlowsJob::LoginFlow; + static const LoginFlow Password { "m.login.password" }; + static const LoginFlow SSO { "m.login.sso" }; + static const LoginFlow Token { "m.login.token" }; + } + class Connection; using room_factory_t = std::function<Room*(Connection*, const QString&, @@ -95,9 +120,6 @@ namespace QMatrixClient class Connection: public QObject { Q_OBJECT - /** Whether or not the rooms state should be cached locally - * \sa loadState(), saveState() - */ Q_PROPERTY(User* localUser READ user NOTIFY stateChanged) Q_PROPERTY(QString localUserId READ userId NOTIFY stateChanged) Q_PROPERTY(QString deviceId READ deviceId NOTIFY stateChanged) @@ -105,6 +127,9 @@ namespace QMatrixClient Q_PROPERTY(QString defaultRoomVersion READ defaultRoomVersion NOTIFY capabilitiesLoaded) Q_PROPERTY(QUrl homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) Q_PROPERTY(QString domain READ domain NOTIFY homeserverChanged) + Q_PROPERTY(QVector<QMatrixClient::GetLoginFlowsJob::LoginFlow> loginFlows READ loginFlows NOTIFY loginFlowsChanged) + Q_PROPERTY(bool supportsSso READ supportsSso NOTIFY loginFlowsChanged) + Q_PROPERTY(bool supportsPasswordAuth READ supportsPasswordAuth NOTIFY loginFlowsChanged) Q_PROPERTY(bool cacheState READ cacheState WRITE setCacheState NOTIFY cacheStateChanged) Q_PROPERTY(bool lazyLoading READ lazyLoading WRITE setLazyLoading NOTIFY lazyLoadingChanged) @@ -246,6 +271,12 @@ namespace QMatrixClient QUrl homeserver() const; /** Get the domain name used for ids/aliases on the server */ QString domain() const; + /** Get the list of supported login flows */ + QVector<GetLoginFlowsJob::LoginFlow> loginFlows() const; + /** Check whether the current homeserver supports password auth */ + bool supportsPasswordAuth() const; + /** Check whether the current homeserver supports SSO */ + bool supportsSso() const; /** Find a room by its id and a mask of applicable states */ Q_INVOKABLE Room* room(const QString& roomId, JoinStates states = JoinState::Invite|JoinState::Join) const; @@ -550,6 +581,7 @@ namespace QMatrixClient void resolveError(QString error); void homeserverChanged(QUrl baseUrl); + void loginFlowsChanged(); void capabilitiesLoaded(); void connected(); |