diff options
51 files changed, 1243 insertions, 329 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 48c99715..7e3eb600 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ if (GTAD_PATH) get_filename_component(ABS_GTAD_PATH "${GTAD_PATH}" ABSOLUTE) endif () if (MATRIX_DOC_PATH) - get_filename_component(ABS_API_DEF_PATH "${MATRIX_DOC_PATH}/api/client-server" ABSOLUTE) + get_filename_component(ABS_API_DEF_PATH "${MATRIX_DOC_PATH}/api" ABSOLUTE) endif () message( STATUS ) @@ -62,7 +62,7 @@ message( STATUS "Using Qt ${Qt5_VERSION} at ${Qt5_Prefix}" ) if (MATRIX_DOC_PATH AND GTAD_PATH) message( STATUS "Generating API stubs enabled" ) message( STATUS " Using GTAD at ${ABS_GTAD_PATH}" ) - message( STATUS " Using CS API files at ${ABS_API_DEF_PATH}" ) + message( STATUS " Using API files at ${ABS_API_DEF_PATH}" ) endif () message( STATUS "=============================================================================" ) message( STATUS ) @@ -102,21 +102,22 @@ set(libqmatrixclient_SRCS ) set(CSAPI_DIR csapi) -set(ASAPI_DIR application-service) set(FULL_CSAPI_DIR lib/${CSAPI_DIR}) -set(FULL_ASAPI_DIR lib/${ASAPI_DIR}) +set(FULL_CSAPI_SRC_DIR ${ABS_API_DEF_PATH}/client-server) +set(ASAPI_DEF_DIR application-service/definitions) +set(ISAPI_DEF_DIR identity/definitions) if (MATRIX_DOC_PATH AND GTAD_PATH) file(GLOB_RECURSE API_DEFS RELATIVE ${PROJECT_SOURCE_DIR} - ${ABS_API_DEF_PATH}/*.yaml - ${ABS_API_DEF_PATH}/definitions/*.yaml - ${MATRIX_DOC_PATH}/event-schemas/schema/* + ${FULL_CSAPI_SRC_DIR}/*.yaml + ${ABS_API_DEF_PATH}/${ASAPI_DEF_DIR}/*.yaml + ${ABS_API_DEF_PATH}/${ISAPI_DEF_DIR}/*.yaml ) add_custom_target(update-api ${ABS_GTAD_PATH} --config ${CSAPI_DIR}/gtad.yaml --out ${CSAPI_DIR} - ${ABS_API_DEF_PATH} + ${FULL_CSAPI_SRC_DIR} cas_login_redirect.yaml- cas_login_ticket.yaml- old_sync.yaml- room_initial_sync.yaml- # deprecated - sync.yaml- + sync.yaml- # we have a better handcrafted implementation WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/lib SOURCES ${FULL_CSAPI_DIR}/gtad.yaml ${FULL_CSAPI_DIR}/{{base}}.h.mustache @@ -128,13 +129,16 @@ endif() aux_source_directory(${FULL_CSAPI_DIR} libqmatrixclient_job_SRCS) aux_source_directory(${FULL_CSAPI_DIR}/definitions libqmatrixclient_csdef_SRCS) -aux_source_directory(${FULL_ASAPI_DIR}/definitions libqmatrixclient_asdef_SRCS) +aux_source_directory(${FULL_CSAPI_DIR}/definitions/wellknown libqmatrixclient_cswellknown_SRCS) +aux_source_directory(lib/${ASAPI_DEF_DIR} libqmatrixclient_asdef_SRCS) +aux_source_directory(lib/${ISAPI_DEF_DIR} libqmatrixclient_isdef_SRCS) set(example_SRCS examples/qmc-example.cpp) add_library(QMatrixClient ${libqmatrixclient_SRCS} ${libqmatrixclient_job_SRCS} ${libqmatrixclient_csdef_SRCS} - ${libqmatrixclient_asdef_SRCS}) + ${libqmatrixclient_cswellknown_SRCS} + ${libqmatrixclient_asdef_SRCS} ${libqmatrixclient_isdef_SRCS}) set(API_VERSION "0.4") set_property(TARGET QMatrixClient PROPERTY VERSION "${API_VERSION}.0") set_property(TARGET QMatrixClient PROPERTY SOVERSION 0 ) diff --git a/lib/application-service/definitions/location.cpp b/lib/application-service/definitions/location.cpp index 1ccff315..958a55bf 100644 --- a/lib/application-service/definitions/location.cpp +++ b/lib/application-service/definitions/location.cpp @@ -9,9 +9,9 @@ using namespace QMatrixClient; QJsonObject QMatrixClient::toJson(const ThirdPartyLocation& pod) { QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("alias"), pod.alias); - addParam<IfNotEmpty>(jo, QStringLiteral("protocol"), pod.protocol); - addParam<IfNotEmpty>(jo, QStringLiteral("fields"), pod.fields); + addParam<>(jo, QStringLiteral("alias"), pod.alias); + addParam<>(jo, QStringLiteral("protocol"), pod.protocol); + addParam<>(jo, QStringLiteral("fields"), pod.fields); return jo; } diff --git a/lib/application-service/definitions/protocol.cpp b/lib/application-service/definitions/protocol.cpp index 13e58382..04bb7dfc 100644 --- a/lib/application-service/definitions/protocol.cpp +++ b/lib/application-service/definitions/protocol.cpp @@ -9,8 +9,8 @@ using namespace QMatrixClient; QJsonObject QMatrixClient::toJson(const FieldType& pod) { QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("regexp"), pod.regexp); - addParam<IfNotEmpty>(jo, QStringLiteral("placeholder"), pod.placeholder); + addParam<>(jo, QStringLiteral("regexp"), pod.regexp); + addParam<>(jo, QStringLiteral("placeholder"), pod.placeholder); return jo; } @@ -25,18 +25,27 @@ FieldType FromJsonObject<FieldType>::operator()(const QJsonObject& jo) const return result; } -QJsonObject QMatrixClient::toJson(const FieldTypes& pod) +QJsonObject QMatrixClient::toJson(const ProtocolInstance& pod) { QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("fieldname"), pod.fieldname); + addParam<>(jo, QStringLiteral("desc"), pod.desc); + addParam<IfNotEmpty>(jo, QStringLiteral("icon"), pod.icon); + addParam<>(jo, QStringLiteral("fields"), pod.fields); + addParam<>(jo, QStringLiteral("network_id"), pod.networkId); return jo; } -FieldTypes FromJsonObject<FieldTypes>::operator()(const QJsonObject& jo) const +ProtocolInstance FromJsonObject<ProtocolInstance>::operator()(const QJsonObject& jo) const { - FieldTypes result; - result.fieldname = - fromJson<FieldType>(jo.value("fieldname"_ls)); + ProtocolInstance result; + result.desc = + fromJson<QString>(jo.value("desc"_ls)); + result.icon = + fromJson<QString>(jo.value("icon"_ls)); + result.fields = + fromJson<QJsonObject>(jo.value("fields"_ls)); + result.networkId = + fromJson<QString>(jo.value("network_id"_ls)); return result; } @@ -44,11 +53,11 @@ FieldTypes FromJsonObject<FieldTypes>::operator()(const QJsonObject& jo) const QJsonObject QMatrixClient::toJson(const ThirdPartyProtocol& pod) { QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("user_fields"), pod.userFields); - addParam<IfNotEmpty>(jo, QStringLiteral("location_fields"), pod.locationFields); - addParam<IfNotEmpty>(jo, QStringLiteral("icon"), pod.icon); - addParam<IfNotEmpty>(jo, QStringLiteral("field_types"), pod.fieldTypes); - addParam<IfNotEmpty>(jo, QStringLiteral("instances"), pod.instances); + addParam<>(jo, QStringLiteral("user_fields"), pod.userFields); + addParam<>(jo, QStringLiteral("location_fields"), pod.locationFields); + addParam<>(jo, QStringLiteral("icon"), pod.icon); + addParam<>(jo, QStringLiteral("field_types"), pod.fieldTypes); + addParam<>(jo, QStringLiteral("instances"), pod.instances); return jo; } @@ -62,9 +71,9 @@ ThirdPartyProtocol FromJsonObject<ThirdPartyProtocol>::operator()(const QJsonObj result.icon = fromJson<QString>(jo.value("icon"_ls)); result.fieldTypes = - fromJson<FieldTypes>(jo.value("field_types"_ls)); + fromJson<QHash<QString, FieldType>>(jo.value("field_types"_ls)); result.instances = - fromJson<QVector<QJsonObject>>(jo.value("instances"_ls)); + fromJson<QVector<ProtocolInstance>>(jo.value("instances"_ls)); return result; } diff --git a/lib/application-service/definitions/protocol.h b/lib/application-service/definitions/protocol.h index 4aa400ab..2aca7d66 100644 --- a/lib/application-service/definitions/protocol.h +++ b/lib/application-service/definitions/protocol.h @@ -6,9 +6,10 @@ #include "converters.h" +#include <QtCore/QHash> #include <QtCore/QJsonObject> -#include <QtCore/QVector> #include "converters.h" +#include <QtCore/QVector> namespace QMatrixClient { @@ -17,7 +18,9 @@ namespace QMatrixClient /// Definition of valid values for a field. struct FieldType { - /// A regular expression for validation of a field's value. + /// A regular expression for validation of a field's value. This may be relatively + /// coarse to verify the value as the application service providing this protocol + /// may apply additional validation or filtering. QString regexp; /// An placeholder serving as a valid example of the field value. QString placeholder; @@ -30,34 +33,50 @@ namespace QMatrixClient FieldType operator()(const QJsonObject& jo) const; }; - /// All location or user fields should have an entry here. - struct FieldTypes + struct ProtocolInstance { - /// Definition of valid values for a field. - Omittable<FieldType> fieldname; + /// A human-readable description for the protocol, such as the name. + QString desc; + /// An optional content URI representing the protocol. Overrides the one provided + /// at the higher level Protocol object. + QString icon; + /// Preset values for ``fields`` the client may use to search by. + QJsonObject fields; + /// A unique identifier across all instances. + QString networkId; }; - QJsonObject toJson(const FieldTypes& pod); + QJsonObject toJson(const ProtocolInstance& pod); - template <> struct FromJsonObject<FieldTypes> + template <> struct FromJsonObject<ProtocolInstance> { - FieldTypes operator()(const QJsonObject& jo) const; + ProtocolInstance operator()(const QJsonObject& jo) const; }; struct ThirdPartyProtocol { - /// Fields used to identify a third party user. + /// Fields which may be used to identify a third party user. These should be + /// ordered to suggest the way that entities may be grouped, where higher + /// groupings are ordered first. For example, the name of a network should be + /// searched before the nickname of a user. QStringList userFields; - /// Fields used to identify a third party location. + /// Fields which may be used to identify a third party location. These should be + /// ordered to suggest the way that entities may be grouped, where higher + /// groupings are ordered first. For example, the name of a network should be + /// searched before the name of a channel. QStringList locationFields; - /// An icon representing the third party protocol. + /// A content URI representing an icon for the third party protocol. QString icon; - /// All location or user fields should have an entry here. - Omittable<FieldTypes> fieldTypes; + /// The type definitions for the fields defined in the ``user_fields`` and + /// ``location_fields``. Each entry in those arrays MUST have an entry here. The + /// ``string`` key for this object is field name itself. + /// + /// May be an empty object if no fields are defined. + QHash<QString, FieldType> fieldTypes; /// A list of objects representing independent instances of configuration. - /// For instance multiple networks on IRC if multiple are bridged by the - /// same bridge. - QVector<QJsonObject> instances; + /// For example, multiple networks on IRC if multiple are provided by the + /// same application service. + QVector<ProtocolInstance> instances; }; QJsonObject toJson(const ThirdPartyProtocol& pod); diff --git a/lib/application-service/definitions/user.cpp b/lib/application-service/definitions/user.cpp index dbe4c104..ca334236 100644 --- a/lib/application-service/definitions/user.cpp +++ b/lib/application-service/definitions/user.cpp @@ -9,9 +9,9 @@ using namespace QMatrixClient; QJsonObject QMatrixClient::toJson(const ThirdPartyUser& pod) { QJsonObject jo; - addParam<IfNotEmpty>(jo, QStringLiteral("userid"), pod.userid); - addParam<IfNotEmpty>(jo, QStringLiteral("protocol"), pod.protocol); - addParam<IfNotEmpty>(jo, QStringLiteral("fields"), pod.fields); + addParam<>(jo, QStringLiteral("userid"), pod.userid); + addParam<>(jo, QStringLiteral("protocol"), pod.protocol); + addParam<>(jo, QStringLiteral("fields"), pod.fields); return jo; } diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index 520e6f58..f62002a6 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -25,6 +25,10 @@ namespace QMatrixClient fromJson<QString>(jo.value("medium"_ls)); result.address = fromJson<QString>(jo.value("address"_ls)); + result.validatedAt = + fromJson<qint64>(jo.value("validated_at"_ls)); + result.addedAt = + fromJson<qint64>(jo.value("added_at"_ls)); return result; } @@ -92,31 +96,86 @@ Post3PIDsJob::Post3PIDsJob(const ThreePidCredentials& threePidCreds, bool bind) setRequestData(_data); } -QUrl RequestTokenTo3PIDEmailJob::makeRequestUrl(QUrl baseUrl) +static const auto Delete3pidFromAccountJobName = QStringLiteral("Delete3pidFromAccountJob"); + +Delete3pidFromAccountJob::Delete3pidFromAccountJob(const QString& medium, const QString& address) + : BaseJob(HttpVerb::Post, Delete3pidFromAccountJobName, + basePath % "/account/3pid/delete") { - return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/account/3pid/email/requestToken"); + QJsonObject _data; + addParam<>(_data, QStringLiteral("medium"), medium); + addParam<>(_data, QStringLiteral("address"), address); + setRequestData(_data); } +class RequestTokenTo3PIDEmailJob::Private +{ + public: + Sid data; +}; + static const auto RequestTokenTo3PIDEmailJobName = QStringLiteral("RequestTokenTo3PIDEmailJob"); -RequestTokenTo3PIDEmailJob::RequestTokenTo3PIDEmailJob() +RequestTokenTo3PIDEmailJob::RequestTokenTo3PIDEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer, const QString& nextLink) : BaseJob(HttpVerb::Post, RequestTokenTo3PIDEmailJobName, basePath % "/account/3pid/email/requestToken", false) + , d(new Private) +{ + QJsonObject _data; + addParam<>(_data, QStringLiteral("client_secret"), clientSecret); + addParam<>(_data, QStringLiteral("email"), email); + addParam<>(_data, QStringLiteral("send_attempt"), sendAttempt); + addParam<IfNotEmpty>(_data, QStringLiteral("next_link"), nextLink); + addParam<>(_data, QStringLiteral("id_server"), idServer); + setRequestData(_data); +} + +RequestTokenTo3PIDEmailJob::~RequestTokenTo3PIDEmailJob() = default; + +const Sid& RequestTokenTo3PIDEmailJob::data() const { + return d->data; } -QUrl RequestTokenTo3PIDMSISDNJob::makeRequestUrl(QUrl baseUrl) +BaseJob::Status RequestTokenTo3PIDEmailJob::parseJson(const QJsonDocument& data) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/account/3pid/msisdn/requestToken"); + d->data = fromJson<Sid>(data); + return Success; } +class RequestTokenTo3PIDMSISDNJob::Private +{ + public: + Sid data; +}; + static const auto RequestTokenTo3PIDMSISDNJobName = QStringLiteral("RequestTokenTo3PIDMSISDNJob"); -RequestTokenTo3PIDMSISDNJob::RequestTokenTo3PIDMSISDNJob() +RequestTokenTo3PIDMSISDNJob::RequestTokenTo3PIDMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, int sendAttempt, const QString& idServer, const QString& nextLink) : BaseJob(HttpVerb::Post, RequestTokenTo3PIDMSISDNJobName, basePath % "/account/3pid/msisdn/requestToken", false) + , d(new Private) +{ + QJsonObject _data; + addParam<>(_data, QStringLiteral("client_secret"), clientSecret); + addParam<>(_data, QStringLiteral("country"), country); + addParam<>(_data, QStringLiteral("phone_number"), phoneNumber); + addParam<>(_data, QStringLiteral("send_attempt"), sendAttempt); + addParam<IfNotEmpty>(_data, QStringLiteral("next_link"), nextLink); + addParam<>(_data, QStringLiteral("id_server"), idServer); + setRequestData(_data); +} + +RequestTokenTo3PIDMSISDNJob::~RequestTokenTo3PIDMSISDNJob() = default; + +const Sid& RequestTokenTo3PIDMSISDNJob::data() const { + return d->data; +} + +BaseJob::Status RequestTokenTo3PIDMSISDNJob::parseJson(const QJsonDocument& data) +{ + d->data = fromJson<Sid>(data); + return Success; } diff --git a/lib/csapi/administrative_contact.h b/lib/csapi/administrative_contact.h index 53123e7a..3fb3d44c 100644 --- a/lib/csapi/administrative_contact.h +++ b/lib/csapi/administrative_contact.h @@ -6,6 +6,7 @@ #include "jobs/basejob.h" +#include "csapi/../identity/definitions/sid.h" #include "converters.h" #include <QtCore/QVector> @@ -19,7 +20,7 @@ namespace QMatrixClient /// associated with the user's account. /// /// This is *not* the same as the list of third party identifiers bound to - /// the user's Matrix ID in Identity Servers. + /// the user's Matrix ID in identity servers. /// /// Identifiers in this list may be used by the homeserver as, for example, /// identifiers that it will accept to reset the user's account password. @@ -32,7 +33,7 @@ namespace QMatrixClient /// associated with the user's account. /// /// This is *not* the same as the list of third party identifiers bound to - /// the user's Matrix ID in Identity Servers. + /// the user's Matrix ID in identity servers. /// /// Identifiers in this list may be used by the homeserver as, for example, /// identifiers that it will accept to reset the user's account password. @@ -42,6 +43,11 @@ namespace QMatrixClient QString medium; /// The third party identifier address. QString address; + /// The timestamp, in milliseconds, when the identifier was + /// validated by the identity server. + qint64 validatedAt; + /// The timestamp, in milliseconds, when the homeserver associated the third party identifier with the user. + qint64 addedAt; }; // Construction/destruction @@ -64,7 +70,7 @@ namespace QMatrixClient /// associated with the user's account. /// /// This is *not* the same as the list of third party identifiers bound to - /// the user's Matrix ID in Identity Servers. + /// the user's Matrix ID in identity servers. /// /// Identifiers in this list may be used by the homeserver as, for example, /// identifiers that it will accept to reset the user's account password. @@ -89,11 +95,11 @@ namespace QMatrixClient /// The third party credentials to associate with the account. struct ThreePidCredentials { - /// The client secret used in the session with the Identity Server. + /// The client secret used in the session with the identity server. QString clientSecret; - /// The Identity Server to use. + /// The identity server to use. QString idServer; - /// The session identifier given by the Identity Server. + /// The session identifier given by the identity server. QString sid; }; @@ -110,49 +116,122 @@ namespace QMatrixClient explicit Post3PIDsJob(const ThreePidCredentials& threePidCreds, bool bind = false); }; - /// Requests a validation token be sent to the given email address for the purpose of adding an email address to an account + /// Deletes a third party identifier from the user's account /// - /// Proxies the identity server API ``validate/email/requestToken``, but + /// Removes a third party identifier from the user's account. This might not + /// cause an unbind of the identifier from the identity server. + class Delete3pidFromAccountJob : public BaseJob + { + public: + /*! Deletes a third party identifier from the user's account + * \param medium + * The medium of the third party identifier being removed. + * \param address + * The third party address being removed. + */ + explicit Delete3pidFromAccountJob(const QString& medium, const QString& address); + }; + + /// Begins the validation process for an email address for association with the user's account. + /// + /// Proxies the Identity Service API ``validate/email/requestToken``, but /// first checks that the given email address is **not** already associated - /// with an account on this Home Server. This API should be used to request + /// with an account on this homeserver. This API should be used to request /// validation tokens when adding an email address to an account. This API's - /// parameters and response is identical to that of the HS API - /// |/register/email/requestToken|_ endpoint. + /// parameters and response are identical to that of the |/register/email/requestToken|_ + /// endpoint. class RequestTokenTo3PIDEmailJob : public BaseJob { public: - explicit RequestTokenTo3PIDEmailJob(); - - /*! Construct a URL without creating a full-fledged job object - * - * This function can be used when a URL for - * RequestTokenTo3PIDEmailJob is necessary but the job - * itself isn't. + /*! Begins the validation process for an email address for association with the user's account. + * \param clientSecret + * A unique string generated by the client, and used to identify the + * validation attempt. It must be a string consisting of the characters + * ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + * must not be empty. + * \param email + * The email address to validate. + * \param sendAttempt + * The server will only send an email if the ``send_attempt`` + * is a number greater than the most recent one which it has seen, + * scoped to that ``email`` + ``client_secret`` pair. This is to + * avoid repeatedly sending the same email in the case of request + * retries between the POSTing user and the identity server. + * The client should increment this value if they desire a new + * email (e.g. a reminder) to be sent. + * \param idServer + * The hostname of the identity server to communicate with. May + * optionally include a port. + * \param nextLink + * Optional. When the validation is completed, the identity + * server will redirect the user to this URL. */ - static QUrl makeRequestUrl(QUrl baseUrl); + explicit RequestTokenTo3PIDEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer, const QString& nextLink = {}); + ~RequestTokenTo3PIDEmailJob() override; + + // Result properties + + /// An email was sent to the given address. + const Sid& data() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + private: + class Private; + QScopedPointer<Private> d; }; - /// Requests a validation token be sent to the given email address for the purpose of adding a phone number to an account. + /// Begins the validation process for a phone number for association with the user's account. /// - /// Proxies the identity server API ``validate/msisdn/requestToken``, but + /// Proxies the Identity Service API ``validate/msisdn/requestToken``, but /// first checks that the given phone number is **not** already associated - /// with an account on this Home Server. This API should be used to request + /// with an account on this homeserver. This API should be used to request /// validation tokens when adding a phone number to an account. This API's - /// parameters and response is identical to that of the HS API - /// |/register/msisdn/requestToken|_ endpoint. + /// parameters and response are identical to that of the |/register/msisdn/requestToken|_ + /// endpoint. class RequestTokenTo3PIDMSISDNJob : public BaseJob { public: - explicit RequestTokenTo3PIDMSISDNJob(); - - /*! Construct a URL without creating a full-fledged job object - * - * This function can be used when a URL for - * RequestTokenTo3PIDMSISDNJob is necessary but the job - * itself isn't. + /*! Begins the validation process for a phone number for association with the user's account. + * \param clientSecret + * A unique string generated by the client, and used to identify the + * validation attempt. It must be a string consisting of the characters + * ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + * must not be empty. + * \param country + * The two-letter uppercase ISO country code that the number in + * ``phone_number`` should be parsed as if it were dialled from. + * \param phoneNumber + * The phone number to validate. + * \param sendAttempt + * The server will only send an SMS if the ``send_attempt`` is a + * number greater than the most recent one which it has seen, + * scoped to that ``country`` + ``phone_number`` + ``client_secret`` + * triple. This is to avoid repeatedly sending the same SMS in + * the case of request retries between the POSTing user and the + * identity server. The client should increment this value if + * they desire a new SMS (e.g. a reminder) to be sent. + * \param idServer + * The hostname of the identity server to communicate with. May + * optionally include a port. + * \param nextLink + * Optional. When the validation is completed, the identity + * server will redirect the user to this URL. */ - static QUrl makeRequestUrl(QUrl baseUrl); + explicit RequestTokenTo3PIDMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, int sendAttempt, const QString& idServer, const QString& nextLink = {}); + ~RequestTokenTo3PIDMSISDNJob() override; + // Result properties + + /// An SMS message was sent to the given phone number. + const Sid& data() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; }; } // namespace QMatrixClient diff --git a/lib/csapi/appservice_room_directory.cpp b/lib/csapi/appservice_room_directory.cpp new file mode 100644 index 00000000..f40e2f05 --- /dev/null +++ b/lib/csapi/appservice_room_directory.cpp @@ -0,0 +1,25 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "appservice_room_directory.h" + +#include "converters.h" + +#include <QtCore/QStringBuilder> + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +static const auto UpdateAppserviceRoomDirectoryVsibilityJobName = QStringLiteral("UpdateAppserviceRoomDirectoryVsibilityJob"); + +UpdateAppserviceRoomDirectoryVsibilityJob::UpdateAppserviceRoomDirectoryVsibilityJob(const QString& networkId, const QString& roomId, const QString& visibility) + : BaseJob(HttpVerb::Put, UpdateAppserviceRoomDirectoryVsibilityJobName, + basePath % "/directory/list/appservice/" % networkId % "/" % roomId) +{ + QJsonObject _data; + addParam<>(_data, QStringLiteral("visibility"), visibility); + setRequestData(_data); +} + diff --git a/lib/csapi/appservice_room_directory.h b/lib/csapi/appservice_room_directory.h new file mode 100644 index 00000000..f35198b3 --- /dev/null +++ b/lib/csapi/appservice_room_directory.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + + +namespace QMatrixClient +{ + // Operations + + /// Updates a room's visibility in the application service's room directory. + /// + /// Updates the visibility of a given room on the application service's room + /// directory. + /// + /// This API is similar to the room directory visibility API used by clients + /// to update the homeserver's more general room directory. + /// + /// This API requires the use of an application service access token (``as_token``) + /// instead of a typical client's access_token. This API cannot be invoked by + /// users who are not identified as application services. + class UpdateAppserviceRoomDirectoryVsibilityJob : public BaseJob + { + public: + /*! Updates a room's visibility in the application service's room directory. + * \param networkId + * The protocol (network) ID to update the room list for. This would + * have been provided by the application service as being listed as + * a supported protocol. + * \param roomId + * The room ID to add to the directory. + * \param visibility + * Whether the room should be visible (public) in the directory + * or not (private). + */ + explicit UpdateAppserviceRoomDirectoryVsibilityJob(const QString& networkId, const QString& roomId, const QString& visibility); + }; +} // namespace QMatrixClient diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index 231f2a61..9b590e42 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -284,7 +284,7 @@ BaseJob::Status GetUrlPreviewJob::parseJson(const QJsonDocument& data) class GetConfigJob::Private { public: - Omittable<double> uploadSize; + Omittable<qint64> uploadSize; }; QUrl GetConfigJob::makeRequestUrl(QUrl baseUrl) @@ -304,7 +304,7 @@ GetConfigJob::GetConfigJob() GetConfigJob::~GetConfigJob() = default; -Omittable<double> GetConfigJob::uploadSize() const +Omittable<qint64> GetConfigJob::uploadSize() const { return d->uploadSize; } @@ -312,7 +312,7 @@ Omittable<double> GetConfigJob::uploadSize() const BaseJob::Status GetConfigJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->uploadSize = fromJson<double>(json.value("m.upload.size"_ls)); + d->uploadSize = fromJson<qint64>(json.value("m.upload.size"_ls)); return Success; } diff --git a/lib/csapi/content-repo.h b/lib/csapi/content-repo.h index 951bc4f7..5ef2e0d6 100644 --- a/lib/csapi/content-repo.h +++ b/lib/csapi/content-repo.h @@ -248,7 +248,7 @@ namespace QMatrixClient /// The maximum size an upload can be in bytes. /// Clients SHOULD use this as a guide when uploading content. /// If not listed or null, the size limit should be treated as unknown. - Omittable<double> uploadSize() const; + Omittable<qint64> uploadSize() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/create_room.h b/lib/csapi/create_room.h index 4a3e50aa..a0a64df0 100644 --- a/lib/csapi/create_room.h +++ b/lib/csapi/create_room.h @@ -43,13 +43,13 @@ namespace QMatrixClient /// ======================== ============== ====================== ================ ========= /// Preset ``join_rules`` ``history_visibility`` ``guest_access`` Other /// ======================== ============== ====================== ================ ========= - /// ``private_chat`` ``invite`` ``shared`` ``can_join`` + /// ``private_chat`` ``invite`` ``shared`` ``can_join`` /// ``trusted_private_chat`` ``invite`` ``shared`` ``can_join`` All invitees are given the same power level as the room creator. - /// ``public_chat`` ``public`` ``shared`` ``forbidden`` + /// ``public_chat`` ``public`` ``shared`` ``forbidden`` /// ======================== ============== ====================== ================ ========= /// /// The server will create a ``m.room.create`` event in the room with the - /// requesting user as the creator, alongside other keys provided in the + /// requesting user as the creator, alongside other keys provided in the /// ``creation_content``. class CreateRoomJob : public BaseJob { @@ -83,13 +83,13 @@ namespace QMatrixClient /// ======================== ============== ====================== ================ ========= /// Preset ``join_rules`` ``history_visibility`` ``guest_access`` Other /// ======================== ============== ====================== ================ ========= - /// ``private_chat`` ``invite`` ``shared`` ``can_join`` + /// ``private_chat`` ``invite`` ``shared`` ``can_join`` /// ``trusted_private_chat`` ``invite`` ``shared`` ``can_join`` All invitees are given the same power level as the room creator. - /// ``public_chat`` ``public`` ``shared`` ``forbidden`` + /// ``public_chat`` ``public`` ``shared`` ``forbidden`` /// ======================== ============== ====================== ================ ========= /// /// The server will create a ``m.room.create`` event in the room with the - /// requesting user as the creator, alongside other keys provided in the + /// requesting user as the creator, alongside other keys provided in the /// ``creation_content``. struct Invite3pid { @@ -128,13 +128,13 @@ namespace QMatrixClient /// ======================== ============== ====================== ================ ========= /// Preset ``join_rules`` ``history_visibility`` ``guest_access`` Other /// ======================== ============== ====================== ================ ========= - /// ``private_chat`` ``invite`` ``shared`` ``can_join`` + /// ``private_chat`` ``invite`` ``shared`` ``can_join`` /// ``trusted_private_chat`` ``invite`` ``shared`` ``can_join`` All invitees are given the same power level as the room creator. - /// ``public_chat`` ``public`` ``shared`` ``forbidden`` + /// ``public_chat`` ``public`` ``shared`` ``forbidden`` /// ======================== ============== ====================== ================ ========= /// /// The server will create a ``m.room.create`` event in the room with the - /// requesting user as the creator, alongside other keys provided in the + /// requesting user as the creator, alongside other keys provided in the /// ``creation_content``. struct StateEvent { @@ -204,7 +204,7 @@ namespace QMatrixClient * * If unspecified, the server should use the ``visibility`` to determine * which preset to use. A visbility of ``public`` equates to a preset of - * ``public_chat`` and ``private`` visibility equates to a preset of + * ``public_chat`` and ``private`` visibility equates to a preset of * ``private_chat``. * \param isDirect * This flag makes the server set the ``is_direct`` flag on the diff --git a/lib/csapi/definitions/event_filter.cpp b/lib/csapi/definitions/event_filter.cpp index 2f0bc899..cc444db0 100644 --- a/lib/csapi/definitions/event_filter.cpp +++ b/lib/csapi/definitions/event_filter.cpp @@ -6,7 +6,7 @@ using namespace QMatrixClient; -QJsonObject QMatrixClient::toJson(const Filter& pod) +QJsonObject QMatrixClient::toJson(const EventFilter& pod) { QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("limit"), pod.limit); @@ -17,9 +17,9 @@ QJsonObject QMatrixClient::toJson(const Filter& pod) return jo; } -Filter FromJsonObject<Filter>::operator()(const QJsonObject& jo) const +EventFilter FromJsonObject<EventFilter>::operator()(const QJsonObject& jo) const { - Filter result; + EventFilter result; result.limit = fromJson<int>(jo.value("limit"_ls)); result.notSenders = diff --git a/lib/csapi/definitions/event_filter.h b/lib/csapi/definitions/event_filter.h index 2c64181b..5c6a5b27 100644 --- a/lib/csapi/definitions/event_filter.h +++ b/lib/csapi/definitions/event_filter.h @@ -12,7 +12,7 @@ namespace QMatrixClient { // Data structures - struct Filter + struct EventFilter { /// The maximum number of events to return. Omittable<int> limit; @@ -26,11 +26,11 @@ namespace QMatrixClient QStringList types; }; - QJsonObject toJson(const Filter& pod); + QJsonObject toJson(const EventFilter& pod); - template <> struct FromJsonObject<Filter> + template <> struct FromJsonObject<EventFilter> { - Filter operator()(const QJsonObject& jo) const; + EventFilter operator()(const QJsonObject& jo) const; }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/public_rooms_response.cpp b/lib/csapi/definitions/public_rooms_response.cpp index 60ae3749..2f52501d 100644 --- a/lib/csapi/definitions/public_rooms_response.cpp +++ b/lib/csapi/definitions/public_rooms_response.cpp @@ -31,7 +31,7 @@ PublicRoomsChunk FromJsonObject<PublicRoomsChunk>::operator()(const QJsonObject& result.name = fromJson<QString>(jo.value("name"_ls)); result.numJoinedMembers = - fromJson<qint64>(jo.value("num_joined_members"_ls)); + fromJson<int>(jo.value("num_joined_members"_ls)); result.roomId = fromJson<QString>(jo.value("room_id"_ls)); result.topic = @@ -66,7 +66,7 @@ PublicRoomsResponse FromJsonObject<PublicRoomsResponse>::operator()(const QJsonO result.prevBatch = fromJson<QString>(jo.value("prev_batch"_ls)); result.totalRoomCountEstimate = - fromJson<qint64>(jo.value("total_room_count_estimate"_ls)); + fromJson<int>(jo.value("total_room_count_estimate"_ls)); return result; } diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index e7fe5ad8..88c805ba 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -22,7 +22,7 @@ namespace QMatrixClient /// The name of the room, if any. QString name; /// The number of members joined to the room. - qint64 numJoinedMembers; + int numJoinedMembers; /// The ID of the room. QString roomId; /// The topic of the room, if any. @@ -59,7 +59,7 @@ namespace QMatrixClient QString prevBatch; /// An estimate on the total number of public rooms, if the /// server has an estimate. - Omittable<qint64> totalRoomCountEstimate; + Omittable<int> totalRoomCountEstimate; }; QJsonObject toJson(const PublicRoomsResponse& pod); diff --git a/lib/csapi/definitions/room_event_filter.h b/lib/csapi/definitions/room_event_filter.h index 1e8d644e..697fe661 100644 --- a/lib/csapi/definitions/room_event_filter.h +++ b/lib/csapi/definitions/room_event_filter.h @@ -13,13 +13,13 @@ namespace QMatrixClient { // Data structures - struct RoomEventFilter : Filter + struct RoomEventFilter : EventFilter { /// A list of room IDs to exclude. If this list is absent then no rooms are excluded. A matching room will be excluded even if it is listed in the ``'rooms'`` filter. QStringList notRooms; /// A list of room IDs to include. If this list is absent then all rooms are included. QStringList rooms; - /// If ``true``, includes only events with a url key in their content. If ``false``, excludes those events. + /// If ``true``, includes only events with a ``url`` key in their content. If ``false``, excludes those events. Defaults to ``false``. bool containsUrl; }; diff --git a/lib/csapi/definitions/sync_filter.cpp b/lib/csapi/definitions/sync_filter.cpp index 984e99ae..bd87804c 100644 --- a/lib/csapi/definitions/sync_filter.cpp +++ b/lib/csapi/definitions/sync_filter.cpp @@ -40,7 +40,7 @@ RoomFilter FromJsonObject<RoomFilter>::operator()(const QJsonObject& jo) const return result; } -QJsonObject QMatrixClient::toJson(const SyncFilter& pod) +QJsonObject QMatrixClient::toJson(const Filter& pod) { QJsonObject jo; addParam<IfNotEmpty>(jo, QStringLiteral("event_fields"), pod.eventFields); @@ -51,17 +51,17 @@ QJsonObject QMatrixClient::toJson(const SyncFilter& pod) return jo; } -SyncFilter FromJsonObject<SyncFilter>::operator()(const QJsonObject& jo) const +Filter FromJsonObject<Filter>::operator()(const QJsonObject& jo) const { - SyncFilter result; + Filter result; result.eventFields = fromJson<QStringList>(jo.value("event_fields"_ls)); result.eventFormat = fromJson<QString>(jo.value("event_format"_ls)); result.presence = - fromJson<Filter>(jo.value("presence"_ls)); + fromJson<EventFilter>(jo.value("presence"_ls)); result.accountData = - fromJson<Filter>(jo.value("account_data"_ls)); + fromJson<EventFilter>(jo.value("account_data"_ls)); result.room = fromJson<RoomFilter>(jo.value("room"_ls)); diff --git a/lib/csapi/definitions/sync_filter.h b/lib/csapi/definitions/sync_filter.h index 47b5fcdb..ca275a9a 100644 --- a/lib/csapi/definitions/sync_filter.h +++ b/lib/csapi/definitions/sync_filter.h @@ -40,25 +40,25 @@ namespace QMatrixClient RoomFilter operator()(const QJsonObject& jo) const; }; - struct SyncFilter + struct Filter { /// List of event fields to include. If this list is absent then all fields are included. The entries may include '.' charaters to indicate sub-fields. So ['content.body'] will include the 'body' field of the 'content' object. A literal '.' character in a field name may be escaped using a '\\'. A server may include more fields than were requested. QStringList eventFields; /// The format to use for events. 'client' will return the events in a format suitable for clients. 'federation' will return the raw event as receieved over federation. The default is 'client'. QString eventFormat; /// The presence updates to include. - Omittable<Filter> presence; + Omittable<EventFilter> presence; /// The user account data that isn't associated with rooms to include. - Omittable<Filter> accountData; + Omittable<EventFilter> accountData; /// Filters to be applied to room data. Omittable<RoomFilter> room; }; - QJsonObject toJson(const SyncFilter& pod); + QJsonObject toJson(const Filter& pod); - template <> struct FromJsonObject<SyncFilter> + template <> struct FromJsonObject<Filter> { - SyncFilter operator()(const QJsonObject& jo) const; + Filter operator()(const QJsonObject& jo) const; }; } // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/homeserver.cpp b/lib/csapi/definitions/wellknown/homeserver.cpp new file mode 100644 index 00000000..f1482ee4 --- /dev/null +++ b/lib/csapi/definitions/wellknown/homeserver.cpp @@ -0,0 +1,24 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "homeserver.h" + +using namespace QMatrixClient; + +QJsonObject QMatrixClient::toJson(const HomeserverInformation& pod) +{ + QJsonObject jo; + addParam<>(jo, QStringLiteral("base_url"), pod.baseUrl); + return jo; +} + +HomeserverInformation FromJsonObject<HomeserverInformation>::operator()(const QJsonObject& jo) const +{ + HomeserverInformation result; + result.baseUrl = + fromJson<QString>(jo.value("base_url"_ls)); + + return result; +} + diff --git a/lib/csapi/definitions/wellknown/homeserver.h b/lib/csapi/definitions/wellknown/homeserver.h new file mode 100644 index 00000000..09d6ba63 --- /dev/null +++ b/lib/csapi/definitions/wellknown/homeserver.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "converters.h" + + +namespace QMatrixClient +{ + // Data structures + + /// Used by clients to discover homeserver information. + struct HomeserverInformation + { + /// The base URL for the homeserver for client-server connections. + QString baseUrl; + }; + + QJsonObject toJson(const HomeserverInformation& pod); + + template <> struct FromJsonObject<HomeserverInformation> + { + HomeserverInformation operator()(const QJsonObject& jo) const; + }; + +} // namespace QMatrixClient diff --git a/lib/csapi/definitions/wellknown/identity_server.cpp b/lib/csapi/definitions/wellknown/identity_server.cpp new file mode 100644 index 00000000..f9d7bc37 --- /dev/null +++ b/lib/csapi/definitions/wellknown/identity_server.cpp @@ -0,0 +1,24 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "identity_server.h" + +using namespace QMatrixClient; + +QJsonObject QMatrixClient::toJson(const IdentityServerInformation& pod) +{ + QJsonObject jo; + addParam<>(jo, QStringLiteral("base_url"), pod.baseUrl); + return jo; +} + +IdentityServerInformation FromJsonObject<IdentityServerInformation>::operator()(const QJsonObject& jo) const +{ + IdentityServerInformation result; + result.baseUrl = + fromJson<QString>(jo.value("base_url"_ls)); + + return result; +} + diff --git a/lib/csapi/definitions/wellknown/identity_server.h b/lib/csapi/definitions/wellknown/identity_server.h new file mode 100644 index 00000000..cb8ffcee --- /dev/null +++ b/lib/csapi/definitions/wellknown/identity_server.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "converters.h" + + +namespace QMatrixClient +{ + // Data structures + + /// Used by clients to discover identity server information. + struct IdentityServerInformation + { + /// The base URL for the identity server for client-server connections. + QString baseUrl; + }; + + QJsonObject toJson(const IdentityServerInformation& pod); + + template <> struct FromJsonObject<IdentityServerInformation> + { + IdentityServerInformation operator()(const QJsonObject& jo) const; + }; + +} // namespace QMatrixClient diff --git a/lib/csapi/directory.cpp b/lib/csapi/directory.cpp index fd3b8839..5353f3bc 100644 --- a/lib/csapi/directory.cpp +++ b/lib/csapi/directory.cpp @@ -19,7 +19,7 @@ SetRoomAliasJob::SetRoomAliasJob(const QString& roomAlias, const QString& roomId basePath % "/room/" % roomAlias) { QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("room_id"), roomId); + addParam<>(_data, QStringLiteral("room_id"), roomId); setRequestData(_data); } diff --git a/lib/csapi/directory.h b/lib/csapi/directory.h index afac4277..39e86635 100644 --- a/lib/csapi/directory.h +++ b/lib/csapi/directory.h @@ -21,7 +21,7 @@ namespace QMatrixClient * \param roomId * The room ID to set. */ - explicit SetRoomAliasJob(const QString& roomAlias, const QString& roomId = {}); + explicit SetRoomAliasJob(const QString& roomAlias, const QString& roomId); }; /// Get the room ID corresponding to this room alias. diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index 51056cc3..77dc9b92 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -20,7 +20,7 @@ class DefineFilterJob::Private static const auto DefineFilterJobName = QStringLiteral("DefineFilterJob"); -DefineFilterJob::DefineFilterJob(const QString& userId, const SyncFilter& filter) +DefineFilterJob::DefineFilterJob(const QString& userId, const Filter& filter) : BaseJob(HttpVerb::Post, DefineFilterJobName, basePath % "/user/" % userId % "/filter") , d(new Private) @@ -38,6 +38,9 @@ const QString& DefineFilterJob::filterId() const BaseJob::Status DefineFilterJob::parseJson(const QJsonDocument& data) { auto json = data.object(); + if (!json.contains("filter_id"_ls)) + return { JsonParseError, + "The key 'filter_id' not found in the response" }; d->filterId = fromJson<QString>(json.value("filter_id"_ls)); return Success; } @@ -45,7 +48,7 @@ BaseJob::Status DefineFilterJob::parseJson(const QJsonDocument& data) class GetFilterJob::Private { public: - SyncFilter data; + Filter data; }; QUrl GetFilterJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& filterId) @@ -65,18 +68,14 @@ GetFilterJob::GetFilterJob(const QString& userId, const QString& filterId) GetFilterJob::~GetFilterJob() = default; -const SyncFilter& GetFilterJob::data() const +const Filter& GetFilterJob::data() const { return d->data; } BaseJob::Status GetFilterJob::parseJson(const QJsonDocument& data) { - auto json = data.object(); - if (!json.contains("data"_ls)) - return { JsonParseError, - "The key 'data' not found in the response" }; - d->data = fromJson<SyncFilter>(json.value("data"_ls)); + d->data = fromJson<Filter>(data); return Success; } diff --git a/lib/csapi/filter.h b/lib/csapi/filter.h index 6854cba4..0ca7e953 100644 --- a/lib/csapi/filter.h +++ b/lib/csapi/filter.h @@ -29,12 +29,15 @@ namespace QMatrixClient * Returns a filter ID that may be used in future requests to * restrict which events are returned to the client. */ - explicit DefineFilterJob(const QString& userId, const SyncFilter& filter); + explicit DefineFilterJob(const QString& userId, const Filter& filter); ~DefineFilterJob() override; // Result properties - /// The ID of the filter that was created. + /// The ID of the filter that was created. Cannot start + /// with a ``{`` as this character is used to determine + /// if the filter provided is inline JSON or a previously + /// declared filter by homeservers on some APIs. const QString& filterId() const; protected: @@ -70,7 +73,7 @@ namespace QMatrixClient // Result properties /// "The filter defintion" - const SyncFilter& data() const; + const Filter& data() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/list_public_rooms.cpp b/lib/csapi/list_public_rooms.cpp index 4466dc5b..2fdb2005 100644 --- a/lib/csapi/list_public_rooms.cpp +++ b/lib/csapi/list_public_rooms.cpp @@ -114,43 +114,12 @@ namespace QMatrixClient addParam<IfNotEmpty>(jo, QStringLiteral("generic_search_term"), pod.genericSearchTerm); return jo; } - - template <> struct FromJsonObject<QueryPublicRoomsJob::PublicRoomsChunk> - { - QueryPublicRoomsJob::PublicRoomsChunk operator()(const QJsonObject& jo) const - { - QueryPublicRoomsJob::PublicRoomsChunk result; - result.aliases = - fromJson<QStringList>(jo.value("aliases"_ls)); - result.canonicalAlias = - fromJson<QString>(jo.value("canonical_alias"_ls)); - result.name = - fromJson<QString>(jo.value("name"_ls)); - result.numJoinedMembers = - fromJson<qint64>(jo.value("num_joined_members"_ls)); - result.roomId = - fromJson<QString>(jo.value("room_id"_ls)); - result.topic = - fromJson<QString>(jo.value("topic"_ls)); - result.worldReadable = - fromJson<bool>(jo.value("world_readable"_ls)); - result.guestCanJoin = - fromJson<bool>(jo.value("guest_can_join"_ls)); - result.avatarUrl = - fromJson<QString>(jo.value("avatar_url"_ls)); - - return result; - } - }; } // namespace QMatrixClient class QueryPublicRoomsJob::Private { public: - QVector<PublicRoomsChunk> chunk; - QString nextBatch; - QString prevBatch; - Omittable<qint64> totalRoomCountEstimate; + PublicRoomsResponse data; }; BaseJob::Query queryToQueryPublicRooms(const QString& server) @@ -162,7 +131,7 @@ BaseJob::Query queryToQueryPublicRooms(const QString& server) static const auto QueryPublicRoomsJobName = QStringLiteral("QueryPublicRoomsJob"); -QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable<int> limit, const QString& since, const Omittable<Filter>& filter) +QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable<int> limit, const QString& since, const Omittable<Filter>& filter, bool includeAllNetworks, const QString& thirdPartyInstanceId) : BaseJob(HttpVerb::Post, QueryPublicRoomsJobName, basePath % "/publicRooms", queryToQueryPublicRooms(server)) @@ -172,41 +141,21 @@ QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable<int> l addParam<IfNotEmpty>(_data, QStringLiteral("limit"), limit); addParam<IfNotEmpty>(_data, QStringLiteral("since"), since); addParam<IfNotEmpty>(_data, QStringLiteral("filter"), filter); + addParam<IfNotEmpty>(_data, QStringLiteral("include_all_networks"), includeAllNetworks); + addParam<IfNotEmpty>(_data, QStringLiteral("third_party_instance_id"), thirdPartyInstanceId); setRequestData(_data); } QueryPublicRoomsJob::~QueryPublicRoomsJob() = default; -const QVector<QueryPublicRoomsJob::PublicRoomsChunk>& QueryPublicRoomsJob::chunk() const -{ - return d->chunk; -} - -const QString& QueryPublicRoomsJob::nextBatch() const +const PublicRoomsResponse& QueryPublicRoomsJob::data() const { - return d->nextBatch; -} - -const QString& QueryPublicRoomsJob::prevBatch() const -{ - return d->prevBatch; -} - -Omittable<qint64> QueryPublicRoomsJob::totalRoomCountEstimate() const -{ - return d->totalRoomCountEstimate; + return d->data; } BaseJob::Status QueryPublicRoomsJob::parseJson(const QJsonDocument& data) { - auto json = data.object(); - if (!json.contains("chunk"_ls)) - return { JsonParseError, - "The key 'chunk' not found in the response" }; - d->chunk = fromJson<QVector<PublicRoomsChunk>>(json.value("chunk"_ls)); - d->nextBatch = fromJson<QString>(json.value("next_batch"_ls)); - d->prevBatch = fromJson<QString>(json.value("prev_batch"_ls)); - d->totalRoomCountEstimate = fromJson<qint64>(json.value("total_room_count_estimate"_ls)); + d->data = fromJson<PublicRoomsResponse>(data); return Success; } diff --git a/lib/csapi/list_public_rooms.h b/lib/csapi/list_public_rooms.h index 4c5e872d..8401c134 100644 --- a/lib/csapi/list_public_rooms.h +++ b/lib/csapi/list_public_rooms.h @@ -6,7 +6,6 @@ #include "jobs/basejob.h" -#include <QtCore/QVector> #include "csapi/definitions/public_rooms_response.h" #include "converters.h" @@ -135,34 +134,6 @@ namespace QMatrixClient QString genericSearchTerm; }; - /// Lists the public rooms on the server, with optional filter. - /// - /// This API returns paginated responses. The rooms are ordered by the number - /// of joined members, with the largest rooms first. - struct PublicRoomsChunk - { - /// Aliases of the room. May be empty. - QStringList aliases; - /// The canonical alias of the room, if any. - QString canonicalAlias; - /// The name of the room, if any. - QString name; - /// The number of members joined to the room. - qint64 numJoinedMembers; - /// The ID of the room. - QString roomId; - /// The topic of the room, if any. - QString topic; - /// Whether the room may be viewed by guest users without joining. - bool worldReadable; - /// Whether guest users may join the room and participate in it. - /// If they can, they will be subject to ordinary power level - /// rules like any other user. - bool guestCanJoin; - /// The URL for the room's avatar, if one is set. - QString avatarUrl; - }; - // Construction/destruction /*! Lists the public rooms on the server with optional filter. @@ -178,25 +149,20 @@ namespace QMatrixClient * rather than via an explicit flag. * \param filter * Filter to apply to the results. + * \param includeAllNetworks + * Whether or not to include all known networks/protocols from + * application services on the homeserver. Defaults to false. + * \param thirdPartyInstanceId + * The specific third party network/protocol to request from the + * homeserver. Can only be used if ``include_all_networks`` is false. */ - explicit QueryPublicRoomsJob(const QString& server = {}, Omittable<int> limit = none, const QString& since = {}, const Omittable<Filter>& filter = none); + explicit QueryPublicRoomsJob(const QString& server = {}, Omittable<int> limit = none, const QString& since = {}, const Omittable<Filter>& filter = none, bool includeAllNetworks = false, const QString& thirdPartyInstanceId = {}); ~QueryPublicRoomsJob() override; // Result properties - /// A paginated chunk of public rooms. - const QVector<PublicRoomsChunk>& chunk() const; - /// A pagination token for the response. The absence of this token - /// means there are no more results to fetch and the client should - /// stop paginating. - const QString& nextBatch() const; - /// A pagination token that allows fetching previous results. The - /// absence of this token means there are no results before this - /// batch, i.e. this is the first batch. - const QString& prevBatch() const; - /// An estimate on the total number of public rooms, if the - /// server has an estimate. - Omittable<qint64> totalRoomCountEstimate() const; + /// A list of the rooms on the server. + const PublicRoomsResponse& data() const; protected: Status parseJson(const QJsonDocument& data) override; diff --git a/lib/csapi/notifications.cpp b/lib/csapi/notifications.cpp index 78cd6f49..785a0a8a 100644 --- a/lib/csapi/notifications.cpp +++ b/lib/csapi/notifications.cpp @@ -32,7 +32,7 @@ namespace QMatrixClient result.roomId = fromJson<QString>(jo.value("room_id"_ls)); result.ts = - fromJson<qint64>(jo.value("ts"_ls)); + fromJson<int>(jo.value("ts"_ls)); return result; } diff --git a/lib/csapi/notifications.h b/lib/csapi/notifications.h index 7d1630be..898b5154 100644 --- a/lib/csapi/notifications.h +++ b/lib/csapi/notifications.h @@ -43,7 +43,7 @@ namespace QMatrixClient QString roomId; /// The unix timestamp at which the event notification was sent, /// in milliseconds. - qint64 ts; + int ts; }; // Construction/destruction diff --git a/lib/csapi/pushrules.h b/lib/csapi/pushrules.h index 53560b3c..c038401c 100644 --- a/lib/csapi/pushrules.h +++ b/lib/csapi/pushrules.h @@ -120,6 +120,8 @@ namespace QMatrixClient /// This endpoint allows the creation, modification and deletion of pushers /// for this user ID. The behaviour of this endpoint varies depending on the /// values in the JSON body. + /// + /// When creating push rules, they MUST be enabled by default. class SetPushRuleJob : public BaseJob { public: diff --git a/lib/csapi/read_markers.cpp b/lib/csapi/read_markers.cpp new file mode 100644 index 00000000..1bc67ba0 --- /dev/null +++ b/lib/csapi/read_markers.cpp @@ -0,0 +1,26 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "read_markers.h" + +#include "converters.h" + +#include <QtCore/QStringBuilder> + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/_matrix/client/r0"); + +static const auto SetReadMarkerJobName = QStringLiteral("SetReadMarkerJob"); + +SetReadMarkerJob::SetReadMarkerJob(const QString& roomId, const QString& mFullyRead, const QString& mRead) + : BaseJob(HttpVerb::Post, SetReadMarkerJobName, + basePath % "/rooms/" % roomId % "/read_markers") +{ + QJsonObject _data; + addParam<>(_data, QStringLiteral("m.fully_read"), mFullyRead); + addParam<IfNotEmpty>(_data, QStringLiteral("m.read"), mRead); + setRequestData(_data); +} + diff --git a/lib/csapi/read_markers.h b/lib/csapi/read_markers.h new file mode 100644 index 00000000..f19f46b0 --- /dev/null +++ b/lib/csapi/read_markers.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + + +namespace QMatrixClient +{ + // Operations + + /// Set the position of the read marker for a room. + /// + /// Sets the position of the read marker for a given room, and optionally + /// the read receipt's location. + class SetReadMarkerJob : public BaseJob + { + public: + /*! Set the position of the read marker for a room. + * \param roomId + * The room ID to set the read marker in for the user. + * \param mFullyRead + * The event ID the read marker should be located at. The + * event MUST belong to the room. + * \param mRead + * The event ID to set the read receipt location at. This is + * equivalent to calling ``/receipt/m.read/$elsewhere:domain.com`` + * and is provided here to save that extra call. + */ + explicit SetReadMarkerJob(const QString& roomId, const QString& mFullyRead, const QString& mRead = {}); + }; +} // namespace QMatrixClient diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index bdfa4606..320ec796 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -30,7 +30,7 @@ BaseJob::Query queryToRegister(const QString& kind) static const auto RegisterJobName = QStringLiteral("RegisterJob"); -RegisterJob::RegisterJob(const QString& kind, const Omittable<AuthenticationData>& auth, bool bindEmail, const QString& username, const QString& password, const QString& deviceId, const QString& initialDeviceDisplayName) +RegisterJob::RegisterJob(const QString& kind, const Omittable<AuthenticationData>& auth, bool bindEmail, const QString& username, const QString& password, const QString& deviceId, const QString& initialDeviceDisplayName, bool inhibitLogin) : BaseJob(HttpVerb::Post, RegisterJobName, basePath % "/register", queryToRegister(kind), @@ -44,6 +44,7 @@ RegisterJob::RegisterJob(const QString& kind, const Omittable<AuthenticationData addParam<IfNotEmpty>(_data, QStringLiteral("password"), password); addParam<IfNotEmpty>(_data, QStringLiteral("device_id"), deviceId); addParam<IfNotEmpty>(_data, QStringLiteral("initial_device_display_name"), initialDeviceDisplayName); + addParam<IfNotEmpty>(_data, QStringLiteral("inhibit_login"), inhibitLogin); setRequestData(_data); } @@ -72,6 +73,9 @@ const QString& RegisterJob::deviceId() const BaseJob::Status RegisterJob::parseJson(const QJsonDocument& data) { auto json = data.object(); + if (!json.contains("user_id"_ls)) + return { JsonParseError, + "The key 'user_id' not found in the response" }; d->userId = fromJson<QString>(json.value("user_id"_ls)); d->accessToken = fromJson<QString>(json.value("access_token"_ls)); d->homeServer = fromJson<QString>(json.value("home_server"_ls)); @@ -79,35 +83,77 @@ BaseJob::Status RegisterJob::parseJson(const QJsonDocument& data) return Success; } +class RequestTokenToRegisterEmailJob::Private +{ + public: + Sid data; +}; + static const auto RequestTokenToRegisterEmailJobName = QStringLiteral("RequestTokenToRegisterEmailJob"); -RequestTokenToRegisterEmailJob::RequestTokenToRegisterEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer) +RequestTokenToRegisterEmailJob::RequestTokenToRegisterEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer, const QString& nextLink) : BaseJob(HttpVerb::Post, RequestTokenToRegisterEmailJobName, basePath % "/register/email/requestToken", false) + , d(new Private) { QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("id_server"), idServer); addParam<>(_data, QStringLiteral("client_secret"), clientSecret); addParam<>(_data, QStringLiteral("email"), email); addParam<>(_data, QStringLiteral("send_attempt"), sendAttempt); + addParam<IfNotEmpty>(_data, QStringLiteral("next_link"), nextLink); + addParam<>(_data, QStringLiteral("id_server"), idServer); setRequestData(_data); } +RequestTokenToRegisterEmailJob::~RequestTokenToRegisterEmailJob() = default; + +const Sid& RequestTokenToRegisterEmailJob::data() const +{ + return d->data; +} + +BaseJob::Status RequestTokenToRegisterEmailJob::parseJson(const QJsonDocument& data) +{ + d->data = fromJson<Sid>(data); + return Success; +} + +class RequestTokenToRegisterMSISDNJob::Private +{ + public: + Sid data; +}; + static const auto RequestTokenToRegisterMSISDNJobName = QStringLiteral("RequestTokenToRegisterMSISDNJob"); -RequestTokenToRegisterMSISDNJob::RequestTokenToRegisterMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, double sendAttempt, const QString& idServer) +RequestTokenToRegisterMSISDNJob::RequestTokenToRegisterMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, int sendAttempt, const QString& idServer, const QString& nextLink) : BaseJob(HttpVerb::Post, RequestTokenToRegisterMSISDNJobName, basePath % "/register/msisdn/requestToken", false) + , d(new Private) { QJsonObject _data; - addParam<IfNotEmpty>(_data, QStringLiteral("id_server"), idServer); addParam<>(_data, QStringLiteral("client_secret"), clientSecret); addParam<>(_data, QStringLiteral("country"), country); addParam<>(_data, QStringLiteral("phone_number"), phoneNumber); addParam<>(_data, QStringLiteral("send_attempt"), sendAttempt); + addParam<IfNotEmpty>(_data, QStringLiteral("next_link"), nextLink); + addParam<>(_data, QStringLiteral("id_server"), idServer); setRequestData(_data); } +RequestTokenToRegisterMSISDNJob::~RequestTokenToRegisterMSISDNJob() = default; + +const Sid& RequestTokenToRegisterMSISDNJob::data() const +{ + return d->data; +} + +BaseJob::Status RequestTokenToRegisterMSISDNJob::parseJson(const QJsonDocument& data) +{ + d->data = fromJson<Sid>(data); + return Success; +} + static const auto ChangePasswordJobName = QStringLiteral("ChangePasswordJob"); ChangePasswordJob::ChangePasswordJob(const QString& newPassword, const Omittable<AuthenticationData>& auth) @@ -120,32 +166,75 @@ ChangePasswordJob::ChangePasswordJob(const QString& newPassword, const Omittable setRequestData(_data); } -QUrl RequestTokenToResetPasswordEmailJob::makeRequestUrl(QUrl baseUrl) +class RequestTokenToResetPasswordEmailJob::Private { - return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/account/password/email/requestToken"); -} + public: + Sid data; +}; static const auto RequestTokenToResetPasswordEmailJobName = QStringLiteral("RequestTokenToResetPasswordEmailJob"); -RequestTokenToResetPasswordEmailJob::RequestTokenToResetPasswordEmailJob() +RequestTokenToResetPasswordEmailJob::RequestTokenToResetPasswordEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer, const QString& nextLink) : BaseJob(HttpVerb::Post, RequestTokenToResetPasswordEmailJobName, basePath % "/account/password/email/requestToken", false) + , d(new Private) { + QJsonObject _data; + addParam<>(_data, QStringLiteral("client_secret"), clientSecret); + addParam<>(_data, QStringLiteral("email"), email); + addParam<>(_data, QStringLiteral("send_attempt"), sendAttempt); + addParam<IfNotEmpty>(_data, QStringLiteral("next_link"), nextLink); + addParam<>(_data, QStringLiteral("id_server"), idServer); + setRequestData(_data); } -QUrl RequestTokenToResetPasswordMSISDNJob::makeRequestUrl(QUrl baseUrl) +RequestTokenToResetPasswordEmailJob::~RequestTokenToResetPasswordEmailJob() = default; + +const Sid& RequestTokenToResetPasswordEmailJob::data() const { - return BaseJob::makeRequestUrl(std::move(baseUrl), - basePath % "/account/password/msisdn/requestToken"); + return d->data; } +BaseJob::Status RequestTokenToResetPasswordEmailJob::parseJson(const QJsonDocument& data) +{ + d->data = fromJson<Sid>(data); + return Success; +} + +class RequestTokenToResetPasswordMSISDNJob::Private +{ + public: + Sid data; +}; + static const auto RequestTokenToResetPasswordMSISDNJobName = QStringLiteral("RequestTokenToResetPasswordMSISDNJob"); -RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob() +RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, int sendAttempt, const QString& idServer, const QString& nextLink) : BaseJob(HttpVerb::Post, RequestTokenToResetPasswordMSISDNJobName, basePath % "/account/password/msisdn/requestToken", false) + , d(new Private) { + QJsonObject _data; + addParam<>(_data, QStringLiteral("client_secret"), clientSecret); + addParam<>(_data, QStringLiteral("country"), country); + addParam<>(_data, QStringLiteral("phone_number"), phoneNumber); + addParam<>(_data, QStringLiteral("send_attempt"), sendAttempt); + addParam<IfNotEmpty>(_data, QStringLiteral("next_link"), nextLink); + addParam<>(_data, QStringLiteral("id_server"), idServer); + setRequestData(_data); +} + +RequestTokenToResetPasswordMSISDNJob::~RequestTokenToResetPasswordMSISDNJob() = default; + +const Sid& RequestTokenToResetPasswordMSISDNJob::data() const +{ + return d->data; +} + +BaseJob::Status RequestTokenToResetPasswordMSISDNJob::parseJson(const QJsonDocument& data) +{ + d->data = fromJson<Sid>(data); + return Success; } static const auto DeactivateAccountJobName = QStringLiteral("DeactivateAccountJob"); diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h index 53af8acc..9002b5c8 100644 --- a/lib/csapi/registration.h +++ b/lib/csapi/registration.h @@ -6,6 +6,7 @@ #include "jobs/basejob.h" +#include "csapi/../identity/definitions/sid.h" #include "converters.h" #include "csapi/definitions/auth_data.h" @@ -61,7 +62,7 @@ namespace QMatrixClient * response with status code 401. * \param bindEmail * If true, the server binds the email used for authentication to - * the Matrix ID with the ID Server. + * the Matrix ID with the identity server. * \param username * The basis for the localpart of the desired Matrix ID. If omitted, * the homeserver MUST generate a Matrix ID local part. @@ -74,19 +75,24 @@ namespace QMatrixClient * \param initialDeviceDisplayName * A display name to assign to the newly-created device. Ignored * if ``device_id`` corresponds to a known device. + * \param inhibitLogin + * If true, an ``access_token`` and ``device_id`` should not be + * returned from this call, therefore preventing an automatic + * login. Defaults to false. */ - explicit RegisterJob(const QString& kind = QStringLiteral("user"), const Omittable<AuthenticationData>& auth = none, bool bindEmail = false, const QString& username = {}, const QString& password = {}, const QString& deviceId = {}, const QString& initialDeviceDisplayName = {}); + explicit RegisterJob(const QString& kind = QStringLiteral("user"), const Omittable<AuthenticationData>& auth = none, bool bindEmail = false, const QString& username = {}, const QString& password = {}, const QString& deviceId = {}, const QString& initialDeviceDisplayName = {}, bool inhibitLogin = false); ~RegisterJob() override; // Result properties /// The fully-qualified Matrix user ID (MXID) that has been registered. - /// + /// /// Any user ID returned by this API must conform to the grammar given in the /// `Matrix specification <https://matrix.org/docs/spec/appendices.html#user-identifiers>`_. const QString& userId() const; /// An access token for the account. /// This access token can then be used to authorize other requests. + /// Required if the ``inhibit_login`` option is false. const QString& accessToken() const; /// The server_name of the homeserver on which the account has /// been registered. @@ -97,6 +103,7 @@ namespace QMatrixClient const QString& homeServer() const; /// ID of the registered device. Will be the same as the /// corresponding parameter in the request, if one was specified. + /// Required if the ``inhibit_login`` option is false. const QString& deviceId() const; protected: @@ -107,51 +114,107 @@ namespace QMatrixClient QScopedPointer<Private> d; }; - /// Requests a validation token be sent to the given email address for the purpose of registering an account + /// Begins the validation process for an email to be used during registration. /// - /// Proxies the identity server API ``validate/email/requestToken``, but + /// Proxies the Identity Service API ``validate/email/requestToken``, but /// first checks that the given email address is not already associated - /// with an account on this Home Server. See the Identity Server API for + /// with an account on this homeserver. See the Identity Service API for /// further information. class RequestTokenToRegisterEmailJob : public BaseJob { public: - /*! Requests a validation token be sent to the given email address for the purpose of registering an account + /*! Begins the validation process for an email to be used during registration. * \param clientSecret - * Client-generated secret string used to protect this session + * A unique string generated by the client, and used to identify the + * validation attempt. It must be a string consisting of the characters + * ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + * must not be empty. * \param email - * The email address + * The email address to validate. * \param sendAttempt - * Used to distinguish protocol level retries from requests to re-send the email. + * The server will only send an email if the ``send_attempt`` + * is a number greater than the most recent one which it has seen, + * scoped to that ``email`` + ``client_secret`` pair. This is to + * avoid repeatedly sending the same email in the case of request + * retries between the POSTing user and the identity server. + * The client should increment this value if they desire a new + * email (e.g. a reminder) to be sent. * \param idServer - * The ID server to send the onward request to as a hostname with an appended colon and port number if the port is not the default. + * The hostname of the identity server to communicate with. May + * optionally include a port. + * \param nextLink + * Optional. When the validation is completed, the identity + * server will redirect the user to this URL. */ - explicit RequestTokenToRegisterEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer = {}); + explicit RequestTokenToRegisterEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer, const QString& nextLink = {}); + ~RequestTokenToRegisterEmailJob() override; + + // Result properties + + /// An email has been sent to the specified address. + /// Note that this may be an email containing the validation token or it may be informing + /// the user of an error. + const Sid& data() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; }; /// Requests a validation token be sent to the given phone number for the purpose of registering an account /// - /// Proxies the identity server API ``validate/msisdn/requestToken``, but + /// Proxies the Identity Service API ``validate/msisdn/requestToken``, but /// first checks that the given phone number is not already associated - /// with an account on this Home Server. See the Identity Server API for + /// with an account on this homeserver. See the Identity Service API for /// further information. class RequestTokenToRegisterMSISDNJob : public BaseJob { public: /*! Requests a validation token be sent to the given phone number for the purpose of registering an account * \param clientSecret - * Client-generated secret string used to protect this session. + * A unique string generated by the client, and used to identify the + * validation attempt. It must be a string consisting of the characters + * ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + * must not be empty. * \param country * The two-letter uppercase ISO country code that the number in * ``phone_number`` should be parsed as if it were dialled from. * \param phoneNumber - * The phone number. + * The phone number to validate. * \param sendAttempt - * Used to distinguish protocol level retries from requests to re-send the SMS message. + * The server will only send an SMS if the ``send_attempt`` is a + * number greater than the most recent one which it has seen, + * scoped to that ``country`` + ``phone_number`` + ``client_secret`` + * triple. This is to avoid repeatedly sending the same SMS in + * the case of request retries between the POSTing user and the + * identity server. The client should increment this value if + * they desire a new SMS (e.g. a reminder) to be sent. * \param idServer - * The ID server to send the onward request to as a hostname with an appended colon and port number if the port is not the default. + * The hostname of the identity server to communicate with. May + * optionally include a port. + * \param nextLink + * Optional. When the validation is completed, the identity + * server will redirect the user to this URL. */ - explicit RequestTokenToRegisterMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, double sendAttempt, const QString& idServer = {}); + explicit RequestTokenToRegisterMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, int sendAttempt, const QString& idServer, const QString& nextLink = {}); + ~RequestTokenToRegisterMSISDNJob() override; + + // Result properties + + /// An SMS message has been sent to the specified phone number. + /// Note that this may be an SMS message containing the validation token or it may be informing + /// the user of an error. + const Sid& data() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; }; /// Changes a user's password. @@ -179,9 +242,9 @@ namespace QMatrixClient /// Requests a validation token be sent to the given email address for the purpose of resetting a user's password /// - /// Proxies the identity server API ``validate/email/requestToken``, but + /// Proxies the Identity Service API ``validate/email/requestToken``, but /// first checks that the given email address **is** associated with an account - /// on this Home Server. This API should be used to request + /// on this homeserver. This API should be used to request /// validation tokens when authenticating for the /// `account/password` endpoint. This API's parameters and response are /// identical to that of the HS API |/register/email/requestToken|_ except that @@ -196,28 +259,55 @@ namespace QMatrixClient class RequestTokenToResetPasswordEmailJob : public BaseJob { public: - explicit RequestTokenToResetPasswordEmailJob(); - - /*! Construct a URL without creating a full-fledged job object - * - * This function can be used when a URL for - * RequestTokenToResetPasswordEmailJob is necessary but the job - * itself isn't. + /*! Requests a validation token be sent to the given email address for the purpose of resetting a user's password + * \param clientSecret + * A unique string generated by the client, and used to identify the + * validation attempt. It must be a string consisting of the characters + * ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + * must not be empty. + * \param email + * The email address to validate. + * \param sendAttempt + * The server will only send an email if the ``send_attempt`` + * is a number greater than the most recent one which it has seen, + * scoped to that ``email`` + ``client_secret`` pair. This is to + * avoid repeatedly sending the same email in the case of request + * retries between the POSTing user and the identity server. + * The client should increment this value if they desire a new + * email (e.g. a reminder) to be sent. + * \param idServer + * The hostname of the identity server to communicate with. May + * optionally include a port. + * \param nextLink + * Optional. When the validation is completed, the identity + * server will redirect the user to this URL. */ - static QUrl makeRequestUrl(QUrl baseUrl); + explicit RequestTokenToResetPasswordEmailJob(const QString& clientSecret, const QString& email, int sendAttempt, const QString& idServer, const QString& nextLink = {}); + ~RequestTokenToResetPasswordEmailJob() override; + // Result properties + + /// An email was sent to the given address. + const Sid& data() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; }; /// Requests a validation token be sent to the given phone number for the purpose of resetting a user's password. /// - /// Proxies the identity server API ``validate/msisdn/requestToken``, but + /// Proxies the Identity Service API ``validate/msisdn/requestToken``, but /// first checks that the given phone number **is** associated with an account - /// on this Home Server. This API should be used to request + /// on this homeserver. This API should be used to request /// validation tokens when authenticating for the /// `account/password` endpoint. This API's parameters and response are /// identical to that of the HS API |/register/msisdn/requestToken|_ except that /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the - /// given email address could be found. The server may instead send an + /// given phone number could be found. The server may instead send an /// SMS message to the given address prompting the user to create an account. /// `M_THREEPID_IN_USE` may not be returned. /// @@ -227,16 +317,46 @@ namespace QMatrixClient class RequestTokenToResetPasswordMSISDNJob : public BaseJob { public: - explicit RequestTokenToResetPasswordMSISDNJob(); - - /*! Construct a URL without creating a full-fledged job object - * - * This function can be used when a URL for - * RequestTokenToResetPasswordMSISDNJob is necessary but the job - * itself isn't. + /*! Requests a validation token be sent to the given phone number for the purpose of resetting a user's password. + * \param clientSecret + * A unique string generated by the client, and used to identify the + * validation attempt. It must be a string consisting of the characters + * ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + * must not be empty. + * \param country + * The two-letter uppercase ISO country code that the number in + * ``phone_number`` should be parsed as if it were dialled from. + * \param phoneNumber + * The phone number to validate. + * \param sendAttempt + * The server will only send an SMS if the ``send_attempt`` is a + * number greater than the most recent one which it has seen, + * scoped to that ``country`` + ``phone_number`` + ``client_secret`` + * triple. This is to avoid repeatedly sending the same SMS in + * the case of request retries between the POSTing user and the + * identity server. The client should increment this value if + * they desire a new SMS (e.g. a reminder) to be sent. + * \param idServer + * The hostname of the identity server to communicate with. May + * optionally include a port. + * \param nextLink + * Optional. When the validation is completed, the identity + * server will redirect the user to this URL. */ - static QUrl makeRequestUrl(QUrl baseUrl); + explicit RequestTokenToResetPasswordMSISDNJob(const QString& clientSecret, const QString& country, const QString& phoneNumber, int sendAttempt, const QString& idServer, const QString& nextLink = {}); + ~RequestTokenToResetPasswordMSISDNJob() override; + + // Result properties + /// An SMS message was sent to the given phone number. + const Sid& data() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; }; /// Deactivate a user's account. diff --git a/lib/csapi/search.cpp b/lib/csapi/search.cpp index ad54b39f..9436eb47 100644 --- a/lib/csapi/search.cpp +++ b/lib/csapi/search.cpp @@ -131,7 +131,7 @@ namespace QMatrixClient { SearchJob::ResultRoomEvents result; result.count = - fromJson<qint64>(jo.value("count"_ls)); + fromJson<int>(jo.value("count"_ls)); result.highlights = fromJson<QStringList>(jo.value("highlights"_ls)); result.results = diff --git a/lib/csapi/search.h b/lib/csapi/search.h index 18411975..85b0886b 100644 --- a/lib/csapi/search.h +++ b/lib/csapi/search.h @@ -6,12 +6,12 @@ #include "jobs/basejob.h" -#include <QtCore/QJsonObject> +#include "csapi/definitions/room_event_filter.h" #include "converters.h" #include <QtCore/QVector> +#include "events/eventloader.h" #include <unordered_map> #include <QtCore/QHash> -#include "events/eventloader.h" namespace QMatrixClient { @@ -65,7 +65,7 @@ namespace QMatrixClient /// The keys to search. Defaults to all. QStringList keys; /// This takes a `filter`_. - QJsonObject filter; + Omittable<RoomEventFilter> filter; /// The order in which to search for results. /// By default, this is ``"rank"``. QString orderBy; @@ -146,7 +146,7 @@ namespace QMatrixClient struct ResultRoomEvents { /// An approximate count of the total number of results found. - Omittable<qint64> count; + Omittable<int> count; /// List of words which should be highlighted, useful for stemming which may change the query terms. QStringList highlights; /// List of results in the requested order. @@ -161,7 +161,7 @@ namespace QMatrixClient /// Any groups that were requested. /// /// The outer ``string`` key is the group key requested (eg: ``room_id`` - /// or ``sender``). The inner ``string`` key is the grouped value (eg: + /// or ``sender``). The inner ``string`` key is the grouped value (eg: /// a room's ID or a user's ID). QHash<QString, QHash<QString, GroupValue>> groups; /// Token that can be used to get the next batch of @@ -185,7 +185,7 @@ namespace QMatrixClient * Describes which categories to search in and their criteria. * \param nextBatch * The point to return events from. If given, this should be a - * `next_batch` result from a previous call to this endpoint. + * ``next_batch`` result from a previous call to this endpoint. */ explicit SearchJob(const Categories& searchCategories, const QString& nextBatch = {}); ~SearchJob() override; diff --git a/lib/csapi/tags.cpp b/lib/csapi/tags.cpp index 1afc3bfc..808915ac 100644 --- a/lib/csapi/tags.cpp +++ b/lib/csapi/tags.cpp @@ -12,10 +12,28 @@ using namespace QMatrixClient; static const auto basePath = QStringLiteral("/_matrix/client/r0"); +namespace QMatrixClient +{ + // Converters + + template <> struct FromJsonObject<GetRoomTagsJob::Tag> + { + GetRoomTagsJob::Tag operator()(QJsonObject jo) const + { + GetRoomTagsJob::Tag result; + result.order = + fromJson<float>(jo.take("order"_ls)); + + result.additionalProperties = fromJson<QVariantHash>(jo); + return result; + } + }; +} // namespace QMatrixClient + class GetRoomTagsJob::Private { public: - QJsonObject tags; + QHash<QString, Tag> tags; }; QUrl GetRoomTagsJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId) @@ -35,7 +53,7 @@ GetRoomTagsJob::GetRoomTagsJob(const QString& userId, const QString& roomId) GetRoomTagsJob::~GetRoomTagsJob() = default; -const QJsonObject& GetRoomTagsJob::tags() const +const QHash<QString, GetRoomTagsJob::Tag>& GetRoomTagsJob::tags() const { return d->tags; } @@ -43,17 +61,19 @@ const QJsonObject& GetRoomTagsJob::tags() const BaseJob::Status GetRoomTagsJob::parseJson(const QJsonDocument& data) { auto json = data.object(); - d->tags = fromJson<QJsonObject>(json.value("tags"_ls)); + d->tags = fromJson<QHash<QString, Tag>>(json.value("tags"_ls)); return Success; } static const auto SetRoomTagJobName = QStringLiteral("SetRoomTagJob"); -SetRoomTagJob::SetRoomTagJob(const QString& userId, const QString& roomId, const QString& tag, const QJsonObject& body) +SetRoomTagJob::SetRoomTagJob(const QString& userId, const QString& roomId, const QString& tag, Omittable<float> order) : BaseJob(HttpVerb::Put, SetRoomTagJobName, basePath % "/user/" % userId % "/rooms/" % roomId % "/tags/" % tag) { - setRequestData(Data(toJson(body))); + QJsonObject _data; + addParam<IfNotEmpty>(_data, QStringLiteral("order"), order); + setRequestData(_data); } QUrl DeleteRoomTagJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId, const QString& tag) diff --git a/lib/csapi/tags.h b/lib/csapi/tags.h index af8e9edb..2c20c2a2 100644 --- a/lib/csapi/tags.h +++ b/lib/csapi/tags.h @@ -6,7 +6,9 @@ #include "jobs/basejob.h" -#include <QtCore/QJsonObject> +#include <QtCore/QVariant> +#include <QtCore/QHash> +#include "converters.h" namespace QMatrixClient { @@ -18,12 +20,26 @@ namespace QMatrixClient class GetRoomTagsJob : public BaseJob { public: + // Inner data structures + + /// List the tags set by a user on a room. + struct Tag + { + /// A number in a range ``[0,1]`` describing a relative + /// position of the room under the given tag. + Omittable<float> order; + /// List the tags set by a user on a room. + QVariantHash additionalProperties; + }; + + // Construction/destruction + /*! List the tags for a room. * \param userId * The id of the user to get tags for. The access token must be - * authorized to make requests for this user id. + * authorized to make requests for this user ID. * \param roomId - * The id of the room to get tags for. + * The ID of the room to get tags for. */ explicit GetRoomTagsJob(const QString& userId, const QString& roomId); @@ -40,7 +56,7 @@ namespace QMatrixClient // Result properties /// List the tags set by a user on a room. - const QJsonObject& tags() const; + const QHash<QString, Tag>& tags() const; protected: Status parseJson(const QJsonDocument& data) override; @@ -59,15 +75,16 @@ namespace QMatrixClient /*! Add a tag to a room. * \param userId * The id of the user to add a tag for. The access token must be - * authorized to make requests for this user id. + * authorized to make requests for this user ID. * \param roomId - * The id of the room to add a tag to. + * The ID of the room to add a tag to. * \param tag * The tag to add. - * \param body - * Extra data for the tag, e.g. ordering. + * \param order + * A number in a range ``[0,1]`` describing a relative + * position of the room under the given tag. */ - explicit SetRoomTagJob(const QString& userId, const QString& roomId, const QString& tag, const QJsonObject& body = {}); + explicit SetRoomTagJob(const QString& userId, const QString& roomId, const QString& tag, Omittable<float> order = none); }; /// Remove a tag from the room. @@ -79,9 +96,9 @@ namespace QMatrixClient /*! Remove a tag from the room. * \param userId * The id of the user to remove a tag for. The access token must be - * authorized to make requests for this user id. + * authorized to make requests for this user ID. * \param roomId - * The id of the room to remove a tag from. + * The ID of the room to remove a tag from. * \param tag * The tag to remove. */ diff --git a/lib/csapi/third_party_lookup.h b/lib/csapi/third_party_lookup.h index 5ebe5864..3a60432b 100644 --- a/lib/csapi/third_party_lookup.h +++ b/lib/csapi/third_party_lookup.h @@ -85,7 +85,7 @@ namespace QMatrixClient QScopedPointer<Private> d; }; - /// Retreive Matrix-side portals rooms leading to a third party location. + /// Retrieve Matrix-side portals rooms leading to a third party location. /// /// Requesting this endpoint with a valid protocol name results in a list /// of successful mapping results in a JSON array. Each result contains @@ -98,7 +98,7 @@ namespace QMatrixClient class QueryLocationByProtocolJob : public BaseJob { public: - /*! Retreive Matrix-side portals rooms leading to a third party location. + /*! Retrieve Matrix-side portals rooms leading to a third party location. * \param protocol * The protocol used to communicate to the third party network. * \param searchFields @@ -170,7 +170,7 @@ namespace QMatrixClient /// Reverse-lookup third party locations given a Matrix room alias. /// - /// Retreive an array of third party network locations from a Matrix room + /// Retrieve an array of third party network locations from a Matrix room /// alias. class QueryLocationByAliasJob : public BaseJob { @@ -206,7 +206,7 @@ namespace QMatrixClient /// Reverse-lookup third party users given a Matrix User ID. /// - /// Retreive an array of third party users from a Matrix User ID. + /// Retrieve an array of third party users from a Matrix User ID. class QueryUserByIDJob : public BaseJob { public: diff --git a/lib/csapi/users.h b/lib/csapi/users.h index 1c223945..1e355b8f 100644 --- a/lib/csapi/users.h +++ b/lib/csapi/users.h @@ -15,15 +15,31 @@ namespace QMatrixClient /// Searches the user directory. /// - /// This API performs a server-side search over all users registered on the server. - /// It searches user ID and displayname case-insensitively for users that you share a room with or that are in public rooms. + /// Performs a search for users on the homeserver. The homeserver may + /// determine which subset of users are searched, however the homeserver + /// MUST at a minimum consider the users the requesting user shares a + /// room with and those who reside in public rooms (known to the homeserver). + /// The search MUST consider local users to the homeserver, and SHOULD + /// query remote users as part of the search. + /// + /// The search is performed case-insensitively on user IDs and display + /// names preferably using a collation determined based upon the + /// ``Accept-Language`` header provided in the request, if present. class SearchUserDirectoryJob : public BaseJob { public: // Inner data structures - /// This API performs a server-side search over all users registered on the server. - /// It searches user ID and displayname case-insensitively for users that you share a room with or that are in public rooms. + /// Performs a search for users on the homeserver. The homeserver may + /// determine which subset of users are searched, however the homeserver + /// MUST at a minimum consider the users the requesting user shares a + /// room with and those who reside in public rooms (known to the homeserver). + /// The search MUST consider local users to the homeserver, and SHOULD + /// query remote users as part of the search. + /// + /// The search is performed case-insensitively on user IDs and display + /// names preferably using a collation determined based upon the + /// ``Accept-Language`` header provided in the request, if present. struct User { /// The user's matrix user ID. @@ -40,7 +56,7 @@ namespace QMatrixClient * \param searchTerm * The term to search for * \param limit - * The maximum number of results to return (Defaults to 10). + * The maximum number of results to return. Defaults to 10. */ explicit SearchUserDirectoryJob(const QString& searchTerm, Omittable<int> limit = none); ~SearchUserDirectoryJob() override; diff --git a/lib/csapi/wellknown.cpp b/lib/csapi/wellknown.cpp new file mode 100644 index 00000000..d42534a0 --- /dev/null +++ b/lib/csapi/wellknown.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "wellknown.h" + +#include "converters.h" + +#include <QtCore/QStringBuilder> + +using namespace QMatrixClient; + +static const auto basePath = QStringLiteral("/.well-known"); + +class GetWellknownJob::Private +{ + public: + HomeserverInformation homeserver; + Omittable<IdentityServerInformation> identityServer; +}; + +QUrl GetWellknownJob::makeRequestUrl(QUrl baseUrl) +{ + return BaseJob::makeRequestUrl(std::move(baseUrl), + basePath % "/matrix/client"); +} + +static const auto GetWellknownJobName = QStringLiteral("GetWellknownJob"); + +GetWellknownJob::GetWellknownJob() + : BaseJob(HttpVerb::Get, GetWellknownJobName, + basePath % "/matrix/client", false) + , d(new Private) +{ +} + +GetWellknownJob::~GetWellknownJob() = default; + +const HomeserverInformation& GetWellknownJob::homeserver() const +{ + return d->homeserver; +} + +const Omittable<IdentityServerInformation>& GetWellknownJob::identityServer() const +{ + return d->identityServer; +} + +BaseJob::Status GetWellknownJob::parseJson(const QJsonDocument& data) +{ + auto json = data.object(); + if (!json.contains("m.homeserver"_ls)) + return { JsonParseError, + "The key 'm.homeserver' not found in the response" }; + d->homeserver = fromJson<HomeserverInformation>(json.value("m.homeserver"_ls)); + d->identityServer = fromJson<IdentityServerInformation>(json.value("m.identity_server"_ls)); + return Success; +} + diff --git a/lib/csapi/wellknown.h b/lib/csapi/wellknown.h new file mode 100644 index 00000000..df4c8c6e --- /dev/null +++ b/lib/csapi/wellknown.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "jobs/basejob.h" + +#include "converters.h" +#include "csapi/definitions/wellknown/identity_server.h" +#include "csapi/definitions/wellknown/homeserver.h" + +namespace QMatrixClient +{ + // Operations + + /// Gets Matrix server discovery information about the domain. + /// + /// Gets discovery information about the domain. The file may include + /// additional keys, which MUST follow the Java package naming convention, + /// e.g. ``com.example.myapp.property``. This ensures property names are + /// suitably namespaced for each application and reduces the risk of + /// clashes. + /// + /// Note that this endpoint is not necessarily handled by the homeserver, + /// but by another webserver, to be used for discovering the homeserver URL. + class GetWellknownJob : public BaseJob + { + public: + explicit GetWellknownJob(); + + /*! Construct a URL without creating a full-fledged job object + * + * This function can be used when a URL for + * GetWellknownJob is necessary but the job + * itself isn't. + */ + static QUrl makeRequestUrl(QUrl baseUrl); + + ~GetWellknownJob() override; + + // Result properties + + /// Information about the homeserver to connect to. + const HomeserverInformation& homeserver() const; + /// Optional. Information about the identity server to connect to. + const Omittable<IdentityServerInformation>& identityServer() const; + + protected: + Status parseJson(const QJsonDocument& data) override; + + private: + class Private; + QScopedPointer<Private> d; + }; +} // namespace QMatrixClient diff --git a/lib/identity/definitions/request_email_validation.cpp b/lib/identity/definitions/request_email_validation.cpp new file mode 100644 index 00000000..95088bcb --- /dev/null +++ b/lib/identity/definitions/request_email_validation.cpp @@ -0,0 +1,33 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "request_email_validation.h" + +using namespace QMatrixClient; + +QJsonObject QMatrixClient::toJson(const RequestEmailValidation& pod) +{ + QJsonObject jo; + addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); + addParam<>(jo, QStringLiteral("email"), pod.email); + addParam<>(jo, QStringLiteral("send_attempt"), pod.sendAttempt); + addParam<IfNotEmpty>(jo, QStringLiteral("next_link"), pod.nextLink); + return jo; +} + +RequestEmailValidation FromJsonObject<RequestEmailValidation>::operator()(const QJsonObject& jo) const +{ + RequestEmailValidation result; + result.clientSecret = + fromJson<QString>(jo.value("client_secret"_ls)); + result.email = + fromJson<QString>(jo.value("email"_ls)); + result.sendAttempt = + fromJson<int>(jo.value("send_attempt"_ls)); + result.nextLink = + fromJson<QString>(jo.value("next_link"_ls)); + + return result; +} + diff --git a/lib/identity/definitions/request_email_validation.h b/lib/identity/definitions/request_email_validation.h new file mode 100644 index 00000000..3e72275f --- /dev/null +++ b/lib/identity/definitions/request_email_validation.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "converters.h" + +#include "converters.h" + +namespace QMatrixClient +{ + // Data structures + + struct RequestEmailValidation + { + /// A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + /// must not be empty. + QString clientSecret; + /// The email address to validate. + QString email; + /// The server will only send an email if the ``send_attempt`` + /// is a number greater than the most recent one which it has seen, + /// scoped to that ``email`` + ``client_secret`` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. + int sendAttempt; + /// Optional. When the validation is completed, the identity + /// server will redirect the user to this URL. + QString nextLink; + }; + + QJsonObject toJson(const RequestEmailValidation& pod); + + template <> struct FromJsonObject<RequestEmailValidation> + { + RequestEmailValidation operator()(const QJsonObject& jo) const; + }; + +} // namespace QMatrixClient diff --git a/lib/identity/definitions/request_msisdn_validation.cpp b/lib/identity/definitions/request_msisdn_validation.cpp new file mode 100644 index 00000000..125baa9c --- /dev/null +++ b/lib/identity/definitions/request_msisdn_validation.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "request_msisdn_validation.h" + +using namespace QMatrixClient; + +QJsonObject QMatrixClient::toJson(const RequestMsisdnValidation& pod) +{ + QJsonObject jo; + addParam<>(jo, QStringLiteral("client_secret"), pod.clientSecret); + addParam<>(jo, QStringLiteral("country"), pod.country); + addParam<>(jo, QStringLiteral("phone_number"), pod.phoneNumber); + addParam<>(jo, QStringLiteral("send_attempt"), pod.sendAttempt); + addParam<IfNotEmpty>(jo, QStringLiteral("next_link"), pod.nextLink); + return jo; +} + +RequestMsisdnValidation FromJsonObject<RequestMsisdnValidation>::operator()(const QJsonObject& jo) const +{ + RequestMsisdnValidation result; + result.clientSecret = + fromJson<QString>(jo.value("client_secret"_ls)); + result.country = + fromJson<QString>(jo.value("country"_ls)); + result.phoneNumber = + fromJson<QString>(jo.value("phone_number"_ls)); + result.sendAttempt = + fromJson<int>(jo.value("send_attempt"_ls)); + result.nextLink = + fromJson<QString>(jo.value("next_link"_ls)); + + return result; +} + diff --git a/lib/identity/definitions/request_msisdn_validation.h b/lib/identity/definitions/request_msisdn_validation.h new file mode 100644 index 00000000..77bea2bc --- /dev/null +++ b/lib/identity/definitions/request_msisdn_validation.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "converters.h" + +#include "converters.h" + +namespace QMatrixClient +{ + // Data structures + + struct RequestMsisdnValidation + { + /// A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// ``[0-9a-zA-Z.=_-]``. Its length must not exceed 255 characters and it + /// must not be empty. + QString clientSecret; + /// The two-letter uppercase ISO country code that the number in + /// ``phone_number`` should be parsed as if it were dialled from. + QString country; + /// The phone number to validate. + QString phoneNumber; + /// The server will only send an SMS if the ``send_attempt`` is a + /// number greater than the most recent one which it has seen, + /// scoped to that ``country`` + ``phone_number`` + ``client_secret`` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + int sendAttempt; + /// Optional. When the validation is completed, the identity + /// server will redirect the user to this URL. + QString nextLink; + }; + + QJsonObject toJson(const RequestMsisdnValidation& pod); + + template <> struct FromJsonObject<RequestMsisdnValidation> + { + RequestMsisdnValidation operator()(const QJsonObject& jo) const; + }; + +} // namespace QMatrixClient diff --git a/lib/identity/definitions/sid.cpp b/lib/identity/definitions/sid.cpp new file mode 100644 index 00000000..443dbedf --- /dev/null +++ b/lib/identity/definitions/sid.cpp @@ -0,0 +1,24 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#include "sid.h" + +using namespace QMatrixClient; + +QJsonObject QMatrixClient::toJson(const Sid& pod) +{ + QJsonObject jo; + addParam<>(jo, QStringLiteral("sid"), pod.sid); + return jo; +} + +Sid FromJsonObject<Sid>::operator()(const QJsonObject& jo) const +{ + Sid result; + result.sid = + fromJson<QString>(jo.value("sid"_ls)); + + return result; +} + diff --git a/lib/identity/definitions/sid.h b/lib/identity/definitions/sid.h new file mode 100644 index 00000000..eae60c47 --- /dev/null +++ b/lib/identity/definitions/sid.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ + +#pragma once + +#include "converters.h" + + +namespace QMatrixClient +{ + // Data structures + + struct Sid + { + /// The session ID. Session IDs are opaque strings generated by the identity + /// server. They must consist entirely of the characters + /// ``[0-9a-zA-Z.=_-]``. Their length must not exceed 255 characters and they + /// must not be empty. + QString sid; + }; + + QJsonObject toJson(const Sid& pod); + + template <> struct FromJsonObject<Sid> + { + Sid operator()(const QJsonObject& jo) const; + }; + +} // namespace QMatrixClient diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 2bb3b499..cb90a9fd 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -44,7 +44,9 @@ HEADERS += \ $$SRCPATH/jobs/postreadmarkersjob.h \ $$files($$SRCPATH/csapi/*.h, false) \ $$files($$SRCPATH/csapi/definitions/*.h, false) \ + $$files($$SRCPATH/csapi/definitions/wellknown/*.h, false) \ $$files($$SRCPATH/application-service/definitions/*.h, false) \ + $$files($$SRCPATH/identity/definitions/*.h, false) \ $$SRCPATH/logging.h \ $$SRCPATH/converters.h \ $$SRCPATH/settings.h \ @@ -79,7 +81,9 @@ SOURCES += \ $$SRCPATH/jobs/downloadfilejob.cpp \ $$files($$SRCPATH/csapi/*.cpp, false) \ $$files($$SRCPATH/csapi/definitions/*.cpp, false) \ + $$files($$SRCPATH/csapi/definitions/wellknown/*.cpp, false) \ $$files($$SRCPATH/application-service/definitions/*.cpp, false) \ + $$files($$SRCPATH/identity/definitions/*.cpp, false) \ $$SRCPATH/logging.cpp \ $$SRCPATH/converters.cpp \ $$SRCPATH/settings.cpp \ |