diff --git a/src/client_server.rs b/src/client_server.rs index 17218dfc..cf3f67ca 100644 --- a/src/client_server.rs +++ b/src/client_server.rs @@ -487,6 +487,7 @@ pub fn deactivate_route( redacts: None, }, &db.globals, + &db.account_data, )?; } @@ -695,6 +696,7 @@ pub fn set_displayname_route( redacts: None, }, &db.globals, + &db.account_data, )?; // Presence update @@ -797,6 +799,7 @@ pub fn set_avatar_url_route( redacts: None, }, &db.globals, + &db.account_data, )?; // Presence update @@ -1318,6 +1321,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; // 2. Let the room creator join @@ -1339,6 +1343,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; // Figure out preset. We need it for power levels and preset specific events @@ -1387,6 +1392,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; // 4. Events set by preset @@ -1412,6 +1418,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; // 4.2 History Visibility @@ -1429,6 +1436,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; // 4.3 Guest Access @@ -1454,6 +1462,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; // 5. Events listed in initial_state @@ -1481,6 +1490,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; } @@ -1502,6 +1512,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; } @@ -1520,6 +1531,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; } @@ -1543,6 +1555,7 @@ pub fn create_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; } @@ -1602,6 +1615,7 @@ pub fn redact_event_route( redacts: Some(body.event_id.clone()), }, &db.globals, + &db.account_data, )?; Ok(redact_event::Response { event_id }.into()) @@ -1696,6 +1710,7 @@ pub fn join_room_by_id_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(join_room_by_id::Response { @@ -1775,6 +1790,7 @@ pub fn leave_room_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(leave_room::Response.into()) @@ -1821,6 +1837,7 @@ pub fn kick_user_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(kick_user::Response.into()) @@ -1913,6 +1930,7 @@ pub fn ban_user_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(ban_user::Response.into()) @@ -1958,6 +1976,7 @@ pub fn unban_user_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(unban_user::Response.into()) @@ -2007,6 +2026,7 @@ pub fn invite_user_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(invite_user::Response.into()) @@ -2396,6 +2416,7 @@ pub fn create_message_event_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(create_message_event::Response { event_id }.into()) @@ -2461,6 +2482,7 @@ pub fn create_state_event_for_key_route( redacts: None, }, &db.globals, + &db.account_data, )?; Ok(create_state_event_for_key::Response { event_id }.into()) diff --git a/src/database/account_data.rs b/src/database/account_data.rs index 99e0d5c7..a9171235 100644 --- a/src/database/account_data.rs +++ b/src/database/account_data.rs @@ -4,8 +4,7 @@ use ruma::{ events::{AnyEvent as EduEvent, EventType}, Raw, RoomId, UserId, }; -use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{de::DeserializeOwned, Serialize}; use sled::IVec; use std::{collections::HashMap, convert::TryFrom}; diff --git a/src/database/key_backups.rs b/src/database/key_backups.rs index a5065647..5b37f1b0 100644 --- a/src/database/key_backups.rs +++ b/src/database/key_backups.rs @@ -4,7 +4,7 @@ use ruma::{ error::ErrorKind, r0::backup::{BackupAlgorithm, KeyData, Sessions}, }, - {RoomId, UserId}, + RoomId, UserId, }; use std::{collections::BTreeMap, convert::TryFrom}; diff --git a/src/database/rooms.rs b/src/database/rooms.rs index 9ff11b89..fe633180 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -7,6 +7,7 @@ use log::error; use ruma::{ api::client::error::ErrorKind, events::{ + ignored_user_list, room::{ join_rules, member, power_levels::{self, PowerLevelsEventContent}, @@ -255,6 +256,7 @@ impl Rooms { &self, pdu_builder: PduBuilder, globals: &super::globals::Globals, + account_data: &super::account_data::AccountData, ) -> Result { let PduBuilder { room_id, @@ -386,7 +388,7 @@ impl Rooms { .join_rule) })?; - let authorized = if target_membership == member::MembershipState::Join { + 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( @@ -459,19 +461,11 @@ impl Rooms { } } else { false - }; - - if authorized { - // Update our membership info - self.update_membership(&room_id, &target_user_id, &target_membership)?; } - - authorized } EventType::RoomCreate => prev_events.is_empty(), // Not allow any of the following events if the sender is not joined. _ if sender_membership != member::MembershipState::Join => false, - _ => { // TODO sender_power.unwrap_or(&power_levels.users_default) @@ -523,7 +517,7 @@ impl Rooms { .expect("time is valid"), kind: event_type.clone(), content: content.clone(), - state_key, + state_key: state_key.clone(), prev_events, depth: depth .try_into() @@ -579,23 +573,50 @@ impl Rooms { self.roomstateid_pdu.insert(key, &*pdu_json.to_string())?; } - if let EventType::RoomRedaction = event_type { - if let Some(redact_id) = &redacts { - // TODO: Reason - let _reason = - serde_json::from_value::>(content) - .expect("Raw::from_value always works.") - .deserialize() - .map_err(|_| { - Error::BadRequest( - ErrorKind::InvalidParam, - "Invalid redaction event content.", - ) - })? - .reason; - - self.redact_pdu(&redact_id)?; + match event_type { + EventType::RoomRedaction => { + if let Some(redact_id) = &redacts { + // TODO: Reason + let _reason = + serde_json::from_value::>(content) + .expect("Raw::from_value always works.") + .deserialize() + .map_err(|_| { + Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid redaction event content.", + ) + })? + .reason; + + self.redact_pdu(&redact_id)?; + } } + EventType::RoomMember => { + if let Some(state_key) = state_key { + // if the state_key fails + let target_user_id = UserId::try_from(state_key) + .expect("This state_key was previously validated"); + // Update our membership info, we do this here incase a user is invited + // and immediately leaves we need the DB to record the invite event for auth + self.update_membership( + &room_id, + &target_user_id, + serde_json::from_value::(content).map_err( + |_| { + Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid redaction event content.", + ) + }, + )?, + &sender, + account_data, + globals, + )?; + } + } + _ => {} } self.edus.room_read_set(&room_id, &sender, index)?; @@ -741,8 +762,12 @@ impl Rooms { &self, room_id: &RoomId, user_id: &UserId, - membership: &member::MembershipState, + mut member_content: member::MemberEventContent, + sender: &UserId, + account_data: &super::account_data::AccountData, + globals: &super::globals::Globals, ) -> Result<()> { + let membership = member_content.membership; 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()); @@ -760,6 +785,37 @@ impl Rooms { self.userroomid_left.remove(&userroom_id)?; } member::MembershipState::Invite => { + // We want to know if the sender is ignored by the receiver + let is_ignored = account_data + .get::( + None, // Ignored users are in global account data + &user_id, // Receiver + EventType::IgnoredUserList, + )? + .map_or(false, |ignored| { + ignored.content.ignored_users.contains(&sender) + }); + + if is_ignored { + member_content.membership = member::MembershipState::Leave; + + self.append_pdu( + PduBuilder { + room_id: room_id.clone(), + sender: user_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(member_content) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, + globals, + account_data, + )?; + + return Ok(()); + } self.userroomid_invited.insert(&userroom_id, &[])?; self.roomuserid_invited.insert(&roomuser_id, &[])?; self.userroomid_joined.remove(&userroom_id)?;