| 1 | #pragma once |
| 2 | |
| 3 | /// @file |
| 4 | /// @brief Structs for for requests to the Matrix API. |
| 5 | |
| 6 | #include <string> |
| 7 | #include <variant> |
| 8 | |
| 9 | #include <mtx/common.hpp> |
| 10 | #include <mtx/events/collections.hpp> |
| 11 | #if __has_include(<nlohmann/json_fwd.hpp>) |
| 12 | #include <nlohmann/json_fwd.hpp> |
| 13 | #else |
| 14 | #include <nlohmann/json.hpp> |
| 15 | #endif |
| 16 | |
| 17 | namespace mtx { |
| 18 | //! Namespace for request structs |
| 19 | namespace requests { |
| 20 | //! Convenience parameter for setting various default state events based on a preset. |
| 21 | enum class Preset |
| 22 | { |
| 23 | //! `join_rules` is set to `invite`. `history_visibility` is set to `shared`. |
| 24 | PrivateChat, |
| 25 | //! `join_rules` is set to `public`. `history_visibility` is set to `shared`. |
| 26 | PublicChat, |
| 27 | //! `join_rules` is set to `invite`. `history_visibility` is set to `shared`. |
| 28 | //! All invitees are given the same power level as the room creator. |
| 29 | TrustedPrivateChat, |
| 30 | }; |
| 31 | |
| 32 | //! Request payload for the `POST /_matrix/client/r0/createRoom` endpoint. |
| 33 | struct CreateRoom |
| 34 | { |
| 35 | //! If this is included, an `m.room.name` event will |
| 36 | //! be sent into the room to indicate the name of the room. |
| 37 | std::string name; |
| 38 | //! If this is included, an `m.room.topic` event will be sent |
| 39 | //! into the room to indicate the topic for the room. |
| 40 | std::string topic; |
| 41 | //! The desired room alias local part. e.g `#foo:example.com`. |
| 42 | std::string room_alias_name; |
| 43 | //! A list of user IDs to invite to the room. |
| 44 | std::vector<std::string> invite; |
| 45 | //! This flag makes the server set the is_direct flag on the |
| 46 | //! `m.room.member` events sent to the users in @p invite and @p invite_3pid. |
| 47 | bool is_direct = false; |
| 48 | //! Convenience parameter for setting various default state events. |
| 49 | Preset preset = Preset::PrivateChat; |
| 50 | //! Whether or not the room will be visible by non members. |
| 51 | common::RoomVisibility visibility = common::RoomVisibility::Private; |
| 52 | |
| 53 | //! A list of state events to set in the new room. This allows the user to override the default |
| 54 | //! state events set in the new room. The expected format of the state events are an object with |
| 55 | //! type, state_key and content keys set. |
| 56 | std::vector<events::collections::StrippedEvents> initial_state; |
| 57 | |
| 58 | //! The room version to set for the room. If not provided, the homeserver is to use its |
| 59 | //! configured default. If provided, the homeserver will return a 400 error with the errcode |
| 60 | //! M_UNSUPPORTED_ROOM_VERSION if it does not support the room version. |
| 61 | std::string room_version; |
| 62 | |
| 63 | //! Extra keys, such as m.federate, to be added to the content of the m.room.create event. The |
| 64 | //! server will overwrite the following keys: creator, room_version. Future versions of the |
| 65 | //! specification may allow the server to overwrite other keys. |
| 66 | std::optional<events::state::Create> creation_content; |
| 67 | |
| 68 | friend void to_json(nlohmann::json &obj, const CreateRoom &request); |
| 69 | }; |
| 70 | |
| 71 | namespace login_identifier { |
| 72 | //! The user is identified by their Matrix ID. |
| 73 | struct User |
| 74 | { |
| 75 | //! A client can identify a user using their Matrix ID. This can either be the fully |
| 76 | //! qualified Matrix user ID, or just the localpart of the user ID. |
| 77 | std::string user; |
| 78 | }; |
| 79 | //! The user is identified by a third-party identifier in canonicalised form. |
| 80 | struct Thirdparty |
| 81 | { |
| 82 | //! The medium of the third party identifier |
| 83 | std::string medium; |
| 84 | //! The canonicalised third party address of the user |
| 85 | std::string address; |
| 86 | }; |
| 87 | //! The user is identified by a phone number. |
| 88 | struct PhoneNumber |
| 89 | { |
| 90 | //! The country is the two-letter uppercase ISO-3166-1 alpha-2 country code that the number |
| 91 | //! in phone should be parsed as if it were dialled from. |
| 92 | std::string country; |
| 93 | //! The phone number. If the client wishes to canonicalise the phone number, then it can use |
| 94 | //! the m.id.thirdparty identifier type with a medium of msisdn instead. |
| 95 | std::string phone; |
| 96 | }; |
| 97 | } |
| 98 | |
| 99 | //! Request payload for the `POST /_matrix/client/r0/login` endpoint. |
| 100 | struct Login |
| 101 | { |
| 102 | //! The login type being used. One of ["m.login.password", "m.login.token"] |
| 103 | std::string type = "m.login.password" ; |
| 104 | //! Identification information for the user. Usually you use `login_identifier::User` with |
| 105 | //! an mxid. Required. |
| 106 | std:: |
| 107 | variant<login_identifier::User, login_identifier::Thirdparty, login_identifier::PhoneNumber> |
| 108 | identifier; |
| 109 | //! Required when type is m.login.token. The login token. |
| 110 | std::string token; |
| 111 | //! Required when type is m.login.password. The user's password. |
| 112 | std::string password; |
| 113 | //! ID of the client device. If this does not correspond to a known client device, |
| 114 | //! a new device will be created. |
| 115 | //! The server will auto-generate a device_id if this is not specified. |
| 116 | std::string device_id; |
| 117 | //! A display name to assign to the newly-created device. |
| 118 | //! Ignored if device_id corresponds to a known device. |
| 119 | std::string initial_device_display_name; |
| 120 | |
| 121 | friend void to_json(nlohmann::json &obj, const Login &request); |
| 122 | }; |
| 123 | |
| 124 | /// @brief Request payload for |
| 125 | /// `POST /_matrix/client/r0/{register,account/password}/email/requestToken` |
| 126 | /// |
| 127 | /// The homeserver should validate the email itself, either by sending a validation email itself or |
| 128 | /// by using a service it has control over. |
| 129 | struct RequestEmailToken |
| 130 | { |
| 131 | //! Required. A unique string generated by the client, and used to identify the validation |
| 132 | //! attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must |
| 133 | //! not exceed 255 characters and it must not be empty. |
| 134 | std::string client_secret; |
| 135 | //! Required. The email address to validate. |
| 136 | std::string email; |
| 137 | |
| 138 | //! Required. The server will only send an email if the send_attempt is a number greater than |
| 139 | //! the most recent one which it has seen, scoped to that email + client_secret pair. This is to |
| 140 | //! avoid repeatedly sending the same email in the case of request retries between the POSTing |
| 141 | //! user and the identity server. The client should increment this value if they desire a new |
| 142 | //! email (e.g. a reminder) to be sent. If they do not, the server should respond with success |
| 143 | //! but not resend the email. |
| 144 | int send_attempt = 0; |
| 145 | |
| 146 | friend void to_json(nlohmann::json &obj, const RequestEmailToken &request); |
| 147 | }; |
| 148 | |
| 149 | /// @brief Request payload for |
| 150 | /// `POST /_matrix/client/r0/{register,account/password}/msisdn/requestToken` |
| 151 | /// |
| 152 | /// The homeserver should validate the email itself, either by sending a validation email itself or |
| 153 | /// by using a service it has control over. |
| 154 | struct RequestMSISDNToken |
| 155 | { |
| 156 | //! Required. A unique string generated by the client, and used to identify the validation |
| 157 | //! attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must |
| 158 | //! not exceed 255 characters and it must not be empty. |
| 159 | std::string client_secret; |
| 160 | //! Required. The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in |
| 161 | //! phone_number should be parsed as if it were dialled from. |
| 162 | std::string country; |
| 163 | //! Required. The phone number to validate. |
| 164 | std::string phone_number; |
| 165 | |
| 166 | //! Required. The server will only send an SMS if the send_attempt is a number greater than the |
| 167 | //! most recent one which it has seen, scoped to that country + phone_number + client_secret |
| 168 | //! triple. This is to avoid repeatedly sending the same SMS in the case of request retries |
| 169 | //! between the POSTing user and the identity server. The client should increment this value if |
| 170 | //! they desire a new SMS (e.g. a reminder) to be sent. |
| 171 | int send_attempt = 0; |
| 172 | }; |
| 173 | |
| 174 | void |
| 175 | to_json(nlohmann::json &obj, const RequestMSISDNToken &request); |
| 176 | |
| 177 | //! Validate ownership of an email address/phone number. |
| 178 | struct IdentitySubmitToken |
| 179 | { |
| 180 | //! Required. The session ID, generated by the requestToken call. |
| 181 | std::string sid; |
| 182 | //! Required. The client secret that was supplied to the requestToken call. |
| 183 | std::string client_secret; |
| 184 | //! Required. The token generated by the requestToken call and emailed to the user. |
| 185 | std::string token; |
| 186 | |
| 187 | friend void to_json(nlohmann::json &obj, const IdentitySubmitToken &request); |
| 188 | }; |
| 189 | |
| 190 | //! Request payload for the `PUT /_matrix/client/r0/sendToDevice/{eventType}/{transcationID}` |
| 191 | template<typename EventContent> |
| 192 | using ToDeviceMessages = std::map<mtx::identifiers::User, std::map<std::string, EventContent>>; |
| 193 | |
| 194 | //! Request payload for the `POST /_matrix/client/r0/profile/{userId}/avatar_url` endpoint. |
| 195 | struct AvatarUrl |
| 196 | { |
| 197 | std::string avatar_url; |
| 198 | |
| 199 | friend void to_json(nlohmann::json &obj, const AvatarUrl &request); |
| 200 | }; |
| 201 | |
| 202 | //! Request payload for the `PUT /_matrix/client/r0/profile/{userId}/displayname` endpoint. |
| 203 | struct DisplayName |
| 204 | { |
| 205 | //! The new display name for this device. If not given, the display name is unchanged. |
| 206 | std::string displayname; |
| 207 | |
| 208 | friend void to_json(nlohmann::json &obj, const DisplayName &request); |
| 209 | }; |
| 210 | |
| 211 | //! Request payload for the `POST /_matrix/client/r0/rooms/{roomId}/invite` endpoint as well as ban, |
| 212 | //! unban and kick. |
| 213 | struct RoomMembershipChange |
| 214 | { |
| 215 | std::string user_id; |
| 216 | |
| 217 | //! optional kick, invite or ban reason |
| 218 | std::string reason; |
| 219 | |
| 220 | friend void to_json(nlohmann::json &obj, const RoomMembershipChange &request); |
| 221 | }; |
| 222 | |
| 223 | //! Request payload for the `PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}` endpoint. |
| 224 | struct TypingNotification |
| 225 | { |
| 226 | //! Whether the user is typing or not. |
| 227 | bool typing = false; |
| 228 | //! The length of time in milliseconds to mark this user as typing. |
| 229 | uint64_t timeout = 0; |
| 230 | |
| 231 | friend void to_json(nlohmann::json &obj, const TypingNotification &request); |
| 232 | }; |
| 233 | |
| 234 | //! Request payload for the `PUT /_matrix/client/r0/devices/{deviceId}` endpoint. |
| 235 | struct DeviceUpdate |
| 236 | { |
| 237 | std::string display_name; |
| 238 | |
| 239 | friend void to_json(nlohmann::json &obj, const DeviceUpdate &request); |
| 240 | }; |
| 241 | |
| 242 | //! Request payload for the `PUT /_matrix/client/r0/directory/list/room/{roomId}` endpoint |
| 243 | struct PublicRoomVisibility |
| 244 | { |
| 245 | //! The new visibility setting for the room. Defaults to 'public'. One of: ["private", |
| 246 | //! "public"] |
| 247 | common::RoomVisibility visibility; |
| 248 | |
| 249 | friend void to_json(nlohmann::json &obj, const PublicRoomVisibility &request); |
| 250 | }; |
| 251 | |
| 252 | struct PublicRoomsFilter |
| 253 | { |
| 254 | //! A string to search for in the room metadata, |
| 255 | //! e.g. name, topic, canonical alias etc. (Optional). |
| 256 | std::string generic_search_term; |
| 257 | |
| 258 | friend void to_json(nlohmann::json &obj, const PublicRoomsFilter &req); |
| 259 | }; |
| 260 | |
| 261 | //! Request payload for the `POST /_matrix/client/r0/publicRooms` endpoint. |
| 262 | struct PublicRooms |
| 263 | { |
| 264 | //! Limit the number of results returned. |
| 265 | int limit; |
| 266 | //! A pagination token from a previous request, allowing clients |
| 267 | //! to get the next (or previous) batch of rooms. The direction of |
| 268 | //! pagination is specified solely by which token is supplied, |
| 269 | //! rather than via an explicit flag. |
| 270 | std::string since; |
| 271 | //! Filter to apply to the results. |
| 272 | PublicRoomsFilter filter; |
| 273 | //! Whether or not to include all known networks/protocols from |
| 274 | //! application services on the homeserver. Defaults to false. |
| 275 | bool include_all_networks = false; |
| 276 | //! The specific third party network/protocol to request from |
| 277 | //! the homeserver. Can only be used if include_all_networks is false. |
| 278 | std::string third_party_instance_id; |
| 279 | |
| 280 | friend void to_json(nlohmann::json &obj, const PublicRooms &request); |
| 281 | }; |
| 282 | |
| 283 | //! An empty response. |
| 284 | /// |
| 285 | /// Some endpoints return this on success. |
| 286 | struct Empty |
| 287 | { |
| 288 | friend inline void to_json(nlohmann::json &, const Empty &) {} |
| 289 | }; |
| 290 | |
| 291 | //! A successfull logout. |
| 292 | using Logout = Empty; |
| 293 | |
| 294 | //! A signed onetime key. Usually curve25519. |
| 295 | struct SignedOneTimeKey |
| 296 | { |
| 297 | //! Required. The unpadded Base64-encoded 32-byte Curve25519 public key. |
| 298 | std::string key; |
| 299 | //! When uploading a signed key, an additional fallback: true key should be included to denote |
| 300 | //! that the key is a fallback key. |
| 301 | bool fallback = false; |
| 302 | //! Required. Signatures of the key object. |
| 303 | //! The signature is calculated using the process described at Signing JSON. |
| 304 | std::map<std::string, std::map<std::string, std::string>> signatures; |
| 305 | |
| 306 | friend void to_json(nlohmann::json &obj, const SignedOneTimeKey &); |
| 307 | }; |
| 308 | |
| 309 | //! Upload a mix of device, one time and fallback keys. |
| 310 | struct UploadKeys |
| 311 | { |
| 312 | //! Identity keys for the device. |
| 313 | //! May be absent if no new identity keys are required. |
| 314 | mtx::crypto::DeviceKeys device_keys; |
| 315 | //! One-time public keys for "pre-key" messages. |
| 316 | //! The names of the properties should be in the format `<algorithm>:<key_id>`. |
| 317 | //! The format of the key is determined by the key algorithm. |
| 318 | std::map<std::string, std::variant<std::string, SignedOneTimeKey>> one_time_keys; |
| 319 | |
| 320 | //! The public key which should be used if the device’s one-time keys are exhausted. The |
| 321 | //! fallback key is not deleted once used, but should be replaced when additional one-time keys |
| 322 | //! are being uploaded. The server will notify the client of the fallback key being used through |
| 323 | //! /sync. |
| 324 | //! |
| 325 | //! There can only be at most one key per algorithm uploaded, and the server will only persist |
| 326 | //! one key per algorithm. |
| 327 | //! |
| 328 | //! When uploading a signed key, an additional fallback: true key should be included to denote |
| 329 | //! that the key is a fallback key. |
| 330 | //! |
| 331 | //! May be absent if a new fallback key is not required. |
| 332 | std::map<std::string, std::variant<std::string, SignedOneTimeKey>> fallback_keys; |
| 333 | |
| 334 | friend void to_json(nlohmann::json &obj, const UploadKeys &); |
| 335 | }; |
| 336 | |
| 337 | //! The default timeout for a download. |
| 338 | inline constexpr uint64_t DEFAULT_DOWNLOAD_TIMEOUT = 10UL * 1000; // 10 seconds |
| 339 | |
| 340 | //! Query the keys of devices of specific users. |
| 341 | struct QueryKeys |
| 342 | { |
| 343 | //! The time (in milliseconds) to wait when downloading keys from remote servers. |
| 344 | uint64_t timeout = DEFAULT_DOWNLOAD_TIMEOUT; |
| 345 | //! The keys to be downloaded. |
| 346 | //! A map from user ID, to a list of device IDs, or to an empty |
| 347 | //! list to indicate all devices for the corresponding user. |
| 348 | std::map<std::string, std::vector<std::string>> device_keys; |
| 349 | //! If the client is fetching keys as a result of a device update |
| 350 | //! received in a sync request, this should be the 'since' token of |
| 351 | //! that sync request, or any later sync token. |
| 352 | //! This allows the server to ensure its response contains the keys |
| 353 | //! advertised by the notification in that sync. |
| 354 | std::string token; |
| 355 | |
| 356 | friend void to_json(nlohmann::json &obj, const QueryKeys &); |
| 357 | }; |
| 358 | |
| 359 | //! Claim onetime keys of devices of specific users. |
| 360 | struct ClaimKeys |
| 361 | { |
| 362 | //! The time (in milliseconds) to wait when downloading keys from remote servers. |
| 363 | uint64_t timeout = DEFAULT_DOWNLOAD_TIMEOUT; |
| 364 | //! The keys to be claimed. A map from user ID, to a map from device ID to algorithm name. |
| 365 | std::map<std::string, std::map<std::string, std::string>> one_time_keys; |
| 366 | |
| 367 | friend void to_json(nlohmann::json &obj, const ClaimKeys &request); |
| 368 | }; |
| 369 | |
| 370 | //! Upload new signatures for a device or cross-signing key. |
| 371 | struct KeySignaturesUpload |
| 372 | { |
| 373 | //! map from user_id to either a map of device id to DeviceKey with new signatures or the |
| 374 | //! key id to CrossSigningKeys with new signatures |
| 375 | std::map< |
| 376 | std::string, |
| 377 | std::map<std::string, std::variant<mtx::crypto::DeviceKeys, mtx::crypto::CrossSigningKeys>>> |
| 378 | signatures; |
| 379 | |
| 380 | friend void to_json(nlohmann::json &obj, const KeySignaturesUpload &req); |
| 381 | }; |
| 382 | |
| 383 | //! Upload cross signing keys |
| 384 | struct DeviceSigningUpload |
| 385 | { |
| 386 | //! Optional. The user's master key. |
| 387 | std::optional<mtx::crypto::CrossSigningKeys> master_key; |
| 388 | //! Optional. The user's self-signing key. Must be signed by the accompanying master key, or by |
| 389 | //! the user's most recently uploaded master key if no master key is included in the request. |
| 390 | std::optional<mtx::crypto::CrossSigningKeys> self_signing_key; |
| 391 | //! Optional. The user's user-signing key. Must be signed by the accompanying master key, or by |
| 392 | //! the user's most recently uploaded master key if no master key is included in the request. |
| 393 | std::optional<mtx::crypto::CrossSigningKeys> user_signing_key; |
| 394 | |
| 395 | friend void to_json(nlohmann::json &obj, const DeviceSigningUpload &req); |
| 396 | }; |
| 397 | |
| 398 | //! Information about a pusher. |
| 399 | struct PusherData |
| 400 | { |
| 401 | //! Required if `kind` is http. The URL to use to send notifications to. |
| 402 | //! MUST be an HTTPS URL with a path of /_matrix/push/v1/notify. |
| 403 | std::string url; |
| 404 | //! The format to send notifications in to Push Gateways if the kind is http. |
| 405 | //! The details about what fields the homeserver should send to the push gateway are |
| 406 | //! defined in the Push Gateway Specification. Currently the only format available is |
| 407 | //! 'event_id_only'. |
| 408 | std::string format; |
| 409 | |
| 410 | friend void to_json(nlohmann::json &obj, const PusherData &data); |
| 411 | }; |
| 412 | |
| 413 | //! Request payload for the `POST /_matrix/client/r0/pushers/set` endpoint. |
| 414 | struct SetPusher |
| 415 | { |
| 416 | //! Required. Unique identifier for this pusher. |
| 417 | std::string pushkey; |
| 418 | //! Required. The kind of pusher to configure. "http" makes a pusher that sends HTTP pokes. |
| 419 | //! "email" makes a pusher that emails the user with unread notifications. |
| 420 | //! null deletes the pusher. |
| 421 | std::string kind; |
| 422 | //! Required. This is a reverse-DNS style identifier for the application. |
| 423 | //! If the `kind` is "email", this is "m.email". |
| 424 | std::string app_id; |
| 425 | //! Required. A string that will allow the user to identify what application owns this |
| 426 | //! pusher. |
| 427 | std::string app_display_name; |
| 428 | //! Required. A string that will allow the user to identify what device owns this pusher. |
| 429 | std::string device_display_name; |
| 430 | //! Determines which set of device specific rules this pusher executes. |
| 431 | std::string profile_tag; |
| 432 | //! Required. The preferred language for receiving notifications. |
| 433 | std::string lang; |
| 434 | //! Required. Data for the pusher implementation (for example, if `kind` is `http`, includes |
| 435 | //! the URL to push to). |
| 436 | PusherData data; |
| 437 | //! If true, add another pusher instead of updating an existing one. |
| 438 | bool append = false; |
| 439 | |
| 440 | friend void to_json(nlohmann::json &obj, const SetPusher &req); |
| 441 | }; |
| 442 | } // namespace requests |
| 443 | } // namespace mtx |
| 444 | |