Changeset - 47bc0f5ac52f
[Not reviewed]
0 3 0
Jan Kaluza - 10 years ago 2016-02-20 16:35:34
jkaluza@redhat.com
Support showing examples in web interface join room dialog
3 files changed with 57 insertions and 9 deletions:
0 comments (0 inline, 0 general)
spectrum/src/frontends/slack/SlackUserManager.cpp
Show inline comments
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "SlackUserManager.h"
 
#include "SlackUserRegistration.h"
 
#include "SlackFrontend.h"
 
#include "SlackSession.h"
 
#include "SlackUser.h"
 

	
 
#include "transport/User.h"
 
#include "transport/Transport.h"
 
#include "transport/StorageBackend.h"
 
#include "transport/Logging.h"
 
#include "transport/Config.h"
 

	
 
#include <boost/algorithm/string.hpp>
 
#include <boost/foreach.hpp>
 

	
 
#include <Swiften/Version.h>
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SlackUserManager");
 

	
 
SlackUserManager::SlackUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) : UserManager(component, userRegistry, storageBackend) {
 
	m_component = component;
 
	m_storageBackend = storageBackend;
 
    m_userRegistration = new SlackUserRegistration(component, this, storageBackend);
 

	
 
	onUserCreated.connect(boost::bind(&SlackUserManager::handleUserCreated, this, _1));
 
}
 

	
 
SlackUserManager::~SlackUserManager() {
 
    delete m_userRegistration;
 
}
 

	
 
void SlackUserManager::reconnectUser(const std::string &user) {
 
	UserInfo uinfo;
 
	if (!m_storageBackend->getUser(user, uinfo)) {
 
		LOG4CXX_ERROR(logger, "User " << user << " tried to reconnect, but he's not registered.");
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, "Connecting user " << user << " to Slack network.");
 
	m_tempSessions[user] = new SlackSession(m_component, m_storageBackend, uinfo);
 
}
 

	
 
void SlackUserManager::sendVCard(unsigned int id, Swift::VCard::ref vcard) {
 

	
 
}
 

	
 
void SlackUserManager::sendMessage(boost::shared_ptr<Swift::Message> message) {
 
	User *user = getUser(message->getTo().toBare().toString());
 
	if (!user) {
 
		LOG4CXX_ERROR(logger, "Received message for unknown user " << message->getTo().toBare().toString());
 
		return;
 
	}
 

	
 
	static_cast<SlackUser *>(user)->getSession()->sendMessage(message);
 
}
 

	
 
