|
|
|
@ -3,11 +3,18 @@ mod edus; |
|
|
|
pub use edus::RoomEdus; |
|
|
|
pub use edus::RoomEdus; |
|
|
|
|
|
|
|
|
|
|
|
use crate::{utils, Error, PduEvent, Result}; |
|
|
|
use crate::{utils, Error, PduEvent, Result}; |
|
|
|
use ruma_events::{room::power_levels::PowerLevelsEventContent, EventJson, EventType}; |
|
|
|
use log::error; |
|
|
|
|
|
|
|
use ruma_events::{ |
|
|
|
|
|
|
|
room::{ |
|
|
|
|
|
|
|
join_rules, member, |
|
|
|
|
|
|
|
power_levels::{self, PowerLevelsEventContent}, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
EventJson, EventType, |
|
|
|
|
|
|
|
}; |
|
|
|
use ruma_identifiers::{EventId, RoomId, UserId}; |
|
|
|
use ruma_identifiers::{EventId, RoomId, UserId}; |
|
|
|
use serde_json::json; |
|
|
|
|
|
|
|
use std::{ |
|
|
|
use std::{ |
|
|
|
collections::HashMap, |
|
|
|
collections::{BTreeMap, HashMap}, |
|
|
|
convert::{TryFrom, TryInto}, |
|
|
|
convert::{TryFrom, TryInto}, |
|
|
|
mem, |
|
|
|
mem, |
|
|
|
}; |
|
|
|
}; |
|
|
|
@ -112,6 +119,20 @@ impl Rooms { |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns the pdu.
|
|
|
|
|
|
|
|
pub fn get_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> { |
|
|
|
|
|
|
|
self.eventid_pduid |
|
|
|
|
|
|
|
.get(event_id.to_string().as_bytes())? |
|
|
|
|
|
|
|
.map_or(Ok(None), |pdu_id| { |
|
|
|
|
|
|
|
Ok(serde_json::from_slice( |
|
|
|
|
|
|
|
&self.pduid_pdu.get(pdu_id)?.ok_or(Error::BadDatabase( |
|
|
|
|
|
|
|
"eventid_pduid points to nonexistent pdu", |
|
|
|
|
|
|
|
))?, |
|
|
|
|
|
|
|
)?) |
|
|
|
|
|
|
|
.map(Some) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Returns the leaf pdus of a room.
|
|
|
|
/// Returns the leaf pdus of a room.
|
|
|
|
pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<Vec<EventId>> { |
|
|
|
pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<Vec<EventId>> { |
|
|
|
let mut prefix = room_id.to_string().as_bytes().to_vec(); |
|
|
|
let mut prefix = room_id.to_string().as_bytes().to_vec(); |
|
|
|
@ -158,41 +179,227 @@ impl Rooms { |
|
|
|
state_key: Option<String>, |
|
|
|
state_key: Option<String>, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
) -> Result<EventId> { |
|
|
|
) -> Result<EventId> { |
|
|
|
|
|
|
|
// TODO: Make sure this isn't called twice in parallel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let prev_events = self.get_pdu_leaves(&room_id)?; |
|
|
|
|
|
|
|
|
|
|
|
// Is the event authorized?
|
|
|
|
// Is the event authorized?
|
|
|
|
if state_key.is_some() { |
|
|
|
if let Some(state_key) = &state_key { |
|
|
|
if let Some(pdu) = self |
|
|
|
let power_levels = self |
|
|
|
.room_state(&room_id)? |
|
|
|
.room_state(&room_id)? |
|
|
|
.get(&(EventType::RoomPowerLevels, "".to_owned())) |
|
|
|
.get(&(EventType::RoomPowerLevels, "".to_owned())) |
|
|
|
|
|
|
|
.map_or_else( |
|
|
|
|
|
|
|
|| { |
|
|
|
|
|
|
|
Ok::<_, Error>(power_levels::PowerLevelsEventContent { |
|
|
|
|
|
|
|
ban: 50.into(), |
|
|
|
|
|
|
|
events: BTreeMap::new(), |
|
|
|
|
|
|
|
events_default: 0.into(), |
|
|
|
|
|
|
|
invite: 50.into(), |
|
|
|
|
|
|
|
kick: 50.into(), |
|
|
|
|
|
|
|
redact: 50.into(), |
|
|
|
|
|
|
|
state_default: 0.into(), |
|
|
|
|
|
|
|
users: BTreeMap::new(), |
|
|
|
|
|
|
|
users_default: 0.into(), |
|
|
|
|
|
|
|
notifications: |
|
|
|
|
|
|
|
ruma_events::room::power_levels::NotificationPowerLevels { |
|
|
|
|
|
|
|
room: 50.into(), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|power_levels| { |
|
|
|
|
|
|
|
Ok( |
|
|
|
|
|
|
|
serde_json::from_value::<EventJson<PowerLevelsEventContent>>( |
|
|
|
|
|
|
|
power_levels.content.clone(), |
|
|
|
|
|
|
|
)? |
|
|
|
|
|
|
|
.deserialize()?, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
)?; |
|
|
|
{ |
|
|
|
{ |
|
|
|
let power_levels = serde_json::from_value::<EventJson<PowerLevelsEventContent>>( |
|
|
|
let sender_membership = self |
|
|
|
|
|
|
|
.room_state(&room_id)? |
|
|
|
|
|
|
|
.get(&(EventType::RoomMember, sender.to_string())) |
|
|
|
|
|
|
|
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { |
|
|
|
|
|
|
|
Ok( |
|
|
|
|
|
|
|
serde_json::from_value::<EventJson<member::MemberEventContent>>( |
|
|
|
pdu.content.clone(), |
|
|
|
pdu.content.clone(), |
|
|
|
)? |
|
|
|
)? |
|
|
|
.deserialize()?; |
|
|
|
.deserialize()? |
|
|
|
|
|
|
|
.membership, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
})?; |
|
|
|
|
|
|
|
|
|
|
|
match event_type { |
|
|
|
let sender_power = power_levels.users.get(&sender).map_or_else( |
|
|
|
|
|
|
|
|| { |
|
|
|
|
|
|
|
if sender_membership != member::MembershipState::Join { |
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
Some(&power_levels.users_default) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
// If it's okay, wrap with Some(_)
|
|
|
|
|
|
|
|
Some, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !match event_type { |
|
|
|
EventType::RoomMember => { |
|
|
|
EventType::RoomMember => { |
|
|
|
// Member events are okay for now (TODO)
|
|
|
|
let target_user_id = UserId::try_from(&**state_key)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let current_membership = self |
|
|
|
|
|
|
|
.room_state(&room_id)? |
|
|
|
|
|
|
|
.get(&(EventType::RoomMember, target_user_id.to_string())) |
|
|
|
|
|
|
|
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { |
|
|
|
|
|
|
|
Ok(serde_json::from_value::< |
|
|
|
|
|
|
|
EventJson<member::MemberEventContent>, |
|
|
|
|
|
|
|
>(pdu.content.clone())? |
|
|
|
|
|
|
|
.deserialize()? |
|
|
|
|
|
|
|
.membership) |
|
|
|
|
|
|
|
})?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let target_membership = serde_json::from_value::< |
|
|
|
|
|
|
|
EventJson<member::MemberEventContent>, |
|
|
|
|
|
|
|
>(content.clone())? |
|
|
|
|
|
|
|
.deserialize()? |
|
|
|
|
|
|
|
.membership; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let target_power = power_levels.users.get(&target_user_id).map_or_else( |
|
|
|
|
|
|
|
|| { |
|
|
|
|
|
|
|
if target_membership != member::MembershipState::Join { |
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
Some(&power_levels.users_default) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
// If it's okay, wrap with Some(_)
|
|
|
|
|
|
|
|
Some, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let join_rules = self |
|
|
|
|
|
|
|
.room_state(&room_id)? |
|
|
|
|
|
|
|
.get(&(EventType::RoomJoinRules, "".to_owned())) |
|
|
|
|
|
|
|
.map_or(join_rules::JoinRule::Public, |pdu| { |
|
|
|
|
|
|
|
serde_json::from_value::< |
|
|
|
|
|
|
|
EventJson<join_rules::JoinRulesEventContent>, |
|
|
|
|
|
|
|
>(pdu.content.clone()) |
|
|
|
|
|
|
|
.unwrap() |
|
|
|
|
|
|
|
.deserialize() |
|
|
|
|
|
|
|
.unwrap() |
|
|
|
|
|
|
|
.join_rule |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if target_membership == member::MembershipState::Join { |
|
|
|
|
|
|
|
let mut prev_events = prev_events.iter(); |
|
|
|
|
|
|
|
let prev_event = self |
|
|
|
|
|
|
|
.get_pdu(prev_events.next().ok_or(Error::BadRequest( |
|
|
|
|
|
|
|
"membership can't be the first event", |
|
|
|
|
|
|
|
))?)? |
|
|
|
|
|
|
|
.ok_or(Error::BadDatabase("pdu leave points to valid event"))?; |
|
|
|
|
|
|
|
if prev_event.kind == EventType::RoomCreate |
|
|
|
|
|
|
|
&& prev_event.prev_events.is_empty() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
true |
|
|
|
|
|
|
|
} else if sender != target_user_id { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else if let member::MembershipState::Ban = current_membership { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else if join_rules == join_rules::JoinRule::Invite |
|
|
|
|
|
|
|
&& (current_membership == member::MembershipState::Join |
|
|
|
|
|
|
|
|| current_membership == member::MembershipState::Invite) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
true |
|
|
|
|
|
|
|
} else if join_rules == join_rules::JoinRule::Public { |
|
|
|
|
|
|
|
true |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if target_membership == member::MembershipState::Invite { |
|
|
|
|
|
|
|
if let Some(third_party_invite_json) = content.get("third_party_invite") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if current_membership == member::MembershipState::Ban { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
let _third_party_invite = |
|
|
|
|
|
|
|
serde_json::from_value::<member::ThirdPartyInvite>( |
|
|
|
|
|
|
|
third_party_invite_json.clone(), |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
todo!("handle third party invites"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if sender_membership != member::MembershipState::Join { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else if current_membership == member::MembershipState::Join |
|
|
|
|
|
|
|
|| current_membership == member::MembershipState::Ban |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else if sender_power |
|
|
|
|
|
|
|
.filter(|&p| p >= &power_levels.invite) |
|
|
|
|
|
|
|
.is_some() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
true |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if target_membership == member::MembershipState::Leave { |
|
|
|
|
|
|
|
if sender == target_user_id { |
|
|
|
|
|
|
|
current_membership == member::MembershipState::Join |
|
|
|
|
|
|
|
|| current_membership == member::MembershipState::Invite |
|
|
|
|
|
|
|
} else if sender_membership != member::MembershipState::Join { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else if current_membership == member::MembershipState::Ban |
|
|
|
|
|
|
|
&& sender_power.filter(|&p| p < &power_levels.ban).is_some() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} else if sender_power.filter(|&p| p >= &power_levels.kick).is_some() |
|
|
|
|
|
|
|
&& target_power < sender_power |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
true |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
false |
|
|
|
} |
|
|
|
} |
|
|
|
_ if power_levels |
|
|
|
} else if target_membership == member::MembershipState::Ban { |
|
|
|
.users |
|
|
|
if sender_membership != member::MembershipState::Join { |
|
|
|
.get(&sender) |
|
|
|
false |
|
|
|
.unwrap_or(&power_levels.users_default) |
|
|
|
} else if sender_power.filter(|&p| p >= &power_levels.ban).is_some() |
|
|
|
<= &0.into() => |
|
|
|
&& target_power < sender_power |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
true |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
EventType::RoomCreate => prev_events.is_empty(), |
|
|
|
|
|
|
|
_ if sender_membership == member::MembershipState::Join => { |
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
sender_power.unwrap_or(&power_levels.users_default) |
|
|
|
|
|
|
|
>= &power_levels.state_default |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_ => false, |
|
|
|
|
|
|
|
} { |
|
|
|
|
|
|
|
error!("Unauthorized"); |
|
|
|
// Not authorized
|
|
|
|
// Not authorized
|
|
|
|
return Err(Error::BadRequest("event not authorized")); |
|
|
|
return Err(Error::BadRequest("event not authorized")); |
|
|
|
} |
|
|
|
} |
|
|
|
// User has sufficient power
|
|
|
|
if event_type == EventType::RoomMember { |
|
|
|
_ => {} |
|
|
|
// TODO: Don't get this twice
|
|
|
|
|
|
|
|
let target_user_id = UserId::try_from(&**state_key)?; |
|
|
|
|
|
|
|
self.update_membership( |
|
|
|
|
|
|
|
&room_id, |
|
|
|
|
|
|
|
&target_user_id, |
|
|
|
|
|
|
|
&serde_json::from_value::<EventJson<member::MemberEventContent>>( |
|
|
|
|
|
|
|
content.clone(), |
|
|
|
|
|
|
|
)? |
|
|
|
|
|
|
|
.deserialize()? |
|
|
|
|
|
|
|
.membership, |
|
|
|
|
|
|
|
)?; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} else if !self.is_joined(&sender, &room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest("event not authorized")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// prev_events are the leaves of the current graph. This method removes all leaves from the
|
|
|
|
|
|
|
|
// room and replaces them with our event
|
|
|
|
|
|
|
|
// TODO: Make sure this isn't called twice in parallel
|
|
|
|
|
|
|
|
let prev_events = self.get_pdu_leaves(&room_id)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Our depth is the maximum depth of prev_events + 1
|
|
|
|
// Our depth is the maximum depth of prev_events + 1
|
|
|
|
let depth = prev_events |
|
|
|
let depth = prev_events |
|
|
|
.iter() |
|
|
|
.iter() |
|
|
|
@ -206,7 +413,7 @@ impl Rooms { |
|
|
|
if let Some(state_key) = &state_key { |
|
|
|
if let Some(state_key) = &state_key { |
|
|
|
if let Some(prev_pdu) = self |
|
|
|
if let Some(prev_pdu) = self |
|
|
|
.room_state(&room_id)? |
|
|
|
.room_state(&room_id)? |
|
|
|
.get(&(event_type.clone(), state_key.clone())) |
|
|
|
.get(&(event_type.clone(), state_key.to_owned())) |
|
|
|
{ |
|
|
|
{ |
|
|
|
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone()); |
|
|
|
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone()); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -348,18 +555,13 @@ impl Rooms { |
|
|
|
.map(|(_, v)| Ok(serde_json::from_slice(&v)?)) |
|
|
|
.map(|(_, v)| Ok(serde_json::from_slice(&v)?)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Makes a user join a room.
|
|
|
|
/// Makes a user join a room. Only call this if the membership is Join already
|
|
|
|
pub fn join( |
|
|
|
fn update_membership( |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
room_id: &RoomId, |
|
|
|
room_id: &RoomId, |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
users: &super::users::Users, |
|
|
|
membership: &member::MembershipState, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
|
|
|
|
) -> Result<()> { |
|
|
|
) -> Result<()> { |
|
|
|
if !self.exists(room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest("room does not exist")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
userroom_id.push(0xff); |
|
|
|
userroom_id.push(0xff); |
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
@ -368,67 +570,30 @@ impl Rooms { |
|
|
|
roomuser_id.push(0xff); |
|
|
|
roomuser_id.push(0xff); |
|
|
|
roomuser_id.extend_from_slice(user_id.to_string().as_bytes()); |
|
|
|
roomuser_id.extend_from_slice(user_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match &membership { |
|
|
|
|
|
|
|
member::MembershipState::Join => { |
|
|
|
self.userroomid_joined.insert(&userroom_id, &[])?; |
|
|
|
self.userroomid_joined.insert(&userroom_id, &[])?; |
|
|
|
self.roomuserid_joined.insert(&roomuser_id, &[])?; |
|
|
|
self.roomuserid_joined.insert(&roomuser_id, &[])?; |
|
|
|
self.userroomid_invited.remove(&userroom_id)?; |
|
|
|
self.userroomid_invited.remove(&userroom_id)?; |
|
|
|
self.roomuserid_invited.remove(&roomuser_id)?; |
|
|
|
self.roomuserid_invited.remove(&roomuser_id)?; |
|
|
|
self.userroomid_left.remove(&userroom_id)?; |
|
|
|
self.userroomid_left.remove(&userroom_id)?; |
|
|
|
|
|
|
|
|
|
|
|
let mut json = serde_json::Map::new(); |
|
|
|
|
|
|
|
json.insert("membership".to_owned(), "join".into()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(displayname) = users.displayname(&user_id).unwrap() { |
|
|
|
|
|
|
|
json.insert("displayname".to_owned(), displayname.into()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
member::MembershipState::Invite => { |
|
|
|
if let Some(avatar_url) = users.avatar_url(&user_id).unwrap() { |
|
|
|
self.userroomid_invited.insert(&userroom_id, &[])?; |
|
|
|
json.insert("avatar_url".to_owned(), avatar_url.into()); |
|
|
|
self.roomuserid_invited.insert(&roomuser_id, &[])?; |
|
|
|
} |
|
|
|
self.userroomid_joined.remove(&userroom_id)?; |
|
|
|
|
|
|
|
self.roomuserid_joined.remove(&roomuser_id)?; |
|
|
|
self.append_pdu( |
|
|
|
self.userroomid_left.remove(&userroom_id)?; |
|
|
|
room_id.clone(), |
|
|
|
|
|
|
|
user_id.clone(), |
|
|
|
|
|
|
|
EventType::RoomMember, |
|
|
|
|
|
|
|
json.into(), |
|
|
|
|
|
|
|
None, |
|
|
|
|
|
|
|
Some(user_id.to_string()), |
|
|
|
|
|
|
|
globals, |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
member::MembershipState::Leave | member::MembershipState::Ban => { |
|
|
|
/// Makes a user leave a room.
|
|
|
|
self.userroomid_left.insert(&userroom_id, &[])?; |
|
|
|
pub fn leave( |
|
|
|
|
|
|
|
&self, |
|
|
|
|
|
|
|
sender: &UserId, |
|
|
|
|
|
|
|
room_id: &RoomId, |
|
|
|
|
|
|
|
user_id: &UserId, |
|
|
|
|
|
|
|
globals: &super::globals::Globals, |
|
|
|
|
|
|
|
) -> Result<()> { |
|
|
|
|
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
userroom_id.push(0xff); |
|
|
|
|
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut roomuser_id = room_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
roomuser_id.push(0xff); |
|
|
|
|
|
|
|
roomuser_id.extend_from_slice(user_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.userroomid_joined.remove(&userroom_id)?; |
|
|
|
self.userroomid_joined.remove(&userroom_id)?; |
|
|
|
self.roomuserid_joined.remove(&roomuser_id)?; |
|
|
|
self.roomuserid_joined.remove(&roomuser_id)?; |
|
|
|
self.userroomid_invited.remove(&userroom_id)?; |
|
|
|
self.userroomid_invited.remove(&userroom_id)?; |
|
|
|
self.roomuserid_invited.remove(&userroom_id)?; |
|
|
|
self.roomuserid_invited.remove(&roomuser_id)?; |
|
|
|
self.userroomid_left.insert(&userroom_id, &[])?; |
|
|
|
} |
|
|
|
|
|
|
|
_ => {} |
|
|
|
self.append_pdu( |
|
|
|
} |
|
|
|
room_id.clone(), |
|
|
|
|
|
|
|
sender.clone(), |
|
|
|
|
|
|
|
EventType::RoomMember, |
|
|
|
|
|
|
|
json!({"membership": "leave"}), |
|
|
|
|
|
|
|
None, |
|
|
|
|
|
|
|
Some(user_id.to_string()), |
|
|
|
|
|
|
|
globals, |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -444,38 +609,6 @@ impl Rooms { |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Makes a user invite another user into room.
|
|
|
|
|
|
|
|
pub fn invite( |
|
|
|
|
|
|
|
&self, |
|
|
|
|
|
|
|
sender: &UserId, |
|
|
|
|
|
|
|
room_id: &RoomId, |
|
|
|
|
|
|
|
user_id: &UserId, |
|
|
|
|
|
|
|
globals: &super::globals::Globals, |
|
|
|
|
|
|
|
) -> Result<()> { |
|
|
|
|
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
userroom_id.push(0xff); |
|
|
|
|
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut roomuser_id = room_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
roomuser_id.push(0xff); |
|
|
|
|
|
|
|
roomuser_id.extend_from_slice(user_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.userroomid_invited.insert(userroom_id, &[])?; |
|
|
|
|
|
|
|
self.roomuserid_invited.insert(roomuser_id, &[])?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.append_pdu( |
|
|
|
|
|
|
|
room_id.clone(), |
|
|
|
|
|
|
|
sender.clone(), |
|
|
|
|
|
|
|
EventType::RoomMember, |
|
|
|
|
|
|
|
json!({"membership": "invite"}), |
|
|
|
|
|
|
|
None, |
|
|
|
|
|
|
|
Some(user_id.to_string()), |
|
|
|
|
|
|
|
globals, |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns an iterator over all rooms a user joined.
|
|
|
|
/// Returns an iterator over all rooms a user joined.
|
|
|
|
pub fn room_members(&self, room_id: &RoomId) -> impl Iterator<Item = Result<UserId>> { |
|
|
|
pub fn room_members(&self, room_id: &RoomId) -> impl Iterator<Item = Result<UserId>> { |
|
|
|
self.roomuserid_joined |
|
|
|
self.roomuserid_joined |
|
|
|
@ -550,4 +683,28 @@ impl Rooms { |
|
|
|
)?)?) |
|
|
|
)?)?) |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn is_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> { |
|
|
|
|
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
userroom_id.push(0xff); |
|
|
|
|
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(self.userroomid_joined.get(userroom_id)?.is_some()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn is_invited(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> { |
|
|
|
|
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
userroom_id.push(0xff); |
|
|
|
|
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(self.userroomid_invited.get(userroom_id)?.is_some()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> { |
|
|
|
|
|
|
|
let mut userroom_id = user_id.to_string().as_bytes().to_vec(); |
|
|
|
|
|
|
|
userroom_id.push(0xff); |
|
|
|
|
|
|
|
userroom_id.extend_from_slice(room_id.to_string().as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(self.userroomid_left.get(userroom_id)?.is_some()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|