diff --git a/.rustfmt.toml b/.rustfmt.toml index 9224a6b..65ac5e2 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,4 +1,4 @@ -fn_call_width = 124 -max_width = 124 +fn_call_width = 128 +max_width = 128 reorder_imported_names = true chain_one_line_max = 6 diff --git a/assets/translations.yaml b/assets/translations.yaml index 66b50b1..3983f24 100644 --- a/assets/translations.yaml +++ b/assets/translations.yaml @@ -41,6 +41,7 @@ en: ${channel_list} room_successfully_bridged: "${channel_name} is now bridged." + room_successfully_unbridged: "${channel_name} is now unbridged." defaults: admin_room_display_name: "Admin Room (Rocket.Chat)" internal_error: "An internal error occurred" @@ -50,6 +51,7 @@ en: authentication_failed: "Authentication failed!" internal: "An internal error occurred" no_rocketchat_server: "No Rocket.Chat server found when querying ${rocketchat_url} (version information is missing from the response)" + other_user_joined: "Another user join the admin room, leaving, please create a new admin room." rocketchat_channel_already_bridged: "The channel ${channel_name} is already bridged." rocketchat_channel_not_found: "No channel with the name ${channel_name} found." rocketchat_token_missing: "A token is needed to connect new Rocket.Chat servers" @@ -58,7 +60,8 @@ en: rocketchat_join_first: "You have to join the channel ${channel_name} on the Rocket.Chat server before you can bridge it." room_already_connected: "This room is already connected" room_not_connected: "This room is not connected to a Rocket.Chat server, you have to connect it first to be able to execute the command, type `help` for further instructions on how to connect this room" + room_not_empty: "Cannot unbdrige room ${channel_name}, because Matrix users (${users}) are still using the room." token_already_in_use: "The token ${token} is already in use, please use another token." - unsupported_rocketchat_api_version: "No supported API version (>= ${min_version}) found for the Rocket.Chat server, found version: ${version}" too_many_members_in_room: "Admin rooms must only contain the user that invites the bot. Too many members in the room, leaving." - other_user_joined: "Another user join the admin room, leaving, please create a new admin room." + unsupported_rocketchat_api_version: "No supported API version (>= ${min_version}) found for the Rocket.Chat server, found version: ${version}" + unbridge_of_not_bridged_room: "The channel ${channel_name} is not bridged, cannot unbridge it." diff --git a/src/matrix-rocketchat/db/rocketchat_server.rs b/src/matrix-rocketchat/db/rocketchat_server.rs index a5107bc..53f5307 100644 --- a/src/matrix-rocketchat/db/rocketchat_server.rs +++ b/src/matrix-rocketchat/db/rocketchat_server.rs @@ -7,7 +7,7 @@ use errors::*; use super::schema::rocketchat_servers; /// A Rocket.Chat server. -#[derive(Debug, Identifiable, Queryable)] +#[derive(Associations, Debug, Identifiable, Queryable)] #[table_name="rocketchat_servers"] pub struct RocketchatServer { /// The unique id for the Rocket.Chat server diff --git a/src/matrix-rocketchat/db/room.rs b/src/matrix-rocketchat/db/room.rs index 8df1592..42e7c90 100644 --- a/src/matrix-rocketchat/db/room.rs +++ b/src/matrix-rocketchat/db/room.rs @@ -4,10 +4,8 @@ use diesel::sqlite::SqliteConnection; use ruma_identifiers::{RoomId, UserId}; use errors::*; -use super::schema::{rocketchat_servers, rooms, users, users_in_rooms}; -use super::RocketchatServer; -use super::user::User; -use super::user_in_room::UserInRoom; +use super::schema::{rocketchat_servers, rooms, users, users_in_rooms, users_on_rocketchat_servers}; +use super::{RocketchatServer, User, UserInRoom, UserOnRocketchatServer}; /// A room that is managed by the application service. This can be either a bridged room or an /// admin room. @@ -86,6 +84,20 @@ impl Room { Ok(rooms.into_iter().next()) } + /// Find a `Room` by its display name. It also requires the server id, because the + /// display name might not be unique across servers. + /// Returns `None`, if the room is not found. + pub fn find_by_display_name(connection: &SqliteConnection, + rocketchat_server_id: i32, + display_name: String) + -> Result> { + let rooms = rooms::table.filter(rooms::rocketchat_server_id.eq(rocketchat_server_id) + .and(rooms::display_name.eq(display_name))) + .load(connection) + .chain_err(|| ErrorKind::DBSelectError)?; + Ok(rooms.into_iter().next()) + } + /// Indicates if the room is bridged for a given user. pub fn is_bridged_for_user(connection: &SqliteConnection, rocketchat_server_id: i32, @@ -100,10 +112,7 @@ impl Room { } /// Indicates if a room is bridged. - pub fn is_bridged(connection: &SqliteConnection, - rocketchat_server_id: i32, - rocketchat_room_id: String) - -> Result { + pub fn is_bridged(connection: &SqliteConnection, rocketchat_server_id: i32, rocketchat_room_id: String) -> Result { match Room::find_by_rocketchat_room_id(connection, rocketchat_server_id, rocketchat_room_id)? { Some(room) => Ok(room.is_bridged), None => Ok(false), @@ -154,6 +163,35 @@ impl Room { Ok(users) } + /// Returns all `Users`s in the room that are not virtual users. + pub fn non_virtual_users(&self, connection: &SqliteConnection) -> Result> { + let rocketchat_server = match self.rocketchat_server(connection)? { + Some(rocketchat_server) => rocketchat_server, + None => { + return self.users(connection); + } + }; + + let users: Vec = + users::table.filter( + users::matrix_user_id.eq_any( + UserInRoom::belonging_to(self).select(users_in_rooms::matrix_user_id) + ).and(users::matrix_user_id.eq_any( + UserOnRocketchatServer::belonging_to(&rocketchat_server).filter( + users_on_rocketchat_servers::is_virtual_user.eq(false) + ).select(users_on_rocketchat_servers::matrix_user_id) + ))).load(connection).chain_err(|| ErrorKind::DBSelectError)?; + Ok(users) + } + + /// Update the is_bridged flag for the room. + pub fn set_is_bridged(&self, connection: &SqliteConnection, is_bridged: bool) -> Result<()> { + diesel::update(rooms::table.find(&self.matrix_room_id)).set(rooms::is_bridged.eq(is_bridged)) + .execute(connection) + .chain_err(|| ErrorKind::DBUpdateError)?; + Ok(()) + } + /// Delete a room, this also deletes any users_in_rooms relations for that room. pub fn delete(&self, connection: &SqliteConnection) -> Result<()> { diesel::delete(UserInRoom::belonging_to(self)).execute(connection).chain_err(|| ErrorKind::DBDeleteError)?; diff --git a/src/matrix-rocketchat/db/user.rs b/src/matrix-rocketchat/db/user.rs index bc54aa7..0b92349 100644 --- a/src/matrix-rocketchat/db/user.rs +++ b/src/matrix-rocketchat/db/user.rs @@ -10,7 +10,9 @@ use i18n::*; use super::schema::users; /// A Matrix `User`. -#[derive(Debug, Queryable)] +#[derive(Associations, Debug, Identifiable, Queryable)] +#[primary_key(matrix_user_id)] +#[table_name="users"] pub struct User { /// The users unique id on the Matrix server. pub matrix_user_id: UserId, diff --git a/src/matrix-rocketchat/db/user_in_room.rs b/src/matrix-rocketchat/db/user_in_room.rs index 7698b85..9716caa 100644 --- a/src/matrix-rocketchat/db/user_in_room.rs +++ b/src/matrix-rocketchat/db/user_in_room.rs @@ -10,8 +10,8 @@ use super::schema::users_in_rooms; /// Join table for users that participate in a room. #[derive(Associations, Debug, Identifiable, Queryable)] #[belongs_to(Room, foreign_key = "matrix_room_id")] -#[table_name="users_in_rooms"] #[primary_key(matrix_user_id, matrix_room_id)] +#[table_name="users_in_rooms"] pub struct UserInRoom { /// The users unique id on the Matrix server. pub matrix_user_id: UserId, @@ -36,9 +36,7 @@ pub struct NewUserInRoom { impl UserInRoom { /// Insert a new `UserInRoom` into the database. pub fn insert(connection: &SqliteConnection, user_in_room: &NewUserInRoom) -> Result { - diesel::insert(user_in_room).into(users_in_rooms::table) - .execute(connection) - .chain_err(|| ErrorKind::DBInsertError)?; + diesel::insert(user_in_room).into(users_in_rooms::table).execute(connection).chain_err(|| ErrorKind::DBInsertError)?; UserInRoom::find(connection, &user_in_room.matrix_user_id, &user_in_room.matrix_room_id) } @@ -60,4 +58,16 @@ impl UserInRoom { .chain_err(|| ErrorKind::DBSelectError)?; Ok(user_in_room.into_iter().next()) } + + /// Delete a user_in_room. + pub fn delete(&self, connection: &SqliteConnection) -> Result<()> { + diesel::delete( + users_in_rooms::table.filter( + users_in_rooms::matrix_user_id.eq(&self.matrix_user_id).and(users_in_rooms::matrix_room_id.eq(&self.matrix_room_id)) + ) + ).execute(connection).chain_err(|| ErrorKind::DBDeleteError)?; + + Ok(()) + + } } diff --git a/src/matrix-rocketchat/db/user_on_rocketchat_server.rs b/src/matrix-rocketchat/db/user_on_rocketchat_server.rs index c056beb..7c5ee72 100644 --- a/src/matrix-rocketchat/db/user_on_rocketchat_server.rs +++ b/src/matrix-rocketchat/db/user_on_rocketchat_server.rs @@ -5,10 +5,13 @@ use ruma_identifiers::UserId; use errors::*; use super::schema::users_on_rocketchat_servers; -use super::User; +use super::{RocketchatServer, User}; /// A user on a Rocket.Chat server. -#[derive(Debug, Queryable)] +#[derive(Associations, Debug, Identifiable, Queryable)] +#[belongs_to(RocketchatServer, foreign_key = "rocketchat_server_id")] +#[primary_key(matrix_user_id, rocketchat_server_id)] +#[table_name="users_on_rocketchat_servers"] pub struct UserOnRocketchatServer { /// Flag to indicate if the user is only used to send messages from Rocket.Chat pub is_virtual_user: bool, diff --git a/src/matrix-rocketchat/errors.rs b/src/matrix-rocketchat/errors.rs index c46972e..eb1359e 100644 --- a/src/matrix-rocketchat/errors.rs +++ b/src/matrix-rocketchat/errors.rs @@ -213,6 +213,16 @@ error_chain!{ display("Bridging the channel {} failed, because the user hasn't joined it on Rocket.Chat", channel_name) } + UnbridgeOfNotBridgedRoom(display_name: String) { + description("Room with the given display name could not be found") + display("No room with display_name {} found", display_name) + } + + RoomNotEmpty(display_name: String, users: String) { + description("Non virtual users are in the room") + display("The room {} has matrix users ({}) in it, cannot unbridge", display_name, users) + } + ReadConfigError { description("Error when reading the config content to a string") display("Could not read config content to string") @@ -353,10 +363,7 @@ impl From for IronError { impl<'a> Modifier for &'a Error { fn modify(self, response: &mut Response) { - let mut causes = Vec::with_capacity(self.error_chain.iter().count() - 1); - for err in self.error_chain.iter().skip(1) { - causes.push(format!("{}", err)); - } + let causes = self.error_chain.iter().skip(1).map(|e| format!("{}", e)).collect(); let resp = ErrorResponse { error: format!("{}", self), diff --git a/src/matrix-rocketchat/handlers/events/command_handler.rs b/src/matrix-rocketchat/handlers/events/command_handler.rs index f51c4ef..8bc6354 100644 --- a/src/matrix-rocketchat/handlers/events/command_handler.rs +++ b/src/matrix-rocketchat/handlers/events/command_handler.rs @@ -69,6 +69,11 @@ impl<'a> CommandHandler<'a> { let rocketchat_server = self.get_rocketchat_server(room, &message)?; self.bridge(event, &rocketchat_server, &message)?; + } else if message.starts_with("unbridge") { + debug!(self.logger, "Received unbridge command"); + + let rocketchat_server = self.get_rocketchat_server(room, &message)?; + self.unbridge(event, &rocketchat_server, &message)?; } else if event.user_id == self.config.matrix_bot_user_id()? { debug!(self.logger, "Skipping event from bot user"); } else { @@ -117,7 +122,12 @@ impl<'a> CommandHandler<'a> { let body = t!(["admin_room", "login_instructions"]) .with_vars(vec![("rocketchat_url", rocketchat_url.to_string())]) .l(&user.language); - self.matrix_api.send_text_message_event(event.room_id.clone(), self.config.matrix_bot_user_id()?, body) + self.matrix_api.send_text_message_event(event.room_id.clone(), self.config.matrix_bot_user_id()?, body)?; + + Ok(info!(self.logger, + "Successfully executed connect command for user {} and Rocket.Chat server {}", + user.matrix_user_id, + rocketchat_url)) }) .map_err(Error::from) } @@ -163,16 +173,16 @@ impl<'a> CommandHandler<'a> { None => t!(["admin_room", "connection_instructions"]).with_vars(vec![("as_url", self.config.as_url.clone())]), }; - self.matrix_api.send_text_message_event(event.room_id.clone(), - self.config.matrix_bot_user_id()?, - body.l(&user.language)) + let bot_matrix_user_id = self.config.matrix_bot_user_id()?; + self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, body.l(&user.language))?; + + Ok(info!(self.logger, "Successfully executed login command for user {}", user.matrix_user_id)) } fn login(&self, event: &MessageEvent, rocketchat_server: &RocketchatServer, message: &str) -> Result<()> { let user = User::find(self.connection, &event.user_id)?; - let user_on_rocketchat_server = - UserOnRocketchatServer::find(self.connection, &event.user_id, rocketchat_server.id)?; + let user_on_rocketchat_server = UserOnRocketchatServer::find(self.connection, &event.user_id, rocketchat_server.id)?; let mut command = message.split_whitespace().collect::>().into_iter(); let username = command.by_ref().nth(1).unwrap_or_default(); @@ -188,18 +198,22 @@ impl<'a> CommandHandler<'a> { Some(rocketchat_auth_token.clone()))?; let username = rocketchat_api.username(rocketchat_user_id, rocketchat_auth_token)?; - user_on_rocketchat_server.set_rocketchat_username(self.connection, Some(username))?; + user_on_rocketchat_server.set_rocketchat_username(self.connection, Some(username.clone()))?; let bot_matrix_user_id = self.config.matrix_bot_user_id()?; let message = t!(["admin_room", "bridge_instructions"]); - self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, message.l(&user.language)) + self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, message.l(&user.language))?; + + Ok(info!(self.logger, + "Successfully executed login command for user {} on Rocket.Chat server {}", + username, + rocketchat_server.rocketchat_url)) } fn list_channels(&self, event: &MessageEvent, rocketchat_server: &RocketchatServer) -> Result<()> { let user = User::find(self.connection, &event.user_id)?; - let user_on_rocketchat_server = - UserOnRocketchatServer::find(self.connection, &event.user_id, rocketchat_server.id)?; + let user_on_rocketchat_server = UserOnRocketchatServer::find(self.connection, &event.user_id, rocketchat_server.id)?; let rocketchat_api = RocketchatApi::new(rocketchat_server.rocketchat_url.clone(), rocketchat_server.rocketchat_token.clone(), self.logger.clone())?; @@ -210,7 +224,9 @@ impl<'a> CommandHandler<'a> { let bot_matrix_user_id = self.config.matrix_bot_user_id()?; let channels_list = self.build_channels_list(rocketchat_server.id, &event.user_id, channels)?; let message = t!(["admin_room", "list_channels"]).with_vars(vec![("channel_list", channels_list)]); - self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, message.l(&user.language)) + self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, message.l(&user.language))?; + + Ok(info!(self.logger, "Successfully listed channels for Rocket.Chat server {}", &rocketchat_server.rocketchat_url)) } fn bridge(&self, event: &MessageEvent, rocketchat_server: &RocketchatServer, message: &str) -> Result<()> { @@ -224,9 +240,7 @@ impl<'a> CommandHandler<'a> { let channels = rocketchat_api.channels_list(user_on_rocketchat_server.rocketchat_user_id.clone().unwrap_or_default(), - user_on_rocketchat_server.rocketchat_auth_token - .clone() - .unwrap_or_default())?; + user_on_rocketchat_server.rocketchat_auth_token.clone().unwrap_or_default())?; let mut command = message.split_whitespace().collect::>().into_iter(); let channel_name = command.by_ref().nth(1).unwrap_or_default(); @@ -235,8 +249,8 @@ impl<'a> CommandHandler<'a> { Some(channel) => channel, None => { bail_error!(ErrorKind::RocketchatChannelNotFound(channel_name.to_string()), - t!(["errors", "rocketchat_channel_not_found"]) - .with_vars(vec![("channel_name", channel_name.to_string())])); + t!(["errors", "rocketchat_channel_not_found"]).with_vars(vec![("channel_name", + channel_name.to_string())])); } }; @@ -253,30 +267,51 @@ impl<'a> CommandHandler<'a> { channel_name.to_string())])); } - let room = - match Room::find_by_rocketchat_room_id(self.connection, rocketchat_server.id, channel.id.clone())? { - Some(room) => room, - None => self.create_room(channel, rocketchat_server.id, event.user_id.clone())?, - }; - - let user = user_on_rocketchat_server.user(self.connection)?; - let new_user_in_room = NewUserInRoom { - matrix_user_id: user.matrix_user_id, - matrix_room_id: room.matrix_room_id.clone(), + let room = match Room::find_by_rocketchat_room_id(self.connection, rocketchat_server.id, channel.id.clone())? { + Some(room) => room, + None => self.create_room(channel, rocketchat_server.id, event.user_id.clone())?, }; - UserInRoom::insert(self.connection, &new_user_in_room)?; + let user = user_on_rocketchat_server.user(self.connection)?; let bot_matrix_user_id = self.config.matrix_bot_user_id()?; let message = t!(["admin_room", "room_successfully_bridged"]).with_vars(vec![("channel_name", channel.name.clone())]); - info!(self.logger, "Successfully bridged room {} to {}", &channel.id, &room.matrix_room_id); - self.matrix_api.send_text_message_event(event.room_id.clone(), - bot_matrix_user_id, - message.l(&user.language)) + self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, message.l(&user.language))?; + + Ok(info!(self.logger, "Successfully bridged room {} to {}", &channel.id, &room.matrix_room_id)) }) .map_err(Error::from) } + fn unbridge(&self, event: &MessageEvent, rocketchat_server: &RocketchatServer, message: &str) -> Result<()> { + let mut command = message.split_whitespace().collect::>().into_iter(); + let channel_name = command.nth(1).unwrap_or_default().to_string(); + + let room = match Room::find_by_display_name(self.connection, rocketchat_server.id, channel_name.clone())? { + Some(room) => room, + None => { + bail_error!(ErrorKind::UnbridgeOfNotBridgedRoom(channel_name.to_string()), + t!(["errors", "unbridge_of_not_bridged_room"]).with_vars(vec![("channel_name", channel_name)])); + } + }; + + let users = room.non_virtual_users(self.connection)?; + if users.len() != 0 { + let user_ids = users.iter().map(|u| u.matrix_user_id.to_string()).collect::>().join(", "); + bail_error!(ErrorKind::RoomNotEmpty(channel_name.to_string(), user_ids.clone()), + t!(["errors", "room_not_empty"]).with_vars(vec![("channel_name", channel_name), ("users", user_ids)])); + } + + room.set_is_bridged(self.connection, false)?; + + let bot_matrix_user_id = self.config.matrix_bot_user_id()?; + let user = User::find(self.connection, &event.user_id)?; + let message = t!(["admin_room", "room_successfully_unbridged"]).with_vars(vec![("channel_name", channel_name.clone())]); + self.matrix_api.send_text_message_event(event.room_id.clone(), bot_matrix_user_id, message.l(&user.language))?; + + Ok(info!(self.logger, "Successfully unbridged room {}", channel_name.clone())) + } + fn get_existing_rocketchat_server(&self, rocketchat_url: String) -> Result { let rocketchat_server: RocketchatServer = match RocketchatServer::find_by_url(self.connection, rocketchat_url)? { Some(rocketchat_server) => rocketchat_server, diff --git a/src/matrix-rocketchat/handlers/events/room_handler.rs b/src/matrix-rocketchat/handlers/events/room_handler.rs index 02e61a9..4ad497d 100644 --- a/src/matrix-rocketchat/handlers/events/room_handler.rs +++ b/src/matrix-rocketchat/handlers/events/room_handler.rs @@ -56,16 +56,16 @@ impl<'a> RoomHandler<'a> { self.handle_bot_join(event.room_id.clone(), matrix_bot_user_id)?; } MembershipState::Join => { - let msg = format!("User {} joined room {}", state_key, event.room_id); + let msg = format!("User {} joined room {}", &state_key, &event.room_id); debug!(self.logger, msg); - self.handle_user_join(event.room_id.clone())?; + self.handle_user_join(state_key, event.room_id.clone())?; } MembershipState::Leave if !addressed_to_matrix_bot => { let msg = format!("User {} left room {}", event.user_id, event.room_id); debug!(self.logger, msg); - self.handle_user_leave(event.room_id.clone())?; + self.handle_user_leave(&event.user_id, &event.room_id)?; } _ => { let msg = format!("Skipping event, don't know how to handle membership state `{}` with state key `{}`", @@ -129,7 +129,7 @@ impl<'a> RoomHandler<'a> { Ok(()) } - fn handle_user_join(&self, matrix_room_id: RoomId) -> Result<()> { + fn handle_user_join(&self, matrix_user_id: UserId, matrix_room_id: RoomId) -> Result<()> { let room = Room::find(self.connection, &matrix_room_id)?; if room.is_admin_room { info!(self.logger, "Another user join the admin room {}, bot user is leaving", matrix_room_id); @@ -137,19 +137,31 @@ impl<'a> RoomHandler<'a> { let body = t!(["errors", "other_user_joined"]).l(&admin_room_language); self.matrix_api.send_text_message_event(matrix_room_id, self.config.matrix_bot_user_id()?, body)?; self.leave_and_forget_room(&room)?; + } else { + let new_user_in_room = NewUserInRoom { + matrix_user_id: matrix_user_id, + matrix_room_id: matrix_room_id, + }; + UserInRoom::insert(self.connection, &new_user_in_room)?; } Ok(()) } - fn handle_user_leave(&self, matrix_room_id: RoomId) -> Result<()> { - let room = match Room::find_by_matrix_room_id(self.connection, &matrix_room_id)? { + fn handle_user_leave(&self, matrix_user_id: &UserId, matrix_room_id: &RoomId) -> Result<()> { + let room = match Room::find_by_matrix_room_id(self.connection, matrix_room_id)? { Some(room) => room, None => return Ok(()), }; if room.is_admin_room { - self.leave_and_forget_room(&room)?; + return self.leave_and_forget_room(&room); + } + + if let Some(user_in_room) = + UserInRoom::find_by_matrix_user_id_and_matrix_room_id(self.connection, matrix_user_id, matrix_room_id)? { + user_in_room.delete(self.connection)?; } + Ok(()) } @@ -158,8 +170,7 @@ impl<'a> RoomHandler<'a> { } fn handle_non_private_room(&self, room: &Room, invitation_submitter: &User, matrix_bot_user_id: UserId) -> Result<()> { - info!(self.logger, - format!("Room {} has more then two members and cannot be used as admin room", room.matrix_room_id)); + info!(self.logger, format!("Room {} has more then two members and cannot be used as admin room", room.matrix_room_id)); let body = t!(["errors", "too_many_members_in_room"]).l(&invitation_submitter.language); self.matrix_api.send_text_message_event(room.matrix_room_id.clone(), matrix_bot_user_id, body)?; self.matrix_api.leave_room(room.matrix_room_id.clone())?; @@ -176,8 +187,10 @@ impl<'a> RoomHandler<'a> { fn admin_room_language(&self, room: &Room) -> Result { let matrix_bot_user_id = self.config.matrix_bot_user_id()?; - let users: Vec = - room.users(self.connection)?.into_iter().filter(|user| user.matrix_user_id != matrix_bot_user_id).collect(); + let users: Vec = room.non_virtual_users(self.connection)? + .into_iter() + .filter(|user| user.matrix_user_id != matrix_bot_user_id) + .collect(); let user = users.first().expect("An admin room always contains another user"); Ok(user.language.clone()) } diff --git a/tests/admin_commands_bridge.rs b/tests/admin_commands_bridge.rs index 2f867f4..80e5b34 100644 --- a/tests/admin_commands_bridge.rs +++ b/tests/admin_commands_bridge.rs @@ -56,6 +56,11 @@ fn successfully_bridge_a_rocketchat_room() { let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); assert!(message_received_by_matrix.contains("joined_channel is now bridged.")); + // spec_user accepts invite from bot user + helpers::join(&test.config.as_url, + RoomId::try_from("!joined_channel_id:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); + let connection = test.connection_pool.get().unwrap(); let room = Room::find(&connection, &RoomId::try_from("!joined_channel_id:localhost").unwrap()).unwrap(); assert_eq!(room.display_name, "joined_channel"); @@ -75,13 +80,10 @@ fn successfully_bridge_a_rocketchat_room_that_an_other_user_already_bridged() { "create_room"); let other_room_members = handlers::RoomMembers { room_id: RoomId::try_from("!admin:localhost").unwrap(), - members: vec![UserId::try_from("@other_user:localhost").unwrap(), - UserId::try_from("@rocketchat:localhost").unwrap()], + members: vec![UserId::try_from("@other_user:localhost").unwrap(), UserId::try_from("@rocketchat:localhost").unwrap()], }; let path_params = get_member_events::PathParams { room_id: RoomId::try_from("!other_admin:localhost").unwrap() }; - matrix_router.get(GetMemberEventsEndpoint::request_path(path_params), - other_room_members, - "other_room_members"); + matrix_router.get(GetMemberEventsEndpoint::request_path(path_params), other_room_members, "other_room_members"); let mut rocketchat_router = Router::new(); rocketchat_router.post(LOGIN_PATH, @@ -161,6 +163,16 @@ fn successfully_bridge_a_rocketchat_room_that_an_other_user_already_bridged() { let other_message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); assert!(other_message_received_by_matrix.contains("joined_channel is now bridged.")); + // spec_user accepts invite from bot user + helpers::join(&test.config.as_url, + RoomId::try_from("!joined_channel_id:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); + + // other_user accepts invite from bot user + helpers::join(&test.config.as_url, + RoomId::try_from("!joined_channel_id:localhost").unwrap(), + UserId::try_from("@other_user:localhost").unwrap()); + let connection = test.connection_pool.get().unwrap(); let room = Room::find(&connection, &RoomId::try_from("!joined_channel_id:localhost").unwrap()).unwrap(); assert_eq!(room.display_name, "joined_channel"); @@ -171,6 +183,62 @@ fn successfully_bridge_a_rocketchat_room_that_an_other_user_already_bridged() { assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@other_user:localhost").unwrap())); } +#[test] +fn successfully_bridge_a_rocketchat_room_that_was_unbridged_before() { + let (message_forwarder, receiver) = MessageForwarder::new(); + let mut matrix_router = Router::new(); + matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); + + let test = Test::new() + .with_matrix_routes(matrix_router) + .with_rocketchat_mock() + .with_connected_admin_room() + .with_logged_in_user() + .with_bridged_room(("joined_channel", "spec_user")) + .run(); + + helpers::leave_room(&test.config.as_url, + RoomId::try_from("!joined_channel_id:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); + + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!admin:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap(), + "unbridge joined_channel".to_string()); + + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!admin:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap(), + "bridge joined_channel".to_string()); + + // spec_user accepts invite from bot user + helpers::join(&test.config.as_url, + RoomId::try_from("!joined_channel_id:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); + + // discard welcome message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard connect message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard login message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard bridge message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard unbridge message + receiver.recv_timeout(default_timeout()).unwrap(); + + let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); + assert!(message_received_by_matrix.contains("joined_channel is now bridged.")); + + let connection = test.connection_pool.get().unwrap(); + let room = Room::find(&connection, &RoomId::try_from("!joined_channel_id:localhost").unwrap()).unwrap(); + assert_eq!(room.display_name, "joined_channel"); + + let users_in_room = room.users(&connection).unwrap(); + assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@rocketchat:localhost").unwrap())); + assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@spec_user:localhost").unwrap())); +} + #[test] fn do_not_allow_to_bridge_channels_that_the_user_has_not_joined_on_the_rocketchat_server() { let (message_forwarder, receiver) = MessageForwarder::new(); @@ -264,6 +332,11 @@ fn attempting_to_bridge_an_already_bridged_channel_returns_an_error() { UserId::try_from("@spec_user:localhost").unwrap(), "bridge joined_channel".to_string()); + // spec_user accepts invite from bot user + helpers::join(&test.config.as_url, + RoomId::try_from("!joined_channel_id:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); + // discard successful bridge message receiver.recv_timeout(default_timeout()).unwrap(); @@ -319,9 +392,7 @@ fn the_user_gets_a_message_when_the_create_room_response_cannot_be_deserialized( let (message_forwarder, receiver) = MessageForwarder::new(); let mut matrix_router = Router::new(); matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); - matrix_router.post(CreateRoomEndpoint::router_path(), - handlers::InvalidJsonResponse { status: status::Ok }, - "create_room"); + matrix_router.post(CreateRoomEndpoint::router_path(), handlers::InvalidJsonResponse { status: status::Ok }, "create_room"); let mut channels = HashMap::new(); channels.insert("joined_channel", vec!["spec_user"]); let test = Test::new() diff --git a/tests/admin_commands_list.rs b/tests/admin_commands_list.rs index fc46fcd..00b3c9d 100644 --- a/tests/admin_commands_list.rs +++ b/tests/admin_commands_list.rs @@ -106,9 +106,7 @@ fn the_user_gets_a_message_when_the_room_list_cannot_be_deserialized() { matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); let mut rocketchat_router = Router::new(); rocketchat_router.get(ME_PATH, handlers::RocketchatMe { username: "spec_user".to_string() }, "me"); - rocketchat_router.get(CHANNELS_LIST_PATH, - handlers::InvalidJsonResponse { status: status::Ok }, - "channels_list"); + rocketchat_router.get(CHANNELS_LIST_PATH, handlers::InvalidJsonResponse { status: status::Ok }, "channels_list"); let test = Test::new() .with_matrix_routes(matrix_router) .with_rocketchat_mock() @@ -138,10 +136,7 @@ fn attempt_to_list_rooms_when_the_admin_room_is_not_connected() { let (message_forwarder, receiver) = MessageForwarder::new(); let mut matrix_router = Router::new(); matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); - let test = Test::new() - .with_matrix_routes(matrix_router) - .with_admin_room() - .run(); + let test = Test::new().with_matrix_routes(matrix_router).with_admin_room().run(); helpers::send_room_message_from_matrix(&test.config.as_url, RoomId::try_from("!admin:localhost").unwrap(), diff --git a/tests/admin_commands_unbridge.rs b/tests/admin_commands_unbridge.rs new file mode 100644 index 0000000..022da80 --- /dev/null +++ b/tests/admin_commands_unbridge.rs @@ -0,0 +1,225 @@ +#![feature(try_from)] + +extern crate ruma_client_api; +extern crate ruma_identifiers; +extern crate matrix_rocketchat; +extern crate matrix_rocketchat_test; +extern crate router; +extern crate serde_json; + +use std::collections::HashMap; +use std::convert::TryFrom; + +use matrix_rocketchat::api::rocketchat::Message; +use matrix_rocketchat::api::rocketchat::v1::{LOGIN_PATH, ME_PATH}; +use matrix_rocketchat::db::Room; +use matrix_rocketchat_test::{MessageForwarder, RS_TOKEN, Test, default_timeout, handlers, helpers}; +use ruma_client_api::Endpoint; +use ruma_client_api::r0::send::send_message_event::Endpoint as SendMessageEventEndpoint; +use ruma_identifiers::{RoomId, UserId}; +use router::Router; +use serde_json::to_string; + +#[test] +fn successfully_unbridge_a_rocketchat_room() { + let (message_forwarder, receiver) = MessageForwarder::new(); + let mut matrix_router = Router::new(); + matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); + + let test = Test::new() + .with_matrix_routes(matrix_router) + .with_rocketchat_mock() + .with_connected_admin_room() + .with_logged_in_user() + .with_bridged_room(("bridged_channel", "spec_user")) + .run(); + + // send message to create a virtual user + let message = Message { + message_id: "spec_id".to_string(), + token: Some(RS_TOKEN.to_string()), + channel_id: "bridged_channel_id".to_string(), + channel_name: "bridged_channel".to_string(), + user_id: "new_user_id".to_string(), + user_name: "new_user".to_string(), + text: "spec_message".to_string(), + }; + let payload = to_string(&message).unwrap(); + + helpers::simulate_message_from_rocketchat(&test.config.as_url, &payload); + + helpers::leave_room(&test.config.as_url, + RoomId::try_from("!bridged_channel_id:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); + + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!admin:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap(), + "unbridge bridged_channel".to_string()); + + // discard welcome message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard connect message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard login message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard bridged message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard message from virtual user + receiver.recv_timeout(default_timeout()).unwrap(); + + let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); + assert!(message_received_by_matrix.contains("bridged_channel is now unbridged.")); + + let connection = test.connection_pool.get().unwrap(); + let room = Room::find(&connection, &RoomId::try_from("!bridged_channel_id:localhost").unwrap()).unwrap(); + assert!(!room.is_bridged); + + let users_in_room = room.users(&connection).unwrap(); + assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@rocketchat:localhost").unwrap())); + assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@rocketchat_new_user_id_1:localhost").unwrap())); + assert!(!users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@spec_user:localhost").unwrap())); +} + +#[test] +fn do_not_allow_to_unbridge_a_channel_with_other_matrix_users() { + let (message_forwarder, receiver) = MessageForwarder::new(); + let mut matrix_router = Router::new(); + matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); + + let mut rocketchat_router = Router::new(); + rocketchat_router.post(LOGIN_PATH, + handlers::RocketchatLogin { + successful: true, + rocketchat_user_id: None, + }, + "login"); + rocketchat_router.get(ME_PATH, handlers::RocketchatMe { username: "spec_user".to_string() }, "me"); + + + let test = Test::new() + .with_matrix_routes(matrix_router) + .with_rocketchat_mock() + .with_custom_rocketchat_routes(rocketchat_router) + .with_connected_admin_room() + .with_logged_in_user() + .with_bridged_room(("bridged_channel", "spec_user")) + .run(); + + // create other admin room + helpers::create_admin_room(&test.config.as_url, + RoomId::try_from("!other_admin:localhost").unwrap(), + UserId::try_from("@other_user:localhost").unwrap(), + UserId::try_from("@rocketchat:localhost").unwrap()); + + // connect other admin room + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!other_admin:localhost").unwrap(), + UserId::try_from("@other_user:localhost").unwrap(), + format!("connect {}", test.rocketchat_mock_url.clone().unwrap())); + + // login other user + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!other_admin:localhost").unwrap(), + UserId::try_from("@other_user:localhost").unwrap(), + "login other_user secret".to_string()); + + // bridge bridged_channel for other user + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!other_admin:localhost").unwrap(), + UserId::try_from("@other_user:localhost").unwrap(), + "bridge bridged_channel".to_string()); + + // other_user accepts invite from bot user + helpers::join(&test.config.as_url, + RoomId::try_from("!bridged_channel_id:localhost").unwrap(), + UserId::try_from("@other_user:localhost").unwrap()); + + // discard welcome message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard connect message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard login message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard bridged message for spec user + receiver.recv_timeout(default_timeout()).unwrap(); + + // discard welcome message for other user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard connect message for other user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard login message for other user + receiver.recv_timeout(default_timeout()).unwrap(); + // discard bridged message for other user + receiver.recv_timeout(default_timeout()).unwrap(); + + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!admin:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap(), + "unbridge bridged_channel".to_string()); + + let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); + assert!(message_received_by_matrix.contains("Cannot unbdrige room bridged_channel, because Matrix users (@other_user:localhost, @spec_user:localhost) are still using the room.")); +} + +#[test] +fn attempting_to_unbridge_a_non_existing_channel_returns_an_error() { + let (message_forwarder, receiver) = MessageForwarder::new(); + let mut matrix_router = Router::new(); + matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); + let mut channels = HashMap::new(); + channels.insert("normal_channel", Vec::new()); + let test = Test::new() + .with_matrix_routes(matrix_router) + .with_rocketchat_mock() + .with_connected_admin_room() + .with_logged_in_user() + .with_custom_channel_list(channels) + .run(); + + // discard welcome message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard connect message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard login message + receiver.recv_timeout(default_timeout()).unwrap(); + + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!admin:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap(), + "unbridge nonexisting_channel".to_string()); + + let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); + assert!(message_received_by_matrix.contains("The channel nonexisting_channel is not bridged, cannot unbridge it.")); +} + +#[test] +fn attempting_to_unbridge_an_channel_that_is_not_bridged_returns_an_error() { + let (message_forwarder, receiver) = MessageForwarder::new(); + let mut matrix_router = Router::new(); + matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); + let mut channels = HashMap::new(); + channels.insert("normal_channel", Vec::new()); + let test = Test::new() + .with_matrix_routes(matrix_router) + .with_rocketchat_mock() + .with_connected_admin_room() + .with_logged_in_user() + .with_custom_channel_list(channels) + .run(); + + // discard welcome message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard connect message + receiver.recv_timeout(default_timeout()).unwrap(); + // discard login message + receiver.recv_timeout(default_timeout()).unwrap(); + + helpers::send_room_message_from_matrix(&test.config.as_url, + RoomId::try_from("!admin:localhost").unwrap(), + UserId::try_from("@spec_user:localhost").unwrap(), + "unbridge normal_channel".to_string()); + + let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap(); + assert!(message_received_by_matrix.contains("The channel normal_channel is not bridged, cannot unbridge it.")); +} diff --git a/tests/admin_room.rs b/tests/admin_room.rs index 310297d..b04a5c1 100644 --- a/tests/admin_room.rs +++ b/tests/admin_room.rs @@ -38,8 +38,7 @@ fn successfully_create_an_admin_room() { matrix_router.post(JoinEndpoint::router_path(), handlers::EmptyJson {}, "join"); let room_members = handlers::RoomMembers { room_id: RoomId::try_from("!admin:localhost").unwrap(), - members: vec![UserId::try_from("@spec_user:localhost").unwrap(), - UserId::try_from("@rocketchat:localhost").unwrap()], + members: vec![UserId::try_from("@spec_user:localhost").unwrap(), UserId::try_from("@rocketchat:localhost").unwrap()], }; matrix_router.get(GetMemberEventsEndpoint::router_path(), room_members, "get_member_events"); matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); @@ -93,21 +92,19 @@ fn attempt_to_create_an_admin_room_with_other_users_in_it() { let spec_user_in_room_error = UserInRoom::find(&connection, &UserId::try_from("@spec_user:localhost").unwrap(), &RoomId::try_from("!admin:localhost").unwrap()) - .err() - .unwrap(); + .err() + .unwrap(); let spec_user_in_room_diesel_error = spec_user_in_room_error.error_chain.iter().nth(1).unwrap(); - assert_eq!(format!("{}", spec_user_in_room_diesel_error), - format!("{}", DieselError::NotFound)); + assert_eq!(format!("{}", spec_user_in_room_diesel_error), format!("{}", DieselError::NotFound)); let bot_user_in_room_error = UserInRoom::find(&connection, &UserId::try_from("@rocketchat:localhost").unwrap(), &RoomId::try_from("!admin:localhost").unwrap()) - .err() - .unwrap(); + .err() + .unwrap(); let bot_user_in_room_diesel_error = bot_user_in_room_error.error_chain.iter().nth(1).unwrap(); - assert_eq!(format!("{}", bot_user_in_room_diesel_error), - format!("{}", DieselError::NotFound)); + assert_eq!(format!("{}", bot_user_in_room_diesel_error), format!("{}", DieselError::NotFound)); } #[test] @@ -137,20 +134,18 @@ fn bot_leaves_and_forgets_the_room_when_the_user_leaves_it() { let spec_user_in_room_error = UserInRoom::find(&connection, &UserId::try_from("@spec_user:localhost").unwrap(), &RoomId::try_from("!admin:localhost").unwrap()) - .err() - .unwrap(); + .err() + .unwrap(); let spec_user_in_room_diesel_error = spec_user_in_room_error.error_chain.iter().nth(1).unwrap(); - assert_eq!(format!("{}", spec_user_in_room_diesel_error), - format!("{}", DieselError::NotFound)); + assert_eq!(format!("{}", spec_user_in_room_diesel_error), format!("{}", DieselError::NotFound)); let bot_user_in_room_error = UserInRoom::find(&connection, &UserId::try_from("@rocketchat:localhost").unwrap(), &RoomId::try_from("!admin:localhost").unwrap()) - .err() - .unwrap(); + .err() + .unwrap(); let bot_user_in_room_diesel_error = bot_user_in_room_error.error_chain.iter().nth(1).unwrap(); - assert_eq!(format!("{}", bot_user_in_room_diesel_error), - format!("{}", DieselError::NotFound)); + assert_eq!(format!("{}", bot_user_in_room_diesel_error), format!("{}", DieselError::NotFound)); } #[test] @@ -183,8 +178,7 @@ fn the_user_gets_a_message_when_joining_the_room_failes_for_the_bot_user() { matrix_router.post(JoinEndpoint::router_path(), error_responder, "join"); let room_members = handlers::RoomMembers { room_id: RoomId::try_from("!admin:localhost").unwrap(), - members: vec![UserId::try_from("@spec_user:localhost").unwrap(), - UserId::try_from("@rocketchat:localhost").unwrap()], + members: vec![UserId::try_from("@spec_user:localhost").unwrap(), UserId::try_from("@rocketchat:localhost").unwrap()], }; matrix_router.get(GetMemberEventsEndpoint::router_path(), room_members, "get_member_events"); matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); @@ -267,13 +261,10 @@ fn the_user_gets_a_message_when_setting_the_room_display_name_fails() { status: status::InternalServerError, message: "Could not set display name for room".to_string(), }; - matrix_router.put(SendStateEventForEmptyKeyEndpoint::router_path(), - error_responder, - "send_state_event_for_empty_key"); + matrix_router.put(SendStateEventForEmptyKeyEndpoint::router_path(), error_responder, "send_state_event_for_empty_key"); let room_members = handlers::RoomMembers { room_id: RoomId::try_from("!admin:localhost").unwrap(), - members: vec![UserId::try_from("@spec_user:localhost").unwrap(), - UserId::try_from("@rocketchat:localhost").unwrap()], + members: vec![UserId::try_from("@spec_user:localhost").unwrap(), UserId::try_from("@rocketchat:localhost").unwrap()], }; matrix_router.get(GetMemberEventsEndpoint::router_path(), room_members, "get_member_events"); matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); @@ -369,8 +360,7 @@ fn bot_leaves_when_a_third_user_joins_the_admin_room() { matrix_router.post(JoinEndpoint::router_path(), handlers::EmptyJson {}, "join"); let room_members = handlers::RoomMembers { room_id: RoomId::try_from("!admin:localhost").unwrap(), - members: vec![UserId::try_from("@spec_user:localhost").unwrap(), - UserId::try_from("@rocketchat:localhost").unwrap()], + members: vec![UserId::try_from("@spec_user:localhost").unwrap(), UserId::try_from("@rocketchat:localhost").unwrap()], }; matrix_router.get(GetMemberEventsEndpoint::router_path(), room_members, "get_member_events"); matrix_router.put(SendMessageEventEndpoint::router_path(), message_forwarder, "send_message_event"); diff --git a/tests/matrix-rocketchat-test/lib.rs b/tests/matrix-rocketchat-test/lib.rs index b959306..6b05996 100644 --- a/tests/matrix-rocketchat-test/lib.rs +++ b/tests/matrix-rocketchat-test/lib.rs @@ -236,9 +236,7 @@ impl Test { None => Router::new(), }; - router.get("/_matrix/client/versions", - handlers::MatrixVersion { versions: default_matrix_api_versions() }, - "versions"); + router.get("/_matrix/client/versions", handlers::MatrixVersion { versions: default_matrix_api_versions() }, "versions"); router.post("*", handlers::EmptyJson {}, "default_post"); router.put("*", handlers::EmptyJson {}, "default_put"); if self.with_admin_room || self.with_connected_admin_room { @@ -279,9 +277,7 @@ impl Test { None => Router::new(), }; - router.get("/api/info", - handlers::RocketchatInfo { version: DEFAULT_ROCKETCHAT_VERSION }, - "info"); + router.get("/api/info", handlers::RocketchatInfo { version: DEFAULT_ROCKETCHAT_VERSION }, "info"); if self.with_logged_in_user { router.post(LOGIN_PATH, @@ -381,6 +377,11 @@ impl Test { RoomId::try_from("!admin:localhost").unwrap(), UserId::try_from("@spec_user:localhost").unwrap(), format!("bridge {}", room_name)); + + // spec_user accepts invite from bot user + helpers::join(&self.config.as_url, + RoomId::try_from(&format!("!{}_id:localhost", room_name)).unwrap(), + UserId::try_from("@spec_user:localhost").unwrap()); } } diff --git a/tests/matrix-rocketchat-test/message_forwarder.rs b/tests/matrix-rocketchat-test/message_forwarder.rs index dc78d2b..b7999ce 100644 --- a/tests/matrix-rocketchat-test/message_forwarder.rs +++ b/tests/matrix-rocketchat-test/message_forwarder.rs @@ -24,11 +24,7 @@ impl Handler for MessageForwarder { fn handle(&self, request: &mut Request) -> IronResult { let mut payload = String::new(); request.body.read_to_string(&mut payload).unwrap(); - self.tx - .lock() - .unwrap() - .send(payload) - .unwrap(); + self.tx.lock().unwrap().send(payload).unwrap(); Ok(Response::with((status::Ok, "{}".to_string()))) } diff --git a/tests/transactions.rs b/tests/transactions.rs index 4751e67..d75bbad 100644 --- a/tests/transactions.rs +++ b/tests/transactions.rs @@ -23,7 +23,7 @@ use ruma_identifiers::{EventId, RoomId, UserId}; use serde_json::to_string; #[test] -fn homeserver_sends_mal_formatted_json() { +fn homeserver_sends_malformated_json() { let test = Test::new().run(); let payload = "bad_json"; @@ -32,7 +32,9 @@ fn homeserver_sends_mal_formatted_json() { params.insert("access_token", HS_TOKEN); let (_, status_code) = RestApi::call(Method::Put, &url, payload, ¶ms, None).unwrap(); - assert_eq!(status_code, StatusCode::UnprocessableEntity) + // the application service does not return an error, because the homeserver would resend the + // message which doesn't help, because the message will still be malformated. + assert_eq!(status_code, StatusCode::Ok) } #[test]