1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-08-01 17:38:36 +00:00
conduit/src/service/rooms/state_cache/mod.rs

356 lines
13 KiB
Rust
Raw Normal View History

mod data;
use std::{collections::HashSet, sync::Arc};
pub use data::Data;
2022-10-05 20:41:05 +02:00
2022-10-05 18:36:12 +02:00
use ruma::{
events::{
2022-10-08 13:03:07 +02:00
direct::DirectEvent,
2022-10-05 18:36:12 +02:00
ignored_user_list::IgnoredUserListEvent,
room::{create::RoomCreateEventContent, member::MembershipState},
2022-10-08 13:03:07 +02:00
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
RoomAccountDataEventType, StateEventType,
2022-10-05 18:36:12 +02:00
},
serde::Raw,
2022-10-09 17:25:06 +02:00
OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId,
2022-10-05 18:36:12 +02:00
};
use tracing::warn;
2022-10-05 18:36:12 +02:00
use crate::{service::appservice::RegistrationInfo, services, Error, Result};
2022-10-05 12:45:54 +02:00
pub struct Service {
2022-10-08 13:02:52 +02:00
pub db: &'static dyn Data,
}
2022-10-05 12:45:54 +02:00
impl Service {
2020-05-26 10:27:51 +02:00
/// Update current membership data.
#[tracing::instrument(skip(self, last_state))]
pub fn update_membership(
&self,
room_id: &RoomId,
user_id: &UserId,
membership: MembershipState,
sender: &UserId,
2021-04-13 15:00:45 +02:00
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
2021-08-17 00:22:52 +02:00
update_joined_count: bool,
) -> Result<()> {
// Keep track what remote users exist by adding them as "deactivated" users
2022-09-07 13:25:51 +02:00
if user_id.server_name() != services().globals.server_name() {
services().users.create(user_id, None)?;
// TODO: displayname, avatar url
}
2020-05-24 18:25:52 +02:00
match &membership {
MembershipState::Join => {
2020-08-06 13:21:53 +02:00
// Check if the user never joined this room
if !self.once_joined(user_id, room_id)? {
2020-08-06 13:21:53 +02:00
// Add the user ID to the join list then
self.db.mark_as_once_joined(user_id, room_id)?;
2020-08-06 13:21:53 +02:00
// Check if the room has a predecessor
2022-10-05 18:36:12 +02:00
if let Some(predecessor) = services()
.rooms
.state_accessor
2022-04-06 21:31:29 +02:00
.room_state_get(room_id, &StateEventType::RoomCreate, "")?
.and_then(|create| serde_json::from_str(create.content.get()).ok())
.and_then(|content: RoomCreateEventContent| content.predecessor)
2020-08-06 13:21:53 +02:00
{
// Copy user settings from predecessor to the current room:
// - Push rules
//
// TODO: finish this once push rules are implemented.
//
// let mut push_rules_event_content: PushRulesEvent = account_data
// .get(
2020-08-06 13:21:53 +02:00
// None,
// user_id,
// EventType::PushRules,
// )?;
//
// NOTE: find where `predecessor.room_id` match
// and update to `room_id`.
//
// account_data
// .update(
// None,
// user_id,
// EventType::PushRules,
// &push_rules_event_content,
// globals,
// )
// .ok();
2020-09-01 13:07:32 +02:00
// Copy old tags to new room
2022-10-05 18:36:12 +02:00
if let Some(tag_event) = services()
.account_data
.get(
Some(&predecessor.room_id),
user_id,
RoomAccountDataEventType::Tag,
)?
.map(|event| {
serde_json::from_str(event.get()).map_err(|e| {
warn!("Invalid account data event in db: {e:?}");
Error::BadDatabase("Invalid account data event in db.")
2022-10-05 20:34:31 +02:00
})
2022-10-05 18:36:12 +02:00
})
{
services()
.account_data
2021-04-14 10:43:31 +02:00
.update(
Some(room_id),
user_id,
2022-04-06 21:31:29 +02:00
RoomAccountDataEventType::Tag,
2022-10-05 18:36:12 +02:00
&tag_event?,
2021-04-14 10:43:31 +02:00
)
2020-08-06 13:21:53 +02:00
.ok();
};
2020-09-01 13:07:32 +02:00
// Copy direct chat flag
2022-10-08 13:02:52 +02:00
if let Some(direct_event) = services()
2022-10-05 20:34:31 +02:00
.account_data
.get(
None,
user_id,
GlobalAccountDataEventType::Direct.to_string().into(),
)?
2022-10-05 18:36:12 +02:00
.map(|event| {
serde_json::from_str::<DirectEvent>(event.get()).map_err(|e| {
warn!("Invalid account data event in db: {e:?}");
Error::BadDatabase("Invalid account data event in db.")
2022-10-05 20:34:31 +02:00
})
2022-10-05 18:36:12 +02:00
})
2022-10-05 20:34:31 +02:00
{
2022-10-08 13:02:52 +02:00
let mut direct_event = direct_event?;
2020-08-06 13:21:53 +02:00
let mut room_ids_updated = false;
2020-09-01 13:07:32 +02:00
for room_ids in direct_event.content.0.values_mut() {
2020-08-06 13:21:53 +02:00
if room_ids.iter().any(|r| r == &predecessor.room_id) {
2021-11-26 20:36:40 +01:00
room_ids.push(room_id.to_owned());
2020-08-06 13:21:53 +02:00
room_ids_updated = true;
}
}
if room_ids_updated {
2022-09-07 13:25:51 +02:00
services().account_data.update(
2020-09-01 13:07:32 +02:00
None,
user_id,
2022-04-06 21:31:29 +02:00
GlobalAccountDataEventType::Direct.to_string().into(),
2022-10-05 20:34:31 +02:00
&serde_json::to_value(&direct_event)
.expect("to json always works"),
2020-09-01 13:07:32 +02:00
)?;
2020-08-06 13:21:53 +02:00
}
};
}
}
2022-09-07 13:25:51 +02:00
self.db.mark_as_joined(user_id, room_id)?;
2020-05-24 18:25:52 +02:00
}
MembershipState::Invite => {
// We want to know if the sender is ignored by the receiver
2022-09-07 13:25:51 +02:00
let is_ignored = services()
2021-04-14 10:43:31 +02:00
.account_data
2022-10-05 18:36:12 +02:00
.get(
None, // Ignored users are in global account data
user_id, // Receiver
2022-04-06 21:31:29 +02:00
GlobalAccountDataEventType::IgnoredUserList
.to_string()
.into(),
)?
2022-10-05 20:34:31 +02:00
.map(|event| {
serde_json::from_str::<IgnoredUserListEvent>(event.get()).map_err(|e| {
warn!("Invalid account data event in db: {e:?}");
Error::BadDatabase("Invalid account data event in db.")
})
2022-10-05 20:34:31 +02:00
})
.transpose()?
.map_or(false, |ignored| {
2021-11-26 20:36:40 +01:00
ignored
.content
.ignored_users
.iter()
2022-12-17 09:21:19 +01:00
.any(|(user, _details)| user == sender)
});
if is_ignored {
return Ok(());
}
2020-09-14 20:23:19 +02:00
2022-09-07 13:25:51 +02:00
self.db.mark_as_invited(user_id, room_id, last_state)?;
2020-05-24 18:25:52 +02:00
}
MembershipState::Leave | MembershipState::Ban => {
2022-09-07 13:25:51 +02:00
self.db.mark_as_left(user_id, room_id)?;
2020-05-24 18:25:52 +02:00
}
_ => {}
}
2021-08-17 00:22:52 +02:00
if update_joined_count {
2022-09-07 13:25:51 +02:00
self.update_joined_count(room_id)?;
2021-08-17 00:22:52 +02:00
}
Ok(())
}
2022-09-07 13:25:51 +02:00
#[tracing::instrument(skip(self, room_id))]
pub fn update_joined_count(&self, room_id: &RoomId) -> Result<()> {
2022-10-05 20:33:55 +02:00
self.db.update_joined_count(room_id)
}
#[tracing::instrument(skip(self, room_id))]
2022-10-09 17:25:06 +02:00
pub fn get_our_real_users(&self, room_id: &RoomId) -> Result<Arc<HashSet<OwnedUserId>>> {
2022-10-05 20:33:55 +02:00
self.db.get_our_real_users(room_id)
2021-08-28 11:39:33 +02:00
}
#[tracing::instrument(skip(self, room_id, appservice))]
2021-08-29 20:00:02 +02:00
pub fn appservice_in_room(
&self,
room_id: &RoomId,
appservice: &RegistrationInfo,
2021-08-29 20:00:02 +02:00
) -> Result<bool> {
2022-10-05 20:33:55 +02:00
self.db.appservice_in_room(room_id, appservice)
2021-08-29 20:00:02 +02:00
}
/// Makes a user forget a room.
#[tracing::instrument(skip(self))]
pub fn forget(&self, room_id: &RoomId, user_id: &UserId) -> Result<()> {
2022-10-05 20:33:55 +02:00
self.db.forget(room_id, user_id)
}
/// Returns an iterator of all servers participating in this room.
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn room_servers<'a>(
&'a self,
room_id: &RoomId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<OwnedServerName>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.room_servers(room_id)
2020-09-14 20:23:19 +02:00
}
2021-08-31 19:14:37 +02:00
#[tracing::instrument(skip(self))]
pub fn server_in_room<'a>(&'a self, server: &ServerName, room_id: &RoomId) -> Result<bool> {
2022-10-05 20:33:55 +02:00
self.db.server_in_room(server, room_id)
2021-08-31 19:14:37 +02:00
}
/// Returns an iterator of all rooms a server participates in (as far as we know).
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn server_rooms<'a>(
&'a self,
server: &ServerName,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<OwnedRoomId>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.server_rooms(server)
}
/// Returns an iterator over all joined members of a room.
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn room_members<'a>(
&'a self,
room_id: &RoomId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<OwnedUserId>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.room_members(room_id)
}
/// Returns the number of users which are currently in a room
#[tracing::instrument(skip(self))]
pub fn room_joined_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
2022-10-05 20:33:55 +02:00
self.db.room_joined_count(room_id)
}
/// Returns the number of users which are currently invited to a room
2021-08-28 11:39:33 +02:00
#[tracing::instrument(skip(self))]
pub fn room_invited_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
2022-10-05 20:33:55 +02:00
self.db.room_invited_count(room_id)
2021-08-28 11:39:33 +02:00
}
2020-08-06 13:21:53 +02:00
/// Returns an iterator over all User IDs who ever joined a room.
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn room_useroncejoined<'a>(
&'a self,
room_id: &RoomId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<OwnedUserId>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.room_useroncejoined(room_id)
2020-08-06 13:21:53 +02:00
}
/// Returns an iterator over all invited members of a room.
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn room_members_invited<'a>(
&'a self,
room_id: &RoomId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<OwnedUserId>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.room_members_invited(room_id)
}
2021-04-11 21:01:27 +02:00
#[tracing::instrument(skip(self))]
pub fn get_invite_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
2022-10-05 20:33:55 +02:00
self.db.get_invite_count(room_id, user_id)
2021-04-11 21:01:27 +02:00
}
2021-04-13 15:00:45 +02:00
#[tracing::instrument(skip(self))]
pub fn get_left_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
2022-10-05 20:33:55 +02:00
self.db.get_left_count(room_id, user_id)
2021-04-13 15:00:45 +02:00
}
/// Returns an iterator over all rooms this user joined.
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn rooms_joined<'a>(
&'a self,
user_id: &UserId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<OwnedRoomId>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.rooms_joined(user_id)
}
/// Returns an iterator over all rooms a user was invited to.
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn rooms_invited<'a>(
&'a self,
2021-04-11 21:01:27 +02:00
user_id: &UserId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<(OwnedRoomId, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.rooms_invited(user_id)
}
2021-04-13 15:00:45 +02:00
#[tracing::instrument(skip(self))]
pub fn invite_state(
&self,
user_id: &UserId,
room_id: &RoomId,
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
2022-10-05 20:33:55 +02:00
self.db.invite_state(user_id, room_id)
2021-04-13 15:00:45 +02:00
}
#[tracing::instrument(skip(self))]
pub fn left_state(
&self,
user_id: &UserId,
room_id: &RoomId,
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
2022-10-05 20:33:55 +02:00
self.db.left_state(user_id, room_id)
2021-04-13 15:00:45 +02:00
}
/// Returns an iterator over all rooms a user left.
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(self))]
2021-06-08 18:10:00 +02:00
pub fn rooms_left<'a>(
&'a self,
2021-04-13 15:00:45 +02:00
user_id: &UserId,
2022-10-09 17:25:06 +02:00
) -> impl Iterator<Item = Result<(OwnedRoomId, Vec<Raw<AnySyncStateEvent>>)>> + 'a {
2022-10-05 20:33:55 +02:00
self.db.rooms_left(user_id)
}
2020-05-24 18:25:52 +02:00
#[tracing::instrument(skip(self))]
2020-08-06 13:21:53 +02:00
pub fn once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
2022-10-05 20:33:55 +02:00
self.db.once_joined(user_id, room_id)
2020-08-06 13:21:53 +02:00
}
#[tracing::instrument(skip(self))]
2020-05-24 18:25:52 +02:00
pub fn is_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
2022-10-05 20:33:55 +02:00
self.db.is_joined(user_id, room_id)
2020-05-24 18:25:52 +02:00
}
#[tracing::instrument(skip(self))]
2020-05-24 18:25:52 +02:00
pub fn is_invited(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
2022-10-05 20:33:55 +02:00
self.db.is_invited(user_id, room_id)
2020-05-24 18:25:52 +02:00
}
#[tracing::instrument(skip(self))]
2020-05-24 18:25:52 +02:00
pub fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
2022-10-05 20:33:55 +02:00
self.db.is_left(user_id, room_id)
2020-05-24 18:25:52 +02:00
}
}