@@ -88,96 +89,120 @@ SlackSession *SlackUserManager::moveTempSession(const std::string &user) {
 
void SlackUserManager::moveTempSession(const std::string &user, SlackSession *session) {
 
	m_tempSessions[user] = session;
 
	session->setUser(NULL);
 
}
 

	
 

	
 
UserRegistration *SlackUserManager::getUserRegistration() {
 
	return m_userRegistration;
 
}
 

	
 
std::string SlackUserManager::handleOAuth2Code(const std::string &code, const std::string &state) {
 
	return static_cast<SlackUserRegistration *>(m_userRegistration)->handleOAuth2Code(code, state);
 
}
 

	
 
std::string SlackUserManager::getOAuth2URL(const std::vector<std::string> &args) {
 
	return static_cast<SlackUserRegistration *>(m_userRegistration)->createOAuth2URL(args);
 
}
 

	
 
void SlackUserManager::handleUserCreated(User *user) {
 
	LOG4CXX_INFO(logger, "handleUserCreated");
 
	static_cast<SlackUser *>(user)->getSession()->handleConnected();
 
}
 

	
 
bool SlackUserManager::handleAdminMessage(Swift::Message::ref message) {
 
#if HAVE_SWIFTEN_3
 
	std::string body = message->getBody().get_value_or("");
 
#else
 
	std::string body = message->getBody();
 
#endif
 

	
 
	if (body.find("list_rooms") == 0) {
 
		std::vector<std::string> args;
 
		boost::split(args, body, boost::is_any_of(" "));
 
		if (args.size() == 2) {
 
			UserInfo uinfo;
 
			if (!m_storageBackend->getUser(args[1], uinfo)) {
 
				message->setBody("Error: Unknown user");
 
				return true;
 
			}
 

	
 
			std::string rooms = "";
 
			int type = (int) TYPE_STRING;
 
			m_storageBackend->getUserSetting(uinfo.id, "rooms", type, rooms);
 

	
 
			message->setBody(rooms);
 
			return true;
 
		}
 
	}
 
	else if (body.find("join_room_fields") == 0) {
 
		std::string ret;
 

	
 
		Config *cfg = m_component->getConfig();
 
		ret += CONFIG_STRING_DEFAULTED(cfg, "service.join_room_nickname_label", "Nickname in 3rd-party room") + "\n";
 
		std::string room_name = CONFIG_STRING_DEFAULTED(cfg, "service.join_room_room_label", "3rd-party room name");
 
		if (room_name[0] == '%') {
 
			room_name[0] = '#';
 
		}
 
		ret += room_name + "\n";
 
		ret += CONFIG_STRING_DEFAULTED(cfg, "service.join_room_server_label", "3rd-party server") + "\n";
 
		ret += "Slack Channel\n";
 
		ret += CONFIG_STRING_DEFAULTED(cfg, "service.join_room_nickname_example", "BotNickname") + "\n";
 
		room_name = CONFIG_STRING_DEFAULTED(cfg, "service.join_room_room_example", "3rd-party room name");
 
		if (room_name[0] == '%') {
 
			room_name[0] = '#';
 
		}
 
		ret += room_name + "\n";
 
		ret += CONFIG_STRING_DEFAULTED(cfg, "service.join_room_server_example", "3rd.party.server.org") + "\n";
 
		ret += "mychannel";
 

	
 
		message->setBody(ret);
 
		return true;
 
	}
 
	else if (body.find("join_room ") == 0) {
 
		std::vector<std::string> args;
 
		boost::split(args, body, boost::is_any_of(" "));
 
		if (args.size() == 6) {
 
			UserInfo uinfo;
 
			if (!m_storageBackend->getUser(args[1], uinfo)) {
 
				message->setBody("Error: Unknown user");
 
				return true;
 
			}
 

	
 
			std::string rooms = "";
 
			int type = (int) TYPE_STRING;
 
			m_storageBackend->getUserSetting(uinfo.id, "rooms", type, rooms);
 
			rooms += body + "\n";
 
			m_storageBackend->updateUserSetting(uinfo.id, "rooms", rooms);
 

	
 
			SlackUser *user = static_cast<SlackUser *>(getUser(args[1]));
 
			if (user) {
 
				user->getSession()->handleJoinMessage("", args, true);
 
			}
 
			message->setBody("Joined the room");
 
			return true;
 
		}
 
	}
 
	else if (body.find("leave_room ") == 0) {
 
		std::vector<std::string> args;
 
		boost::split(args, body, boost::is_any_of(" "));
 
		if (args.size() == 3) {
 
			UserInfo uinfo;
 
			if (!m_storageBackend->getUser(args[1], uinfo)) {
 
				message->setBody("Error: Unknown user");
 
				return true;
 
			}
 

	
 
			std::string rooms = "";
 
			int type = (int) TYPE_STRING;
 
			m_storageBackend->getUserSetting(uinfo.id, "rooms", type, rooms);
 

	
 
			std::vector<std::string> commands;
 
			boost::split(commands, rooms, boost::is_any_of("\n"));
 
			rooms = "";
 

	
 
			BOOST_FOREACH(const std::string &command, commands) {
 
				if (command.size() > 5) {
 
					std::vector<std::string> args2;
 
					boost::split(args2, command, boost::is_any_of(" "));
 
					if (args2.size() == 6) {
 
						if (args[2] != args2[5]) {
spectrum_manager/src/APIServer.cpp
Show inline comments
 
@@ -313,104 +313,127 @@ void APIServer::serve_instances_join_room(Server *server, Server::session *sessi
 
		return;
 
	}
 

	
 
	std::string name = get_http_var(hm, "name");
 
	boost::replace_all(name, " ", "_");
 
	std::string legacy_room = get_http_var(hm, "legacy_room");
 
	std::string legacy_server = get_http_var(hm, "legacy_server");
 
	std::string frontend_room = get_http_var(hm, "frontend_room");
 

	
 
	std::string response = server->send_command(instance, "join_room " +
 
		username + " " + name + " " + legacy_room + " " + legacy_server + " " + frontend_room);
 

	
 
	if (response.find("Joined the room") == std::string::npos) {
 
		send_ack(conn, true, response);
 
	}
 
	else {
 
		send_ack(conn, false, response);
 
	}
 
}
 

	
 
void APIServer::serve_instances_leave_room(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string instance = uri.substr(uri.rfind("/") + 1);
 

	
 
	UserInfo info;
 
	m_storage->getUser(session->user, info);
 

	
 
	std::string username = "";
 
	int type = (int) TYPE_STRING;
 
	m_storage->getUserSetting(info.id, instance, type, username);
 

	
 
	if (username.empty()) {
 
		send_ack(conn, true, "You are not registered to this Spectrum 2 instance.");
 
		return;
 
	}
 

	
 
	std::string frontend_room = get_http_var(hm, "frontend_room");
 
	std::string response = server->send_command(instance, "leave_room " + username + " " + frontend_room);
 

	
 
	if (response.find("Left the room") == std::string::npos) {
 
		send_ack(conn, true, response);
 
	}
 
	else {
 
		send_ack(conn, false, response);
 
	}
 
}
 

	
 
void APIServer::serve_instances_join_room_form(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string instance = uri.substr(uri.rfind("/") + 1);
 

	
 
	// So far we support just Slack here. For XMPP, it is up to user to initiate the join room request.
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	json.AddMember("name_label", "Nickname in 3rd-party room", json.GetAllocator());
 
	json.AddMember("legacy_room_label", "3rd-party room name", json.GetAllocator());
 
	json.AddMember("legacy_server_label", "3rd-party server", json.GetAllocator());
 
	json.AddMember("frontend_room_label", "Slack channel", json.GetAllocator());
 

	
 
	std::string response = server->send_command(instance, "join_room_fields");
 
	std::vector<std::string> fields;
 
	boost::split(fields, response, boost::is_any_of("\n"));
 

	
 
	if (fields.size() != 8) {
 
		fields.push_back("Nickname in 3rd-party room");
 
		fields.push_back("3rd-party room name");
 
		fields.push_back("3rd-party server");
 
		fields.push_back("Slack Channel");
 
		fields.push_back("BotNickname");
 
		fields.push_back("room_name");
 
		fields.push_back("3rd.party.server.org");
 
		fields.push_back("mychannel");
 
	}
 

	
 
	json.AddMember("name_label", fields[0].c_str(), json.GetAllocator());
 
	json.AddMember("legacy_room_label", fields[1].c_str(), json.GetAllocator());
 
	json.AddMember("legacy_server_label", fields[2].c_str(), json.GetAllocator());
 
	json.AddMember("frontend_room_label", fields[3].c_str(), json.GetAllocator());
 
	json.AddMember("name_example", fields[4].c_str(), json.GetAllocator());
 
	json.AddMember("legacy_room_example", fields[5].c_str(), json.GetAllocator());
 
	json.AddMember("legacy_server_example", fields[6].c_str(), json.GetAllocator());
 
	json.AddMember("frontend_room_example", fields[7].c_str(), json.GetAllocator());
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_instances_register_form(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string instance = uri.substr(uri.rfind("/") + 1);
 

	
 
	std::string response = server->send_command(instance, "registration_fields");
 
	std::vector<std::string> fields;
 
	boost::split(fields, response, boost::is_any_of("\n"));
 

	
 
	if (fields.empty()) {
 
		fields.push_back("Jabber ID");
 
		fields.push_back("3rd-party network username");
 
		fields.push_back("3rd-party network password");
 
	}
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	json.AddMember("username_label", fields[0].c_str(), json.GetAllocator());
 
	json.AddMember("legacy_username_label", fields.size() >= 2 ? fields[1].c_str() : "", json.GetAllocator());
 
	json.AddMember("password_label", fields.size() >= 3 ? fields[2].c_str() : "", json.GetAllocator());
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_users(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	ALLOW_ONLY_ADMIN();
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 

	
 
	std::vector<std::string> list;
 
	m_storage->getUsers(list);
 

	
 
	Value users(kArrayType);
 
	BOOST_FOREACH(std::string &id, list) {
 
		Value user;
 
		user.SetObject();
 
		user.AddMember("username", id.c_str(), json.GetAllocator());
 
		users.PushBack(user, json.GetAllocator());
 
	}
 

	
 
	json.AddMember("users", users, json.GetAllocator());
 
	send_json(conn, json);
 
}
 

	
spectrum_manager/src/html/js/app.js
Show inline comments
 
function getQueryParams(qs) {
 
	qs = qs.split('+').join(' ');
 

	
 
	var params = {},
 
		tokens,
 
		re = /[?&]?([^=]+)=([^&]*)/g;
 

	
 
	while (tokens = re.exec(qs)) {
 
		params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
 
	}
 

	
 
	return params;
 
}
 

	
 
function show_instances() {
 
	$.get($.cookie("base_location") + "api/v1/instances", function(data) {
 
		$("#main_content").html("<h2>List of Spectrum 2 instances</h2><table id='main_result'><tr><th>Name<th>Status</th><th>Actions</th></tr>");
 

	
 
		var admin = $.cookie("admin") == "1";
 
		$.each(data.instances, function(i, instance) {
 
			if (instance.running) {
 
				if (admin) {
 
					var command = instance.running ? "stop" : "start";
 
				}
 
				else {
 
					var command = instance.registered ? "unregister" : "register";
 
					if (instance.registered) {
 
						instance.status += "<br/>Registered as " + instance.username;
 
					}
 
				}
 
			}
 
			else if (admin) {
 
				var command = "start";
 
			}
 
			else {
 
				var command = "";
 
			}
 
			var row = '<tr>'
 
			row += '<td>' + instance.name + '</td>'
 
			row += '<td>' + instance.status + '</td>'
 

	
 
			if (command == 'register') {
 
				row += '<td><a class="button_command" href="' + $.cookie("base_location") + 'instances/register.shtml?id=' + instance.id + '">' + command + '</a>' + '</td></tr>';
 
				row += '<td><a href="' + $.cookie("base_location") + 'instances/register.shtml?id=' + instance.id + '">' + command + '</a>' + '</td></tr>';
 
				$("#main_result  > tbody:last-child").append(row);
 
			}
 
			else if (command == "") {
 
				row += '<td></td></tr>';
 
				$("#main_result  > tbody:last-child").append(row);
 
			}
 
			else {
 
				row += '<td>';
 
				if (command == 'unregister' && instance.frontend == "slack") {
 
					row += '<a href="' + $.cookie("base_location") + 'instances/join_room.shtml?id=' + instance.id + '">Join room</a> | ';
 
					row += '<a href="' + $.cookie("base_location") + 'instances/list_rooms.shtml?id=' + instance.id + '">List joined rooms</a> | ';
 
				}
 
				row += '<a class="button_command" href="' + $.cookie("base_location") +  'api/v1/instances/' + command + '/' + instance.id + '">' + command + '</a>';
 
				row += '</td></tr>';
 
				$("#main_result  > tbody:last-child").append(row);
 
				$(".button_command").click(function(e) {
 
					e.preventDefault();
 
					$(this).parent().empty().progressbar( {value: false} ).css('height', '1em');
 

	
 
					var url = $(this).attr('href');
 
					$.get(url, function(data) {
 
						show_instances();
 
					});
 
				})
 
			}
 
		});
 
	});
 
}
 

	
 
function show_list_rooms() {
 
	var query = getQueryParams(document.location.search);
 
	$.get($.cookie("base_location") + "api/v1/instances/list_rooms/" + query.id, function(data) {
 
		$("#main_content").html("<h2>Joined rooms</h2><table id='main_result'><tr><th>" + data.frontend_room_label + "</th><th>" + data.legacy_room_label + "</th><th>" + data.legacy_server_label + "</th><th>" + data.name_label + "</th><th>Actions</th></tr>");
 

	
 
		$.each(data.rooms, function(i, room) {
 
			var row = '<tr>';
 
			row += '<td>' + room.frontend_room + '</td>';
 
			row += '<td>' + room.legacy_room + '</td>';
 
			row += '<td>' + room.legacy_server + '</td>';
 
			row += '<td>' + room.name + '</td>';
 
			row += '<td><a class="button_command" href="' + $.cookie("base_location") +  'api/v1/instances/leave_room/' + query.id + '?frontend_room=' + encodeURIComponent(room.frontend_room) + '">Leave</a></td>';
 
			row += '</tr>';
 

	
 
			$("#main_result  > tbody:last-child").append(row);
 
			$(".button_command").click(function(e) {
 
				e.preventDefault();
 
				$(this).parent().empty().progressbar( {value: false} ).css('height', '1em');
 

	
 
@@ -107,100 +107,100 @@ function show_users() {
 

	
 
	$.get($.cookie("base_location") + "api/v1/users", function(data) {
 
		$("#main_content").html("<h2>List of Spectrum 2 users</h2><p>You can add new users <a href=\"register.shtml?back_to_list=1\">here</a>.</p><table id='main_result'><tr><th>Name<th>Actions</th></tr>");
 

	
 
		$.each(data.users, function(i, user) {
 
			var row = '<tr>'
 
			row += '<td>' + user.username + '</td>'
 
			row += '<td><a class="button_command" href="' + $.cookie("base_location") +  'api/v1/users/remove/' + user.username + '">remove</a></td></tr>';
 
			$("#main_result  > tbody:last-child").append(row);
 
			$(".button_command").click(function(e) {
 
				e.preventDefault();
 
				$(this).parent().empty().progressbar( {value: false} ).css('height', '1em');
 

	
 
				var url = $(this).attr('href');
 
				$.get(url, function(data) {
 
					show_users();
 
				});
 
			})
 
		});
 
	});
 
}
 

	
 
function fill_instances_join_room_form() {
 
	var query = getQueryParams(document.location.search);
 
	$("#instance").attr("value", query.id);
 

	
 
	$(".button_command").click(function(e) {
 
		e.preventDefault();
 
		$(this).parent().empty().progressbar( {value: false} ).css('height', '1em');
 

	
 
		var postdata ={
 
			"name": $("#name").val(),
 
			"legacy_room": $("#legacy_room").val(),
 
			"legacy_server": $("#legacy_server").val(),
 
			"frontend_room": $("#frontend_room").val()
 
		};
 

	
 
		$.post($.cookie("base_location") + "api/v1/instances/join_room/" + $("#instance").val(), postdata, function(data) {
 
			window.location.replace("index.shtml");
 
		});
 
	})
 
	
 
	$.get($.cookie("base_location") + "api/v1/instances/join_room_form/" + query.id, function(data) {
 
		$("#name_desc").html(data.name_label + ":");
 
		$("#legacy_room_desc").html(data.legacy_room_label + ":");
 
		$("#legacy_server_desc").html(data.legacy_server_label + ":");
 
		$("#frontend_room_desc").html(data.frontend_room_label + ":");
 

	
 
		$("#name").attr("placeholder", data.name_label + ":");
 
		$("#legacy_room").attr("placeholder", data.legacy_room_label + ":");
 
		$("#legacy_server").attr("placeholder", data.legacy_server_label + ":");
 
		$("#frontend_room").attr("placeholder", data.frontend_room_label + ":");
 
		$("#name").attr("placeholder", data.name_example);
 
		$("#legacy_room").attr("placeholder", data.legacy_room_example);
 
		$("#legacy_server").attr("placeholder", data.legacy_server_example);
 
		$("#frontend_room").attr("placeholder", data.frontend_room_example);
 
	});
 
}
 

	
 
function fill_instances_register_form() {
 
	var query = getQueryParams(document.location.search);
 
	$("#instance").attr("value", query.id);
 

	
 
	$(".button_command").click(function(e) {
 
		e.preventDefault();
 
		$(this).parent().empty().progressbar( {value: false} ).css('height', '1em');
 

	
 
		var postdata ={
 
			"jid": $("#jid").val(),
 
			"uin": $("#uin").val(),
 
			"password": $("#password").val()
 
		};
 

	
 
		$.post($.cookie("base_location") + "api/v1/instances/register/" + $("#instance").val(), postdata, function(data) {
 
			if (data.oauth2_url) {
 
				window.location.replace(data.oauth2_url);
 
			}
 
			else {
 
				window.location.replace("index.shtml");
 
			}
 
		});
 
	})
 
	
 
	$.get($.cookie("base_location") + "api/v1/instances/register_form/" + query.id, function(data) {
 
		$("#jid_desc").html(data.username_label + ":");
 
		$("#jid").attr("placeholder", data.username_label);
 

	
 
		if (data.legacy_username_label.length == 0) {
 
			$('#uin_label').hide();
 
		}
 
		else {
 
			$("#uin_desc").html(data.legacy_username_label + ":");
 
			$("#uin").attr("placeholder", data.legacy_username_label);
 
		}
 

	
 
		if (data.password_label.length == 0) {
 
			$('#password_label').hide();
 
		}
 
		else {
 
			$("#password_desc").html(data.password_label + ":");
 
			$("#password").attr("placeholder", data.password_label);
 
		}
 
	});
 
}
0 comments (0 inline, 0 general)