diff --git a/crates/matrix-sdk-appservice/src/lib.rs b/crates/matrix-sdk-appservice/src/lib.rs index 7500766af..d02fb1bb8 100644 --- a/crates/matrix-sdk-appservice/src/lib.rs +++ b/crates/matrix-sdk-appservice/src/lib.rs @@ -202,6 +202,11 @@ impl<'a> VirtualUserBuilder<'a> { } let user_id = UserId::parse_with_server_name(self.localpart, &self.appservice.server_name)?; + if !(self.appservice.user_id_is_in_namespace(&user_id)? + || self.localpart == self.appservice.registration.sender_localpart) + { + warn!("Virtual client id '{user_id}' is not in the namespace") + } let mut builder = self.client_builder; diff --git a/crates/matrix-sdk-appservice/tests/tests.rs b/crates/matrix-sdk-appservice/tests/tests.rs index 88886e5ef..2d20fd074 100644 --- a/crates/matrix-sdk-appservice/tests/tests.rs +++ b/crates/matrix-sdk-appservice/tests/tests.rs @@ -10,7 +10,12 @@ use matrix_sdk::{ }; use matrix_sdk_appservice::*; use matrix_sdk_test::{appservice::TransactionBuilder, async_test, EventsJson}; -use ruma::{api::MatrixVersion, room_id}; +use ruma::{ + api::{appservice::event::push_events, MatrixVersion}, + events::AnyRoomEvent, + room_id, + serde::Raw, +}; use serde_json::json; use warp::{Filter, Reply}; @@ -299,6 +304,105 @@ async fn test_appservice_on_sub_path() -> Result<()> { Ok(()) } +#[async_test] +async fn test_receive_transaction() -> Result<()> { + tracing_subscriber::fmt().try_init().ok(); + let json = vec![ + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Appservice", + "membership": "join" + }, + "event_id": "$151800140479rdvjg:localhost", + "membership": "join", + "origin_server_ts": 151800140, + "sender": "@_appservice:localhost", + "state_key": "@_appservice:localhost", + "type": "m.room.member", + "room_id": "!coolplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Appservice", + "membership": "join" + }, + "event_id": "$151800140491rfbja:localhost", + "membership": "join", + "origin_server_ts": 151800140, + "sender": "@_appservice:localhost", + "state_key": "@_appservice:localhost", + "type": "m.room.member", + "room_id": "!boringplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Alice", + "membership": "join" + }, + "event_id": "$151800140517rfvjc:localhost", + "membership": "join", + "origin_server_ts": 151800140, + "sender": "@_appservice_alice:localhost", + "state_key": "@_appservice_alice:localhost", + "type": "m.room.member", + "room_id": "!coolplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Bob", + "membership": "invite" + }, + "event_id": "$151800140594rfvjc:localhost", + "membership": "invite", + "origin_server_ts": 151800174, + "sender": "@_appservice_bob:localhost", + "state_key": "@_appservice_bob:localhost", + "type": "m.room.member", + "room_id": "!boringplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + ]; + let appservice = appservice(None).await?; + + let alice = appservice.virtual_user_client("_appservice_alice").await?; + let bob = appservice.virtual_user_client("_appservice_bob").await?; + appservice + .receive_transaction(push_events::v1::IncomingRequest::new("dontcare".into(), json)) + .await?; + let coolplace = room_id!("!coolplace:localhost"); + let boringplace = room_id!("!boringplace:localhost"); + assert!( + alice.get_joined_room(coolplace).is_some(), + "Alice's membership in coolplace should be join" + ); + assert!( + bob.get_invited_room(boringplace).is_some(), + "Bob's membership in boringplace should be invite" + ); + assert!(alice.get_room(boringplace).is_none(), "Alice should not know about boringplace"); + assert!(bob.get_room(coolplace).is_none(), "Bob should not know about coolplace"); + Ok(()) +} + mod registration { use super::*;