ruma_state_res/events/
member.rs1use std::ops::Deref;
4
5use ruma_common::{serde::from_raw_json_value, CanonicalJsonObject, OwnedUserId};
6use ruma_events::room::member::MembershipState;
7use ruma_signatures::canonical_json;
8use serde::Deserialize;
9use serde_json::value::RawValue as RawJsonValue;
10
11use super::Event;
12
13#[derive(Debug, Clone)]
17pub struct RoomMemberEvent<E: Event>(E);
18
19impl<E: Event> RoomMemberEvent<E> {
20 pub fn new(event: E) -> Self {
22 Self(event)
23 }
24
25 pub fn membership(&self) -> Result<MembershipState, String> {
27 RoomMemberEventContent(self.content()).membership()
28 }
29
30 pub fn join_authorised_via_users_server(&self) -> Result<Option<OwnedUserId>, String> {
32 RoomMemberEventContent(self.content()).join_authorised_via_users_server()
33 }
34
35 pub(crate) fn third_party_invite(&self) -> Result<Option<ThirdPartyInvite>, String> {
38 RoomMemberEventContent(self.content()).third_party_invite()
39 }
40}
41
42impl<E: Event> Deref for RoomMemberEvent<E> {
43 type Target = E;
44
45 fn deref(&self) -> &Self::Target {
46 &self.0
47 }
48}
49
50pub(crate) trait RoomMemberEventOptionExt {
52 fn membership(&self) -> Result<MembershipState, String>;
56}
57
58impl<E: Event> RoomMemberEventOptionExt for Option<RoomMemberEvent<E>> {
59 fn membership(&self) -> Result<MembershipState, String> {
60 match self {
61 Some(event) => event.membership(),
62 None => Ok(MembershipState::Leave),
63 }
64 }
65}
66
67pub(crate) struct RoomMemberEventContent<'a>(&'a RawJsonValue);
69
70impl<'a> RoomMemberEventContent<'a> {
71 pub(crate) fn new(content: &'a RawJsonValue) -> Self {
73 Self(content)
74 }
75}
76
77impl RoomMemberEventContent<'_> {
78 pub(crate) fn membership(&self) -> Result<MembershipState, String> {
80 #[derive(Deserialize)]
81 struct RoomMemberContentMembership {
82 membership: MembershipState,
83 }
84
85 let content: RoomMemberContentMembership =
86 from_raw_json_value(self.0).map_err(|err: serde_json::Error| {
87 format!("missing or invalid `membership` field in `m.room.member` event: {err}")
88 })?;
89 Ok(content.membership)
90 }
91
92 pub(crate) fn join_authorised_via_users_server(&self) -> Result<Option<OwnedUserId>, String> {
94 #[derive(Deserialize)]
95 struct RoomMemberContentJoinAuthorizedViaUsersServer {
96 join_authorised_via_users_server: Option<OwnedUserId>,
97 }
98
99 let content: RoomMemberContentJoinAuthorizedViaUsersServer = from_raw_json_value(self.0)
100 .map_err(|err: serde_json::Error| {
101 format!(
102 "invalid `join_authorised_via_users_server` field in `m.room.member` event: {err}"
103 )
104 })?;
105 Ok(content.join_authorised_via_users_server)
106 }
107
108 pub(crate) fn third_party_invite(&self) -> Result<Option<ThirdPartyInvite>, String> {
111 #[derive(Deserialize)]
112 struct RoomMemberContentThirdPartyInvite {
113 third_party_invite: Option<ThirdPartyInvite>,
114 }
115
116 let content: RoomMemberContentThirdPartyInvite =
117 from_raw_json_value(self.0).map_err(|err: serde_json::Error| {
118 format!("invalid `third_party_invite` field in `m.room.member` event: {err}")
119 })?;
120 Ok(content.third_party_invite)
121 }
122}
123
124#[derive(Deserialize)]
126pub(crate) struct ThirdPartyInvite {
127 signed: CanonicalJsonObject,
129}
130
131impl ThirdPartyInvite {
132 pub(crate) fn token(&self) -> Result<&str, String> {
134 let Some(token_value) = self.signed.get("token") else {
135 return Err("missing `token` field in `third_party_invite.signed` \
136 of `m.room.member` event"
137 .into());
138 };
139
140 token_value.as_str().ok_or_else(|| {
141 format!(
142 "unexpected format of `token` field in `third_party_invite.signed` \
143 of `m.room.member` event: expected string, got {token_value:?}"
144 )
145 })
146 }
147
148 pub(crate) fn mxid(&self) -> Result<&str, String> {
150 let Some(mxid_value) = self.signed.get("mxid") else {
151 return Err("missing `mxid` field in `third_party_invite.signed` \
152 of `m.room.member` event"
153 .into());
154 };
155
156 mxid_value.as_str().ok_or_else(|| {
157 format!(
158 "unexpected format of `mxid` field in `third_party_invite.signed` \
159 of `m.room.member` event: expected string, got {mxid_value:?}"
160 )
161 })
162 }
163
164 pub(crate) fn signatures(&self) -> Result<&CanonicalJsonObject, String> {
166 let Some(signatures_value) = self.signed.get("signatures") else {
167 return Err("missing `signatures` field in `third_party_invite.signed` \
168 of `m.room.member` event"
169 .into());
170 };
171
172 signatures_value.as_object().ok_or_else(|| {
173 format!(
174 "unexpected format of `signatures` field in `third_party_invite.signed` \
175 of `m.room.member` event: expected object, got {signatures_value:?}"
176 )
177 })
178 }
179
180 pub(crate) fn signed_canonical_json(&self) -> Result<String, String> {
182 canonical_json(&self.signed).map_err(|error| {
183 format!("invalid `third_party_invite.signed` field in `m.room.member` event: {error}")
184 })
185 }
186}