From e16049b5b3378a6b8ed7b2a9300aac27e193008c Mon Sep 17 00:00:00 2001 From: iinuwa Date: Sat, 22 Feb 2020 16:14:10 -0600 Subject: [PATCH] Add invite-by-3pid endpoint --- CHANGELOG.md | 3 ++ src/r0/membership.rs | 15 +++++++ src/r0/membership/invite_user.rs | 68 ++++++++++++++++++++++++++++++-- src/r0/room/create_room.rs | 15 +------ 4 files changed, 84 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4049b6c7..5479e03c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ Breaking changes: * Fix `r0::session::get_login_types` * Add `allow_remote` parameter to `r0::media::get_content` * Add missing parameters for `r0::room::create_room` +* Moved `r0::room::create_room::Invite3pid` to `r0::membership::Invite3pid` +* Replaced `user_id` parameter of `r0::membership::invite_user` with `recipient` + to allow invitation of users by either Matrix or third party identifiers. * Remove deprecated endpoint `r0::contact::create_contact` (deprecated in r0.6.0) # 0.6.0 diff --git a/src/r0/membership.rs b/src/r0/membership.rs index 023965c7..37880957 100644 --- a/src/r0/membership.rs +++ b/src/r0/membership.rs @@ -16,6 +16,8 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; +use crate::r0::thirdparty::Medium; + // TODO: spec requires a nesting ThirdPartySigned { signed: Signed { mxid: ..., ... } } // for join_room_by_id_or_alias but not for join_room_by_id, inconsistency? @@ -32,3 +34,16 @@ pub struct ThirdPartySigned { /// The state key of the m.third_party_invite event. pub token: String, } + +/// Represents third party IDs to invite to the room. +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +pub struct Invite3pid { + /// Hostname and port of identity server to be used for account lookups. + pub id_server: String, + /// An access token registered with the identity server. + pub id_access_token: String, + /// Type of third party ID. + pub medium: Medium, + /// Third party identifier. + pub address: String, +} diff --git a/src/r0/membership/invite_user.rs b/src/r0/membership/invite_user.rs index f0d59871..bac550e8 100644 --- a/src/r0/membership/invite_user.rs +++ b/src/r0/membership/invite_user.rs @@ -1,7 +1,16 @@ -//! [POST /_matrix/client/r0/rooms/{roomId}/invite](https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-rooms-roomid-invite) - +//! [POST /_matrix/client/r0/rooms/{roomId}/invite][invite-by-user-id] +//! +//! This endpoint has two forms: one to invite a user +//! [by their Matrix identifier][invite-by-user-id], and one to invite a user +//! [by their third party identifier][invite-by-3pid]. +//! +//! [invite-by-user-id]: https://matrix.org/docs/spec/client_server/r0.6.0.html#post-matrix-client-r0-rooms-roomid-invite +//! [invite-by-3pid]: https://matrix.org/docs/spec/client_server/r0.6.0#id101 use ruma_api::ruma_api; use ruma_identifiers::{RoomId, UserId}; +use serde::{Deserialize, Serialize}; + +use super::Invite3pid; ruma_api! { metadata { @@ -18,8 +27,61 @@ ruma_api! { #[ruma_api(path)] pub room_id: RoomId, /// The user to invite. - pub user_id: UserId, + #[ruma_api(body)] + pub recipient: InvitationRecipient, } response {} } + +/// Distinguishes between invititations by Matrix or third party identifiers. +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(untagged)] +pub enum InvitationRecipient { + /// Used to invite user by their Matrix identifer. + UserId { + /// Matrix identifier of user. + user_id: UserId, + }, + /// Used to invite user by a third party identifer. + ThirdPartyId(Invite3pid), +} + +#[cfg(test)] +mod tests { + use super::InvitationRecipient; + use crate::r0::{membership::Invite3pid, thirdparty::Medium}; + use ruma_identifiers::UserId; + use std::convert::TryFrom; + #[test] + fn deserialize_invite_by_user_id() { + let incoming = + serde_json::from_str::(r#" { "user_id": "@carl:example.org" } "#) + .unwrap(); + let user_id = UserId::try_from("@carl:example.org").unwrap(); + let recipient = InvitationRecipient::UserId { user_id }; + assert_eq!(incoming, recipient); + } + + #[test] + fn deserialize_invite_by_3pid() { + let incoming = serde_json::from_str::( + r#" + { + "id_server": "example.org", + "id_access_token": "abcdefghijklmnop", + "medium": "email", + "address": "carl@example.org" + } + "#, + ) + .unwrap(); + let recipient = InvitationRecipient::ThirdPartyId(Invite3pid { + id_server: "example.org".to_string(), + id_access_token: "abcdefghijklmnop".to_string(), + medium: Medium::Email, + address: "carl@example.org".to_string(), + }); + assert_eq!(incoming, recipient); + } +} diff --git a/src/r0/room/create_room.rs b/src/r0/room/create_room.rs index 53d077f6..5b81627c 100644 --- a/src/r0/room/create_room.rs +++ b/src/r0/room/create_room.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use super::Visibility; -use crate::r0::thirdparty::Medium; +use crate::r0::membership::Invite3pid; ruma_api! { metadata { @@ -96,19 +96,6 @@ pub enum RoomPreset { TrustedPrivateChat, } -/// Represents third party IDs to invite to the room. -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Invite3pid { - /// Hostname and port of identity server to be used for account lookups. - pub id_server: String, - /// An access token registered with the identity server. - pub id_access_token: String, - /// Type of third party ID. - pub medium: Medium, - /// Third party identifier. - pub address: String, -} - /// Represents content of a state event to be used to initalize new room state. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct InitialStateEvent {