Skip to content

Commit

Permalink
Allow two matrix users to bridge the same Rocket.Chat room
Browse files Browse the repository at this point in the history
This creates one matrix room for both users
  • Loading branch information
exul committed Feb 26, 2017
1 parent 5d5029c commit d92ddd3
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 23 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 28 additions & 19 deletions src/matrix-rocketchat/handlers/events/command_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,27 +250,36 @@ impl<'a> CommandHandler<'a> {
.with_vars(vec![("channel_name", channel_name.to_string())]));
}

let matrix_room_id = self.matrix_api.create_room(channel.name.clone(), event.user_id.clone())?;
let new_room = NewRoom {
matrix_room_id: matrix_room_id,
display_name: channel.name.clone(),
rocketchat_server_id: Some(rocketchat_server.id),
rocketchat_room_id: Some(channel.id.clone()),
is_admin_room: false,
is_bridged: true,
};

let room = Room::insert(self.connection, &new_room)?;
let user = user_on_rocketchat_server.user(self.connection)?;
let bot_matrix_user_id = self.config.matrix_bot_user_id()?;

for matrix_user_id in vec![user.matrix_user_id, bot_matrix_user_id.clone()] {
let new_user_in_room = NewUserInRoom {
matrix_user_id: 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 => {
let matrix_room_id = self.matrix_api.create_room(channel.name.clone(), event.user_id.clone())?;
let new_room = NewRoom {
matrix_room_id: matrix_room_id,
display_name: channel.name.clone(),
rocketchat_server_id: Some(rocketchat_server.id),
rocketchat_room_id: Some(channel.id.clone()),
is_admin_room: false,
is_bridged: true,
};
let room = Room::insert(self.connection, &new_room)?;
let new_user_in_room = NewUserInRoom {
matrix_user_id: bot_matrix_user_id.clone(),
matrix_room_id: room.matrix_room_id.clone(),
};
UserInRoom::insert(self.connection, &new_user_in_room)?;
room
}
};
UserInRoom::insert(self.connection, &new_user_in_room)?;
}

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(),
};
UserInRoom::insert(self.connection, &new_user_in_room)?;

let message = t!(["admin_room", "room_successfully_bridged"])
.with_vars(vec![("channel_name", channel.name.clone())]);
Expand Down
103 changes: 103 additions & 0 deletions tests/admin_commands_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ use std::collections::HashMap;
use std::convert::TryFrom;

use iron::status;
use matrix_rocketchat::api::rocketchat::v1::{LOGIN_PATH, ME_PATH};
use matrix_rocketchat::db::Room;
use matrix_rocketchat_test::{MessageForwarder, Test, default_timeout, handlers, helpers};
use router::Router;
use ruma_client_api::Endpoint;
use ruma_client_api::r0::room::create_room::Endpoint as CreateRoomEndpoint;
use ruma_client_api::r0::send::send_message_event::Endpoint as SendMessageEventEndpoint;
use ruma_client_api::r0::sync::get_member_events::{self, Endpoint as GetMemberEventsEndpoint};
use ruma_identifiers::{RoomId, UserId};


Expand Down Expand Up @@ -63,6 +65,107 @@ fn successfully_bridge_a_rocketchat_room() {
assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@spec_user:localhost").unwrap()));
}

#[test]
fn successfully_bridge_a_rocketchat_room_that_an_other_user_already_bridged() {
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::MatrixCreateRoom { room_id: RoomId::try_from("!joined_channel_id:localhost").unwrap() },
"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()],
};
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");

let mut rocketchat_router = Router::new();
rocketchat_router.post(LOGIN_PATH, handlers::RocketchatLogin { successful: true }, "login");
rocketchat_router.get(ME_PATH, handlers::RocketchatMe { username: "spec_user".to_string() }, "me");

let mut channels = HashMap::new();
channels.insert("joined_channel", vec!["spec_user", "other_user"]);

let test = Test::new()
.with_matrix_routes(matrix_router)
.with_rocketchat_mock()
.with_custom_rocketchat_routes(rocketchat_router)
.with_connected_admin_room()
.with_custom_channel_list(channels)
.run();

// login spec user
helpers::send_room_message_from_matrix(&test.config.as_url,
RoomId::try_from("!admin:localhost").unwrap(),
UserId::try_from("@spec_user:localhost").unwrap(),
"login spec_user secret".to_string());

// 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());

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 joined_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 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();

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 received success message
let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap();
assert!(message_received_by_matrix.contains("joined_channel is now bridged."));

// other user received success message
let other_message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap();
assert!(other_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()));
assert!(users_in_room.iter().any(|u| u.matrix_user_id == UserId::try_from("@other_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();
Expand Down
1 change: 0 additions & 1 deletion tests/admin_commands_login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ fn sucessfully_login_via_chat_mesage() {
rocketchat_server.id)
.unwrap();
assert_eq!(user_on_rocketchat_server.rocketchat_auth_token.unwrap(), "spec_auth_token");
assert_eq!(user_on_rocketchat_server.rocketchat_user_id.unwrap(), "spec_user_id");

let message_received_by_matrix = receiver.recv_timeout(default_timeout()).unwrap();
assert!(message_received_by_matrix.contains("You are logged in."));
Expand Down
1 change: 1 addition & 0 deletions tests/matrix-rocketchat-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ lazy_static = "0.2"
matrix_rocketchat = { path = "../.." }
r2d2 = "0.7"
r2d2-diesel = "0.9"
rand = "0.3"
reqwest = "0.3"
router = "0.5"
ruma-client-api = { git = "https://github.com/ruma/ruma-client-api.git" }
Expand Down
11 changes: 8 additions & 3 deletions tests/matrix-rocketchat-test/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::HashMap;
use rand::{Rng, thread_rng};

use iron::prelude::*;
use iron::{Handler, status};
Expand Down Expand Up @@ -32,23 +33,27 @@ pub struct RocketchatLogin {

impl Handler for RocketchatLogin {
fn handle(&self, _request: &mut Request) -> IronResult<Response> {

let (status, payload) = match self.successful {
true => {
let user_id: String = thread_rng().gen_ascii_chars().take(10).collect();
(status::Ok,
r#"{
"status": "success",
"data": {
"authToken": "spec_auth_token",
"userId": "spec_user_id"
"userId": "USER_ID"
}
}"#)
}"#
.replace("USER_ID", &user_id))
}
false => {
(status::Unauthorized,
r#"{
"status": "error",
"message": "Unauthorized"
}"#)
}"#
.to_string())
}
};

Expand Down
1 change: 1 addition & 0 deletions tests/matrix-rocketchat-test/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern crate lazy_static;
extern crate matrix_rocketchat;
extern crate r2d2;
extern crate r2d2_diesel;
extern crate rand;
extern crate reqwest;
extern crate ruma_client_api;
extern crate ruma_events;
Expand Down

0 comments on commit d92ddd3

Please sign in to comment.