aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2020-03-25 20:35:30 +0100
committerKitsune Ral <Kitsune-Ral@users.sf.net>2020-03-26 22:52:01 +0100
commit7033aa5ad8152f77164a4c644837d1fe44aa0430 (patch)
tree9d3465a3c3e90cee8b0f118efd8246a51aa67ad5
parent16a0a88b3db9e8c3f1c8ff80139b77a31f2da287 (diff)
downloadlibquotient-7033aa5ad8152f77164a4c644837d1fe44aa0430.tar.gz
libquotient-7033aa5ad8152f77164a4c644837d1fe44aa0430.zip
Connection: support getting the list of login flows
Backport of #386.
-rw-r--r--lib/connection.cpp43
-rw-r--r--lib/connection.h38
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();