leave room locally if room is banned, rescind knocks on deactivation too
Signed-off-by: June Clementine Strawberry <june@3.dog>
This commit is contained in:
parent
24be579477
commit
f14756fb76
5 changed files with 87 additions and 28 deletions
|
@ -475,9 +475,9 @@ pub(crate) async fn leave_room_route(
|
||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<leave_room::v3::Request>,
|
body: Ruma<leave_room::v3::Request>,
|
||||||
) -> Result<leave_room::v3::Response> {
|
) -> Result<leave_room::v3::Response> {
|
||||||
leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone()).await?;
|
leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone())
|
||||||
|
.await
|
||||||
Ok(leave_room::v3::Response::new())
|
.map(|()| leave_room::v3::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/invite`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/invite`
|
||||||
|
@ -1763,8 +1763,8 @@ pub(crate) async fn invite_helper(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a user leave all their joined rooms, forgets all rooms, and ignores
|
// Make a user leave all their joined rooms, rescinds knocks, forgets all rooms,
|
||||||
// errors
|
// and ignores errors
|
||||||
pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
|
pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
|
||||||
let rooms_joined = services
|
let rooms_joined = services
|
||||||
.rooms
|
.rooms
|
||||||
|
@ -1778,7 +1778,17 @@ pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
|
||||||
.rooms_invited(user_id)
|
.rooms_invited(user_id)
|
||||||
.map(|(r, _)| r);
|
.map(|(r, _)| r);
|
||||||
|
|
||||||
let all_rooms: Vec<_> = rooms_joined.chain(rooms_invited).collect().await;
|
let rooms_knocked = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.rooms_knocked(user_id)
|
||||||
|
.map(|(r, _)| r);
|
||||||
|
|
||||||
|
let all_rooms: Vec<_> = rooms_joined
|
||||||
|
.chain(rooms_invited)
|
||||||
|
.chain(rooms_knocked)
|
||||||
|
.collect()
|
||||||
|
.await;
|
||||||
|
|
||||||
for room_id in all_rooms {
|
for room_id in all_rooms {
|
||||||
// ignore errors
|
// ignore errors
|
||||||
|
@ -1795,7 +1805,40 @@ pub async fn leave_room(
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
) -> Result<()> {
|
) -> Result {
|
||||||
|
let default_member_content = RoomMemberEventContent {
|
||||||
|
membership: MembershipState::Leave,
|
||||||
|
reason: reason.clone(),
|
||||||
|
join_authorized_via_users_server: None,
|
||||||
|
is_direct: None,
|
||||||
|
avatar_url: None,
|
||||||
|
displayname: None,
|
||||||
|
third_party_invite: None,
|
||||||
|
blurhash: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if services.rooms.metadata.is_banned(room_id).await
|
||||||
|
|| services.rooms.metadata.is_disabled(room_id).await
|
||||||
|
{
|
||||||
|
// the room is banned/disabled, the room must be rejected locally since we
|
||||||
|
// cant/dont want to federate with this server
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.update_membership(
|
||||||
|
room_id,
|
||||||
|
user_id,
|
||||||
|
default_member_content,
|
||||||
|
user_id,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
// Ask a remote server if we don't have this room and are not knocking on it
|
// Ask a remote server if we don't have this room and are not knocking on it
|
||||||
if !services
|
if !services
|
||||||
.rooms
|
.rooms
|
||||||
|
@ -1828,7 +1871,7 @@ pub async fn leave_room(
|
||||||
.update_membership(
|
.update_membership(
|
||||||
room_id,
|
room_id,
|
||||||
user_id,
|
user_id,
|
||||||
RoomMemberEventContent::new(MembershipState::Leave),
|
default_member_content,
|
||||||
user_id,
|
user_id,
|
||||||
last_state,
|
last_state,
|
||||||
None,
|
None,
|
||||||
|
@ -1848,26 +1891,23 @@ pub async fn leave_room(
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
else {
|
else {
|
||||||
// Fix for broken rooms
|
debug_warn!(
|
||||||
warn!(
|
|
||||||
"Trying to leave a room you are not a member of, marking room as left locally."
|
"Trying to leave a room you are not a member of, marking room as left locally."
|
||||||
);
|
);
|
||||||
|
|
||||||
services
|
return services
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.update_membership(
|
.update_membership(
|
||||||
room_id,
|
room_id,
|
||||||
user_id,
|
user_id,
|
||||||
RoomMemberEventContent::new(MembershipState::Leave),
|
default_member_content,
|
||||||
user_id,
|
user_id,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.await?;
|
.await;
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services
|
services
|
||||||
|
@ -1897,7 +1937,7 @@ async fn remote_leave_room(
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut make_leave_response_and_server =
|
let mut make_leave_response_and_server =
|
||||||
Err!(BadServerResponse("No server available to assist in leaving."));
|
Err!(BadServerResponse("No remote server available to assist in leaving {room_id}."));
|
||||||
|
|
||||||
let mut servers: HashSet<OwnedServerName> = services
|
let mut servers: HashSet<OwnedServerName> = services
|
||||||
.rooms
|
.rooms
|
||||||
|
@ -1977,20 +2017,25 @@ async fn remote_leave_room(
|
||||||
let (make_leave_response, remote_server) = make_leave_response_and_server?;
|
let (make_leave_response, remote_server) = make_leave_response_and_server?;
|
||||||
|
|
||||||
let Some(room_version_id) = make_leave_response.room_version else {
|
let Some(room_version_id) = make_leave_response.room_version else {
|
||||||
return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
|
return Err!(BadServerResponse(warn!(
|
||||||
|
"No room version was returned by {remote_server} for {room_id}, room version is \
|
||||||
|
likely not supported by conduwuit"
|
||||||
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
if !services.server.supported_room_version(&room_version_id) {
|
if !services.server.supported_room_version(&room_version_id) {
|
||||||
return Err!(BadServerResponse(
|
return Err!(BadServerResponse(warn!(
|
||||||
"Remote room version {room_version_id} is not supported by conduwuit"
|
"Remote room version {room_version_id} for {room_id} is not supported by conduwuit",
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>(
|
let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>(
|
||||||
make_leave_response.event.get(),
|
make_leave_response.event.get(),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
err!(BadServerResponse("Invalid make_leave event json received from server: {e:?}"))
|
err!(BadServerResponse(warn!(
|
||||||
|
"Invalid make_leave event json received from {remote_server} for {room_id}: {e:?}"
|
||||||
|
)))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// TODO: Is origin needed?
|
// TODO: Is origin needed?
|
||||||
|
|
|
@ -15,6 +15,7 @@ use conduwuit::{
|
||||||
math::ruma_from_u64,
|
math::ruma_from_u64,
|
||||||
stream::{BroadbandExt, Tools, TryExpect, WidebandExt},
|
stream::{BroadbandExt, Tools, TryExpect, WidebandExt},
|
||||||
},
|
},
|
||||||
|
warn,
|
||||||
};
|
};
|
||||||
use conduwuit_service::{
|
use conduwuit_service::{
|
||||||
Services,
|
Services,
|
||||||
|
@ -428,9 +429,12 @@ async fn handle_left_room(
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !services.rooms.metadata.exists(room_id).await {
|
if !services.rooms.metadata.exists(room_id).await
|
||||||
|
|| services.rooms.metadata.is_disabled(room_id).await
|
||||||
|
|| services.rooms.metadata.is_banned(room_id).await
|
||||||
|
{
|
||||||
// This is just a rejected invite, not a room we know
|
// This is just a rejected invite, not a room we know
|
||||||
// Insert a leave event anyways
|
// Insert a leave event anyways for the client
|
||||||
let event = PduEvent {
|
let event = PduEvent {
|
||||||
event_id: EventId::new(services.globals.server_name()),
|
event_id: EventId::new(services.globals.server_name()),
|
||||||
sender: sender_user.to_owned(),
|
sender: sender_user.to_owned(),
|
||||||
|
@ -489,7 +493,7 @@ async fn handle_left_room(
|
||||||
.room_state_get_id(room_id, &StateEventType::RoomMember, sender_user.as_str())
|
.room_state_get_id(room_id, &StateEventType::RoomMember, sender_user.as_str())
|
||||||
.await
|
.await
|
||||||
else {
|
else {
|
||||||
error!("Left room but no left state event");
|
warn!("Left {room_id} but no left state event");
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -499,7 +503,7 @@ async fn handle_left_room(
|
||||||
.pdu_shortstatehash(&left_event_id)
|
.pdu_shortstatehash(&left_event_id)
|
||||||
.await
|
.await
|
||||||
else {
|
else {
|
||||||
error!(event_id = %left_event_id, "Leave event has no state");
|
warn!(event_id = %left_event_id, "Leave event has no state in {room_id}");
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -438,7 +438,10 @@ pub(crate) async fn sync_events_v4_route(
|
||||||
|
|
||||||
let mut known_subscription_rooms = BTreeSet::new();
|
let mut known_subscription_rooms = BTreeSet::new();
|
||||||
for (room_id, room) in &body.room_subscriptions {
|
for (room_id, room) in &body.room_subscriptions {
|
||||||
if !services.rooms.metadata.exists(room_id).await {
|
if !services.rooms.metadata.exists(room_id).await
|
||||||
|
|| services.rooms.metadata.is_disabled(room_id).await
|
||||||
|
|| services.rooms.metadata.is_banned(room_id).await
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let todo_room =
|
let todo_room =
|
||||||
|
|
|
@ -214,7 +214,10 @@ async fn fetch_subscriptions(
|
||||||
) {
|
) {
|
||||||
let mut known_subscription_rooms = BTreeSet::new();
|
let mut known_subscription_rooms = BTreeSet::new();
|
||||||
for (room_id, room) in &body.room_subscriptions {
|
for (room_id, room) in &body.room_subscriptions {
|
||||||
if !services.rooms.metadata.exists(room_id).await {
|
if !services.rooms.metadata.exists(room_id).await
|
||||||
|
|| services.rooms.metadata.is_disabled(room_id).await
|
||||||
|
|| services.rooms.metadata.is_banned(room_id).await
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let todo_room =
|
let todo_room =
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct Services {
|
||||||
account_data: Dep<account_data::Service>,
|
account_data: Dep<account_data::Service>,
|
||||||
config: Dep<config::Service>,
|
config: Dep<config::Service>,
|
||||||
globals: Dep<globals::Service>,
|
globals: Dep<globals::Service>,
|
||||||
|
metadata: Dep<rooms::metadata::Service>,
|
||||||
state_accessor: Dep<rooms::state_accessor::Service>,
|
state_accessor: Dep<rooms::state_accessor::Service>,
|
||||||
users: Dep<users::Service>,
|
users: Dep<users::Service>,
|
||||||
}
|
}
|
||||||
|
@ -73,6 +74,7 @@ impl crate::Service for Service {
|
||||||
account_data: args.depend::<account_data::Service>("account_data"),
|
account_data: args.depend::<account_data::Service>("account_data"),
|
||||||
config: args.depend::<config::Service>("config"),
|
config: args.depend::<config::Service>("config"),
|
||||||
globals: args.depend::<globals::Service>("globals"),
|
globals: args.depend::<globals::Service>("globals"),
|
||||||
|
metadata: args.depend::<rooms::metadata::Service>("rooms::metadata"),
|
||||||
state_accessor: args
|
state_accessor: args
|
||||||
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
|
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
|
||||||
users: args.depend::<users::Service>("users"),
|
users: args.depend::<users::Service>("users"),
|
||||||
|
@ -271,7 +273,9 @@ impl Service {
|
||||||
self.mark_as_left(user_id, room_id);
|
self.mark_as_left(user_id, room_id);
|
||||||
|
|
||||||
if self.services.globals.user_is_local(user_id)
|
if self.services.globals.user_is_local(user_id)
|
||||||
&& self.services.config.forget_forced_upon_leave
|
&& (self.services.config.forget_forced_upon_leave
|
||||||
|
|| self.services.metadata.is_banned(room_id).await
|
||||||
|
|| self.services.metadata.is_disabled(room_id).await)
|
||||||
{
|
{
|
||||||
self.forget(room_id, user_id);
|
self.forget(room_id, user_id);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue