mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 07:41:23 +01:00
change rustfmt configuration
This change is fully automated, except the `rustfmt.toml` changes and a few clippy directives to allow specific functions with too many lines because they are longer now.
This commit is contained in:
parent
40d6ce230d
commit
0afc1d2f50
123 changed files with 7881 additions and 4687 deletions
|
|
@ -7,29 +7,31 @@ use std::{
|
|||
};
|
||||
|
||||
pub(crate) use data::Data;
|
||||
|
||||
use ruma::{
|
||||
api::{client::error::ErrorKind, federation},
|
||||
canonical_json::to_canonical_value,
|
||||
events::{
|
||||
push_rules::PushRulesEvent,
|
||||
room::{
|
||||
create::RoomCreateEventContent, encrypted::Relation, member::MembershipState,
|
||||
power_levels::RoomPowerLevelsEventContent, redaction::RoomRedactionEventContent,
|
||||
create::RoomCreateEventContent, encrypted::Relation,
|
||||
member::MembershipState, power_levels::RoomPowerLevelsEventContent,
|
||||
redaction::RoomRedactionEventContent,
|
||||
},
|
||||
GlobalAccountDataEventType, StateEventType, TimelineEventType,
|
||||
},
|
||||
push::{Action, Ruleset, Tweak},
|
||||
serde::Base64,
|
||||
state_res::{self, Event, RoomVersion},
|
||||
uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId,
|
||||
OwnedServerName, RoomId, RoomVersionId, ServerName, UserId,
|
||||
uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId,
|
||||
OwnedEventId, OwnedRoomId, OwnedServerName, RoomId, RoomVersionId,
|
||||
ServerName, UserId,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
|
||||
use tokio::sync::{Mutex, MutexGuard, RwLock};
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
use super::state_compressor::CompressedStateEvent;
|
||||
use crate::{
|
||||
api::server_server,
|
||||
service::{
|
||||
|
|
@ -39,8 +41,6 @@ use crate::{
|
|||
services, utils, Error, PduEvent, Result,
|
||||
};
|
||||
|
||||
use super::state_compressor::CompressedStateEvent;
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub(crate) enum PduCount {
|
||||
Backfilled(u64),
|
||||
|
|
@ -48,8 +48,8 @@ pub(crate) enum PduCount {
|
|||
}
|
||||
|
||||
impl PduCount {
|
||||
pub(crate) const MIN: Self = Self::Backfilled(u64::MAX);
|
||||
pub(crate) const MAX: Self = Self::Normal(u64::MAX);
|
||||
pub(crate) const MIN: Self = Self::Backfilled(u64::MAX);
|
||||
|
||||
pub(crate) fn try_from_string(token: &str) -> Result<Self> {
|
||||
if let Some(stripped) = token.strip_prefix('-') {
|
||||
|
|
@ -57,7 +57,12 @@ impl PduCount {
|
|||
} else {
|
||||
token.parse().map(PduCount::Normal)
|
||||
}
|
||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid pagination token."))
|
||||
.map_err(|_| {
|
||||
Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Invalid pagination token.",
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn stringify(&self) -> String {
|
||||
|
|
@ -93,7 +98,10 @@ pub(crate) struct Service {
|
|||
|
||||
impl Service {
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(crate) fn first_pdu_in_room(&self, room_id: &RoomId) -> Result<Option<Arc<PduEvent>>> {
|
||||
pub(crate) fn first_pdu_in_room(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
) -> Result<Option<Arc<PduEvent>>> {
|
||||
self.all_pdus(user_id!("@doesntmatter:grapevine"), room_id)?
|
||||
.next()
|
||||
.map(|o| o.map(|(_, p)| Arc::new(p)))
|
||||
|
|
@ -110,12 +118,18 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Returns the `count` of this pdu's id.
|
||||
pub(crate) fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<PduCount>> {
|
||||
pub(crate) fn get_pdu_count(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<Option<PduCount>> {
|
||||
self.db.get_pdu_count(event_id)
|
||||
}
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
pub(crate) fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
pub(crate) fn get_pdu_json(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<Option<CanonicalJsonObject>> {
|
||||
self.db.get_pdu_json(event_id)
|
||||
}
|
||||
|
||||
|
|
@ -128,21 +142,30 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Returns the pdu's id.
|
||||
pub(crate) fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>> {
|
||||
pub(crate) fn get_pdu_id(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
self.db.get_pdu_id(event_id)
|
||||
}
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||
pub(crate) fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
||||
pub(crate) fn get_pdu(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<Option<Arc<PduEvent>>> {
|
||||
self.db.get_pdu(event_id)
|
||||
}
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// This does __NOT__ check the outliers `Tree`.
|
||||
pub(crate) fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>> {
|
||||
pub(crate) fn get_pdu_from_id(
|
||||
&self,
|
||||
pdu_id: &[u8],
|
||||
) -> Result<Option<PduEvent>> {
|
||||
self.db.get_pdu_from_id(pdu_id)
|
||||
}
|
||||
|
||||
|
|
@ -167,8 +190,8 @@ impl Service {
|
|||
|
||||
/// Creates a new persisted data unit and adds it to a room.
|
||||
///
|
||||
/// By this point the incoming event should be fully authenticated, no auth happens
|
||||
/// in `append_pdu`.
|
||||
/// By this point the incoming event should be fully authenticated, no auth
|
||||
/// happens in `append_pdu`.
|
||||
///
|
||||
/// Returns pdu id
|
||||
#[tracing::instrument(skip(self, pdu, pdu_json, leaves))]
|
||||
|
|
@ -186,13 +209,15 @@ impl Service {
|
|||
.get_shortroomid(&pdu.room_id)?
|
||||
.expect("room exists");
|
||||
|
||||
// Make unsigned fields correct. This is not properly documented in the spec, but state
|
||||
// events need to have previous content in the unsigned field, so clients can easily
|
||||
// interpret things like membership changes
|
||||
// Make unsigned fields correct. This is not properly documented in the
|
||||
// spec, but state events need to have previous content in the
|
||||
// unsigned field, so clients can easily interpret things like
|
||||
// membership changes
|
||||
if let Some(state_key) = &pdu.state_key {
|
||||
if let CanonicalJsonValue::Object(unsigned) = pdu_json
|
||||
.entry("unsigned".to_owned())
|
||||
.or_insert_with(|| CanonicalJsonValue::Object(CanonicalJsonObject::default()))
|
||||
if let CanonicalJsonValue::Object(unsigned) =
|
||||
pdu_json.entry("unsigned".to_owned()).or_insert_with(|| {
|
||||
CanonicalJsonValue::Object(CanonicalJsonObject::default())
|
||||
})
|
||||
{
|
||||
if let Some(shortstatehash) = services()
|
||||
.rooms
|
||||
|
|
@ -203,14 +228,20 @@ impl Service {
|
|||
if let Some(prev_state) = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.state_get(shortstatehash, &pdu.kind.to_string().into(), state_key)
|
||||
.state_get(
|
||||
shortstatehash,
|
||||
&pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
)
|
||||
.unwrap()
|
||||
{
|
||||
unsigned.insert(
|
||||
"prev_content".to_owned(),
|
||||
CanonicalJsonValue::Object(
|
||||
utils::to_canonical_object(prev_state.content.clone())
|
||||
.expect("event is valid, we just created it"),
|
||||
utils::to_canonical_object(
|
||||
prev_state.content.clone(),
|
||||
)
|
||||
.expect("event is valid, we just created it"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -225,10 +256,11 @@ impl Service {
|
|||
.rooms
|
||||
.pdu_metadata
|
||||
.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
||||
services()
|
||||
.rooms
|
||||
.state
|
||||
.set_forward_extremities(&pdu.room_id, leaves, state_lock)?;
|
||||
services().rooms.state.set_forward_extremities(
|
||||
&pdu.room_id,
|
||||
leaves,
|
||||
state_lock,
|
||||
)?;
|
||||
|
||||
let mutex_insert = Arc::clone(
|
||||
services()
|
||||
|
|
@ -242,13 +274,13 @@ impl Service {
|
|||
let insert_lock = mutex_insert.lock().await;
|
||||
|
||||
let count1 = services().globals.next_count()?;
|
||||
// Mark as read first so the sending client doesn't get a notification even if appending
|
||||
// fails
|
||||
services()
|
||||
.rooms
|
||||
.edus
|
||||
.read_receipt
|
||||
.private_read_set(&pdu.room_id, &pdu.sender, count1)?;
|
||||
// Mark as read first so the sending client doesn't get a notification
|
||||
// even if appending fails
|
||||
services().rooms.edus.read_receipt.private_read_set(
|
||||
&pdu.room_id,
|
||||
&pdu.sender,
|
||||
count1,
|
||||
)?;
|
||||
services()
|
||||
.rooms
|
||||
.user
|
||||
|
|
@ -269,8 +301,9 @@ impl Service {
|
|||
.state_accessor
|
||||
.room_state_get(&pdu.room_id, &StateEventType::RoomPowerLevels, "")?
|
||||
.map(|ev| {
|
||||
serde_json::from_str(ev.content.get())
|
||||
.map_err(|_| Error::bad_database("invalid m.room.power_levels event"))
|
||||
serde_json::from_str(ev.content.get()).map_err(|_| {
|
||||
Error::bad_database("invalid m.room.power_levels event")
|
||||
})
|
||||
})
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
|
|
@ -280,10 +313,8 @@ impl Service {
|
|||
let mut notifies = Vec::new();
|
||||
let mut highlights = Vec::new();
|
||||
|
||||
let mut push_target = services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_our_real_users(&pdu.room_id)?;
|
||||
let mut push_target =
|
||||
services().rooms.state_cache.get_our_real_users(&pdu.room_id)?;
|
||||
|
||||
if pdu.kind == TimelineEventType::RoomMember {
|
||||
if let Some(state_key) = &pdu.state_key {
|
||||
|
|
@ -312,8 +343,13 @@ impl Service {
|
|||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
||||
)?
|
||||
.map(|event| {
|
||||
serde_json::from_str::<PushRulesEvent>(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid push rules event in db."))
|
||||
serde_json::from_str::<PushRulesEvent>(event.get()).map_err(
|
||||
|_| {
|
||||
Error::bad_database(
|
||||
"Invalid push rules event in db.",
|
||||
)
|
||||
},
|
||||
)
|
||||
})
|
||||
.transpose()?
|
||||
.map_or_else(
|
||||
|
|
@ -353,12 +389,16 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
self.db
|
||||
.increment_notification_counts(&pdu.room_id, notifies, highlights)?;
|
||||
self.db.increment_notification_counts(
|
||||
&pdu.room_id,
|
||||
notifies,
|
||||
highlights,
|
||||
)?;
|
||||
|
||||
match pdu.kind {
|
||||
TimelineEventType::RoomRedaction => {
|
||||
let room_version_id = services().rooms.state.get_room_version(&pdu.room_id)?;
|
||||
let room_version_id =
|
||||
services().rooms.state.get_room_version(&pdu.room_id)?;
|
||||
match room_version_id {
|
||||
RoomVersionId::V1
|
||||
| RoomVersionId::V2
|
||||
|
|
@ -383,10 +423,14 @@ impl Service {
|
|||
}
|
||||
RoomVersionId::V11 => {
|
||||
let content =
|
||||
serde_json::from_str::<RoomRedactionEventContent>(pdu.content.get())
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in redaction pdu.")
|
||||
})?;
|
||||
serde_json::from_str::<RoomRedactionEventContent>(
|
||||
pdu.content.get(),
|
||||
)
|
||||
.map_err(|_| {
|
||||
Error::bad_database(
|
||||
"Invalid content in redaction pdu.",
|
||||
)
|
||||
})?;
|
||||
if let Some(redact_id) = &content.redacts {
|
||||
if services().rooms.state_accessor.user_can_redact(
|
||||
redact_id,
|
||||
|
|
@ -398,7 +442,9 @@ impl Service {
|
|||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!("Validity of room version already checked"),
|
||||
_ => {
|
||||
unreachable!("Validity of room version already checked")
|
||||
}
|
||||
};
|
||||
}
|
||||
TimelineEventType::SpaceChild => {
|
||||
|
|
@ -423,19 +469,27 @@ impl Service {
|
|||
let target_user_id = UserId::parse(state_key.clone())
|
||||
.expect("This state_key was previously validated");
|
||||
|
||||
let content = serde_json::from_str::<ExtractMembership>(pdu.content.get())
|
||||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||
let content = serde_json::from_str::<ExtractMembership>(
|
||||
pdu.content.get(),
|
||||
)
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in pdu.")
|
||||
})?;
|
||||
|
||||
let invite_state = match content.membership {
|
||||
MembershipState::Invite => {
|
||||
let state = services().rooms.state.calculate_invite_state(pdu)?;
|
||||
let state = services()
|
||||
.rooms
|
||||
.state
|
||||
.calculate_invite_state(pdu)?;
|
||||
Some(state)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// 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
|
||||
// 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
|
||||
services().rooms.state_cache.update_membership(
|
||||
&pdu.room_id,
|
||||
&target_user_id,
|
||||
|
|
@ -452,14 +506,18 @@ impl Service {
|
|||
body: Option<String>,
|
||||
}
|
||||
|
||||
let content = serde_json::from_str::<ExtractBody>(pdu.content.get())
|
||||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||
let content =
|
||||
serde_json::from_str::<ExtractBody>(pdu.content.get())
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in pdu.")
|
||||
})?;
|
||||
|
||||
if let Some(body) = content.body {
|
||||
services()
|
||||
.rooms
|
||||
.search
|
||||
.index_pdu(shortroomid, &pdu_id, &body)?;
|
||||
services().rooms.search.index_pdu(
|
||||
shortroomid,
|
||||
&pdu_id,
|
||||
&body,
|
||||
)?;
|
||||
|
||||
let server_user = format!(
|
||||
"@{}:{}",
|
||||
|
|
@ -471,18 +529,25 @@ impl Service {
|
|||
services().globals.server_name()
|
||||
);
|
||||
|
||||
let to_grapevine = body.starts_with(&format!("{server_user}: "))
|
||||
let to_grapevine = body
|
||||
.starts_with(&format!("{server_user}: "))
|
||||
|| body.starts_with(&format!("{server_user} "))
|
||||
|| body == format!("{server_user}:")
|
||||
|| body == server_user;
|
||||
|
||||
// This will evaluate to false if the emergency password is set up so that
|
||||
// the administrator can execute commands as grapevine
|
||||
// This will evaluate to false if the emergency password is
|
||||
// set up so that the administrator can
|
||||
// execute commands as grapevine
|
||||
let from_grapevine = pdu.sender == server_user
|
||||
&& services().globals.emergency_password().is_none();
|
||||
|
||||
if let Some(admin_room) = services().admin.get_admin_room()? {
|
||||
if to_grapevine && !from_grapevine && admin_room == pdu.room_id {
|
||||
if let Some(admin_room) =
|
||||
services().admin.get_admin_room()?
|
||||
{
|
||||
if to_grapevine
|
||||
&& !from_grapevine
|
||||
&& admin_room == pdu.room_id
|
||||
{
|
||||
services().admin.process_message(body);
|
||||
}
|
||||
}
|
||||
|
|
@ -493,7 +558,9 @@ impl Service {
|
|||
|
||||
// Update Relationships
|
||||
|
||||
if let Ok(content) = serde_json::from_str::<ExtractRelatesToEventId>(pdu.content.get()) {
|
||||
if let Ok(content) =
|
||||
serde_json::from_str::<ExtractRelatesToEventId>(pdu.content.get())
|
||||
{
|
||||
if let Some(related_pducount) = services()
|
||||
.rooms
|
||||
.timeline
|
||||
|
|
@ -506,9 +573,13 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
if let Ok(content) = serde_json::from_str::<ExtractRelatesTo>(pdu.content.get()) {
|
||||
if let Ok(content) =
|
||||
serde_json::from_str::<ExtractRelatesTo>(pdu.content.get())
|
||||
{
|
||||
match content.relates_to {
|
||||
Relation::Reply { in_reply_to } => {
|
||||
Relation::Reply {
|
||||
in_reply_to,
|
||||
} => {
|
||||
// We need to do it again here, because replies don't have
|
||||
// event_id as a top level field
|
||||
if let Some(related_pducount) = services()
|
||||
|
|
@ -516,10 +587,10 @@ impl Service {
|
|||
.timeline
|
||||
.get_pdu_count(&in_reply_to.event_id)?
|
||||
{
|
||||
services()
|
||||
.rooms
|
||||
.pdu_metadata
|
||||
.add_relation(PduCount::Normal(count2), related_pducount)?;
|
||||
services().rooms.pdu_metadata.add_relation(
|
||||
PduCount::Normal(count2),
|
||||
related_pducount,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Relation::Thread(thread) => {
|
||||
|
|
@ -539,21 +610,24 @@ impl Service {
|
|||
.state_cache
|
||||
.appservice_in_room(&pdu.room_id, appservice)?
|
||||
{
|
||||
services()
|
||||
.sending
|
||||
.send_pdu_appservice(appservice.registration.id.clone(), pdu_id.clone())?;
|
||||
services().sending.send_pdu_appservice(
|
||||
appservice.registration.id.clone(),
|
||||
pdu_id.clone(),
|
||||
)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the RoomMember event has a non-empty state_key, it is targeted at someone.
|
||||
// If it is our appservice user, we send this PDU to it.
|
||||
// If the RoomMember event has a non-empty state_key, it is targeted
|
||||
// at someone. If it is our appservice user, we send
|
||||
// this PDU to it.
|
||||
if pdu.kind == TimelineEventType::RoomMember {
|
||||
if let Some(state_key_uid) = &pdu
|
||||
.state_key
|
||||
.as_ref()
|
||||
.and_then(|state_key| UserId::parse(state_key.as_str()).ok())
|
||||
if let Some(state_key_uid) =
|
||||
&pdu.state_key.as_ref().and_then(|state_key| {
|
||||
UserId::parse(state_key.as_str()).ok()
|
||||
})
|
||||
{
|
||||
let appservice_uid = appservice.registration.sender_localpart.as_str();
|
||||
let appservice_uid =
|
||||
appservice.registration.sender_localpart.as_str();
|
||||
if state_key_uid == appservice_uid {
|
||||
services().sending.send_pdu_appservice(
|
||||
appservice.registration.id.clone(),
|
||||
|
|
@ -567,10 +641,9 @@ impl Service {
|
|||
let matching_users = |users: &NamespaceRegex| {
|
||||
appservice.users.is_match(pdu.sender.as_str())
|
||||
|| pdu.kind == TimelineEventType::RoomMember
|
||||
&& pdu
|
||||
.state_key
|
||||
.as_ref()
|
||||
.map_or(false, |state_key| users.is_match(state_key))
|
||||
&& pdu.state_key.as_ref().map_or(false, |state_key| {
|
||||
users.is_match(state_key)
|
||||
})
|
||||
};
|
||||
let matching_aliases = |aliases: &NamespaceRegex| {
|
||||
services()
|
||||
|
|
@ -585,9 +658,10 @@ impl Service {
|
|||
|| appservice.rooms.is_match(pdu.room_id.as_str())
|
||||
|| matching_users(&appservice.users)
|
||||
{
|
||||
services()
|
||||
.sending
|
||||
.send_pdu_appservice(appservice.registration.id.clone(), pdu_id.clone())?;
|
||||
services().sending.send_pdu_appservice(
|
||||
appservice.registration.id.clone(),
|
||||
pdu_id.clone(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -620,13 +694,13 @@ impl Service {
|
|||
.collect();
|
||||
|
||||
// If there was no create event yet, assume we are creating a room
|
||||
let room_version_id = services()
|
||||
.rooms
|
||||
.state
|
||||
.get_room_version(room_id)
|
||||
.or_else(|_| {
|
||||
let room_version_id =
|
||||
services().rooms.state.get_room_version(room_id).or_else(|_| {
|
||||
if event_type == TimelineEventType::RoomCreate {
|
||||
let content = serde_json::from_str::<RoomCreateEventContent>(content.get())
|
||||
let content =
|
||||
serde_json::from_str::<RoomCreateEventContent>(
|
||||
content.get(),
|
||||
)
|
||||
.expect("Invalid content in RoomCreate pdu.");
|
||||
Ok(content.room_version)
|
||||
} else {
|
||||
|
|
@ -637,7 +711,8 @@ impl Service {
|
|||
}
|
||||
})?;
|
||||
|
||||
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
|
||||
let room_version = RoomVersion::new(&room_version_id)
|
||||
.expect("room version is supported");
|
||||
|
||||
let auth_events = services().rooms.state.get_auth_events(
|
||||
room_id,
|
||||
|
|
@ -658,18 +733,22 @@ impl Service {
|
|||
let mut unsigned = unsigned.unwrap_or_default();
|
||||
|
||||
if let Some(state_key) = &state_key {
|
||||
if let Some(prev_pdu) = services().rooms.state_accessor.room_state_get(
|
||||
room_id,
|
||||
&event_type.to_string().into(),
|
||||
state_key,
|
||||
)? {
|
||||
if let Some(prev_pdu) =
|
||||
services().rooms.state_accessor.room_state_get(
|
||||
room_id,
|
||||
&event_type.to_string().into(),
|
||||
state_key,
|
||||
)?
|
||||
{
|
||||
unsigned.insert(
|
||||
"prev_content".to_owned(),
|
||||
serde_json::from_str(prev_pdu.content.get()).expect("string is valid json"),
|
||||
serde_json::from_str(prev_pdu.content.get())
|
||||
.expect("string is valid json"),
|
||||
);
|
||||
unsigned.insert(
|
||||
"prev_sender".to_owned(),
|
||||
serde_json::to_value(&prev_pdu.sender).expect("UserId::to_value always works"),
|
||||
serde_json::to_value(&prev_pdu.sender)
|
||||
.expect("UserId::to_value always works"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -694,7 +773,9 @@ impl Service {
|
|||
unsigned: if unsigned.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(to_raw_value(&unsigned).expect("to_raw_value always works"))
|
||||
Some(
|
||||
to_raw_value(&unsigned).expect("to_raw_value always works"),
|
||||
)
|
||||
},
|
||||
hashes: EventHash {
|
||||
sha256: "aaa".to_owned(),
|
||||
|
|
@ -722,8 +803,8 @@ impl Service {
|
|||
}
|
||||
|
||||
// Hash and sign
|
||||
let mut pdu_json =
|
||||
utils::to_canonical_object(&pdu).expect("event is valid, we just created it");
|
||||
let mut pdu_json = utils::to_canonical_object(&pdu)
|
||||
.expect("event is valid, we just created it");
|
||||
|
||||
pdu_json.remove("event_id");
|
||||
|
||||
|
|
@ -769,16 +850,15 @@ impl Service {
|
|||
);
|
||||
|
||||
// Generate short event id
|
||||
let _shorteventid = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shorteventid(&pdu.event_id)?;
|
||||
let _shorteventid =
|
||||
services().rooms.short.get_or_create_shorteventid(&pdu.event_id)?;
|
||||
|
||||
Ok((pdu, pdu_json))
|
||||
}
|
||||
|
||||
/// Creates a new persisted data unit and adds it to a room. This function takes a
|
||||
/// roomid_mutex_state, meaning that only this function is able to mutate the room state.
|
||||
/// Creates a new persisted data unit and adds it to a room. This function
|
||||
/// takes a roomid_mutex_state, meaning that only this function is able
|
||||
/// to mutate the room state.
|
||||
#[tracing::instrument(skip(self, state_lock))]
|
||||
pub(crate) async fn build_and_append_pdu(
|
||||
&self,
|
||||
|
|
@ -788,8 +868,12 @@ impl Service {
|
|||
// Take mutex guard to make sure users get the room state mutex
|
||||
state_lock: &MutexGuard<'_, ()>,
|
||||
) -> Result<Arc<EventId>> {
|
||||
let (pdu, pdu_json) =
|
||||
self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
|
||||
let (pdu, pdu_json) = self.create_hash_and_sign_event(
|
||||
pdu_builder,
|
||||
sender,
|
||||
room_id,
|
||||
state_lock,
|
||||
)?;
|
||||
|
||||
if let Some(admin_room) = services().admin.get_admin_room()? {
|
||||
if admin_room == room_id {
|
||||
|
|
@ -820,15 +904,24 @@ impl Service {
|
|||
"grapevine"
|
||||
},
|
||||
);
|
||||
let content = serde_json::from_str::<ExtractMembership>(pdu.content.get())
|
||||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||
let content =
|
||||
serde_json::from_str::<ExtractMembership>(
|
||||
pdu.content.get(),
|
||||
)
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in pdu.")
|
||||
})?;
|
||||
|
||||
if content.membership == MembershipState::Leave {
|
||||
if target == server_user {
|
||||
warn!("Grapevine user cannot leave from admins room");
|
||||
warn!(
|
||||
"Grapevine user cannot leave from admins \
|
||||
room"
|
||||
);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Grapevine user cannot leave from admins room.",
|
||||
"Grapevine user cannot leave from admins \
|
||||
room.",
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -841,7 +934,9 @@ impl Service {
|
|||
.filter(|m| m != target)
|
||||
.count();
|
||||
if count < 2 {
|
||||
warn!("Last admin cannot leave from admins room");
|
||||
warn!(
|
||||
"Last admin cannot leave from admins room"
|
||||
);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Last admin cannot leave from admins room.",
|
||||
|
|
@ -849,12 +944,18 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
if content.membership == MembershipState::Ban && pdu.state_key().is_some() {
|
||||
if content.membership == MembershipState::Ban
|
||||
&& pdu.state_key().is_some()
|
||||
{
|
||||
if target == server_user {
|
||||
warn!("Grapevine user cannot be banned in admins room");
|
||||
warn!(
|
||||
"Grapevine user cannot be banned in \
|
||||
admins room"
|
||||
);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Grapevine user cannot be banned in admins room.",
|
||||
"Grapevine user cannot be banned in \
|
||||
admins room.",
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -867,10 +968,14 @@ impl Service {
|
|||
.filter(|m| m != target)
|
||||
.count();
|
||||
if count < 2 {
|
||||
warn!("Last admin cannot be banned in admins room");
|
||||
warn!(
|
||||
"Last admin cannot be banned in admins \
|
||||
room"
|
||||
);
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Last admin cannot be banned in admins room.",
|
||||
"Last admin cannot be banned in admins \
|
||||
room.",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -880,7 +985,8 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
// If redaction event is not authorized, do not append it to the timeline
|
||||
// If redaction event is not authorized, do not append it to the
|
||||
// timeline
|
||||
if pdu.kind == TimelineEventType::RoomRedaction {
|
||||
match services().rooms.state.get_room_version(&pdu.room_id)? {
|
||||
RoomVersionId::V1
|
||||
|
|
@ -908,11 +1014,12 @@ impl Service {
|
|||
};
|
||||
}
|
||||
RoomVersionId::V11 => {
|
||||
let content =
|
||||
serde_json::from_str::<RoomRedactionEventContent>(pdu.content.get())
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in redaction pdu.")
|
||||
})?;
|
||||
let content = serde_json::from_str::<
|
||||
RoomRedactionEventContent,
|
||||
>(pdu.content.get())
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in redaction pdu.")
|
||||
})?;
|
||||
|
||||
if let Some(redact_id) = &content.redacts {
|
||||
if !services().rooms.state_accessor.user_can_redact(
|
||||
|
|
@ -937,27 +1044,30 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
// We append to state before appending the pdu, so we don't have a moment in time with the
|
||||
// pdu without it's state. This is okay because append_pdu can't fail.
|
||||
// We append to state before appending the pdu, so we don't have a
|
||||
// moment in time with the pdu without it's state. This is okay
|
||||
// because append_pdu can't fail.
|
||||
let statehashid = services().rooms.state.append_to_state(&pdu)?;
|
||||
|
||||
let pdu_id = self
|
||||
.append_pdu(
|
||||
&pdu,
|
||||
pdu_json,
|
||||
// Since this PDU references all pdu_leaves we can update the leaves
|
||||
// of the room
|
||||
// Since this PDU references all pdu_leaves we can update the
|
||||
// leaves of the room
|
||||
vec![(*pdu.event_id).to_owned()],
|
||||
state_lock,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// We set the room state after inserting the pdu, so that we never have a moment in time
|
||||
// where events in the current room state do not exist
|
||||
services()
|
||||
.rooms
|
||||
.state
|
||||
.set_room_state(room_id, statehashid, state_lock)?;
|
||||
// We set the room state after inserting the pdu, so that we never have
|
||||
// a moment in time where events in the current room state do
|
||||
// not exist
|
||||
services().rooms.state.set_room_state(
|
||||
room_id,
|
||||
statehashid,
|
||||
state_lock,
|
||||
)?;
|
||||
|
||||
let mut servers: HashSet<OwnedServerName> = services()
|
||||
.rooms
|
||||
|
|
@ -966,7 +1076,8 @@ impl Service {
|
|||
.filter_map(Result::ok)
|
||||
.collect();
|
||||
|
||||
// In case we are kicking or banning a user, we need to inform their server of the change
|
||||
// In case we are kicking or banning a user, we need to inform their
|
||||
// server of the change
|
||||
if pdu.kind == TimelineEventType::RoomMember {
|
||||
if let Some(state_key_uid) = &pdu
|
||||
.state_key
|
||||
|
|
@ -977,7 +1088,8 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
// Remove our server from the server list since it will be added to it by room_servers() and/or the if statement above
|
||||
// Remove our server from the server list since it will be added to it
|
||||
// by room_servers() and/or the if statement above
|
||||
servers.remove(services().globals.server_name());
|
||||
|
||||
services().sending.send_pdu(servers.into_iter(), &pdu_id)?;
|
||||
|
|
@ -985,8 +1097,8 @@ impl Service {
|
|||
Ok(pdu.event_id)
|
||||
}
|
||||
|
||||
/// Append the incoming event setting the state snapshot to the state from the
|
||||
/// server that sent the event.
|
||||
/// Append the incoming event setting the state snapshot to the state from
|
||||
/// the server that sent the event.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn append_incoming_pdu(
|
||||
&self,
|
||||
|
|
@ -998,8 +1110,9 @@ impl Service {
|
|||
// Take mutex guard to make sure users get the room state mutex
|
||||
state_lock: &MutexGuard<'_, ()>,
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
// We append to state before appending the pdu, so we don't have a moment in time with the
|
||||
// pdu without it's state. This is okay because append_pdu can't fail.
|
||||
// We append to state before appending the pdu, so we don't have a
|
||||
// moment in time with the pdu without it's state. This is okay
|
||||
// because append_pdu can't fail.
|
||||
services().rooms.state.set_event_state(
|
||||
&pdu.event_id,
|
||||
&pdu.room_id,
|
||||
|
|
@ -1037,8 +1150,9 @@ impl Service {
|
|||
self.pdus_after(user_id, room_id, PduCount::MIN)
|
||||
}
|
||||
|
||||
/// Returns an iterator over all events and their tokens in a room that happened before the
|
||||
/// event with id `until` in reverse-chronological order.
|
||||
/// Returns an iterator over all events and their tokens in a room that
|
||||
/// happened before the event with id `until` in reverse-chronological
|
||||
/// order.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(crate) fn pdus_until<'a>(
|
||||
&'a self,
|
||||
|
|
@ -1049,8 +1163,8 @@ impl Service {
|
|||
self.db.pdus_until(user_id, room_id, until)
|
||||
}
|
||||
|
||||
/// Returns an iterator over all events and their token in a room that happened after the event
|
||||
/// with id `from` in chronological order.
|
||||
/// Returns an iterator over all events and their token in a room that
|
||||
/// happened after the event with id `from` in chronological order.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(crate) fn pdus_after<'a>(
|
||||
&'a self,
|
||||
|
|
@ -1063,13 +1177,18 @@ impl Service {
|
|||
|
||||
/// Replace a PDU with the redacted form.
|
||||
#[tracing::instrument(skip(self, reason))]
|
||||
pub(crate) fn redact_pdu(&self, event_id: &EventId, reason: &PduEvent) -> Result<()> {
|
||||
pub(crate) fn redact_pdu(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
reason: &PduEvent,
|
||||
) -> Result<()> {
|
||||
// TODO: Don't reserialize, keep original json
|
||||
if let Some(pdu_id) = self.get_pdu_id(event_id)? {
|
||||
let mut pdu = self
|
||||
.get_pdu_from_id(&pdu_id)?
|
||||
.ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?;
|
||||
let room_version_id = services().rooms.state.get_room_version(&pdu.room_id)?;
|
||||
let mut pdu = self.get_pdu_from_id(&pdu_id)?.ok_or_else(|| {
|
||||
Error::bad_database("PDU ID points to invalid PDU.")
|
||||
})?;
|
||||
let room_version_id =
|
||||
services().rooms.state.get_room_version(&pdu.room_id)?;
|
||||
pdu.redact(room_version_id, reason)?;
|
||||
self.replace_pdu(
|
||||
&pdu_id,
|
||||
|
|
@ -1102,8 +1221,9 @@ impl Service {
|
|||
.state_accessor
|
||||
.room_state_get(room_id, &StateEventType::RoomPowerLevels, "")?
|
||||
.map(|ev| {
|
||||
serde_json::from_str(ev.content.get())
|
||||
.map_err(|_| Error::bad_database("invalid m.room.power_levels event"))
|
||||
serde_json::from_str(ev.content.get()).map_err(|_| {
|
||||
Error::bad_database("invalid m.room.power_levels event")
|
||||
})
|
||||
})
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
|
|
@ -1133,7 +1253,9 @@ impl Service {
|
|||
Ok(response) => {
|
||||
let pub_key_map = RwLock::new(BTreeMap::new());
|
||||
for pdu in response.pdus {
|
||||
if let Err(e) = self.backfill_pdu(backfill_server, pdu, &pub_key_map).await
|
||||
if let Err(e) = self
|
||||
.backfill_pdu(backfill_server, pdu, &pub_key_map)
|
||||
.await
|
||||
{
|
||||
warn!("Failed to add backfilled pdu: {e}");
|
||||
}
|
||||
|
|
@ -1157,7 +1279,8 @@ impl Service {
|
|||
pdu: Box<RawJsonValue>,
|
||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> Result<()> {
|
||||
let (event_id, value, room_id) = server_server::parse_incoming_pdu(&pdu)?;
|
||||
let (event_id, value, room_id) =
|
||||
server_server::parse_incoming_pdu(&pdu)?;
|
||||
|
||||
// Lock so we cannot backfill the same pdu twice at the same time
|
||||
let mutex = Arc::clone(
|
||||
|
|
@ -1180,7 +1303,14 @@ impl Service {
|
|||
services()
|
||||
.rooms
|
||||
.event_handler
|
||||
.handle_incoming_pdu(origin, &event_id, &room_id, value, false, pub_key_map)
|
||||
.handle_incoming_pdu(
|
||||
origin,
|
||||
&event_id,
|
||||
&room_id,
|
||||
value,
|
||||
false,
|
||||
pub_key_map,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let value = self.get_pdu_json(&event_id)?.expect("We just created it");
|
||||
|
|
@ -1219,14 +1349,18 @@ impl Service {
|
|||
body: Option<String>,
|
||||
}
|
||||
|
||||
let content = serde_json::from_str::<ExtractBody>(pdu.content.get())
|
||||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||
let content =
|
||||
serde_json::from_str::<ExtractBody>(pdu.content.get())
|
||||
.map_err(|_| {
|
||||
Error::bad_database("Invalid content in pdu.")
|
||||
})?;
|
||||
|
||||
if let Some(body) = content.body {
|
||||
services()
|
||||
.rooms
|
||||
.search
|
||||
.index_pdu(shortroomid, &pdu_id, &body)?;
|
||||
services().rooms.search.index_pdu(
|
||||
shortroomid,
|
||||
&pdu_id,
|
||||
&body,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
drop(mutex_lock);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue