Changeset - fe69cbd7a13f
[Not reviewed]
0 6 0
Jan Kaluza - 9 years ago 2016-03-06 20:13:52
jkaluza@redhat.com
Web interface: support diplaying tables generated on transport's side
6 files changed with 111 insertions and 28 deletions:
0 comments (0 inline, 0 general)
include/transport/AdminInterfaceCommand.h
Show inline comments
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2016, 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
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <map>
 

	
 
#include "Swiften/Elements/Message.h"
 
#include "transport/StorageBackend.h"
 

	
 
namespace Transport {
 

	
 
class User;
 

	
 
class AdminInterfaceCommand {
 
	public:
 
		typedef enum {
 
			GlobalContext,
 
			UserContext
 
		} Context;
 

	
 
		typedef enum {
 
			None = 0,
 
			Get = 1,
 
			Set = 2,
 
			Execute = 4
 
		} Actions;
 

	
 
		typedef enum {
 
			AdminMode,
 
			UserMode
 
		} AccessMode;
 

	
 
		typedef enum {
 
			General,
 
			Users,
 
			Messages,
 
			Frontend,
 
			Backends,
 
			Memory
 
		} Category;
 

	
 
		class Arg {
 
			public:
 
				Arg(const std::string &_name, const std::string &_label, const std::string &_example) :
 
					name(_name), label(_label), example(_example) {}
 
				Arg(const std::string &_name, const std::string &_label, const std::string &_type, const std::string &_example) :
 
					name(_name), label(_label), type(_type), example(_example) {}
 
				~Arg() {}
 

	
 
				std::string name;
 
				std::string label;
 
				std::string type;
 
				std::string example;
 
		};
 

	
 
		AdminInterfaceCommand(const std::string &name, Category category, Context context, AccessMode accessMode, Actions actions, const std::string &label = "");
 

	
 
		virtual ~AdminInterfaceCommand() { }
 

	
 
		void setDescription(const std::string &desc) {
 
			m_desc = desc;
 
		}
 

	
 
		const std::string &getDescription() {
 
			return m_desc;
 
		}
 

	
 
		const std::string &getName() {
 
			return m_name;
 
		}
 

	
 
		Actions getActions() {
 
			return m_actions;
 
		}
 

	
 
		Category getCategory() {
 
			return m_category;
 
		}
 

	
 
		const std::string getCategoryName(Category category);
 

	
 
		Context getContext() {
 
			return m_context;
 
		}
 

	
 
		AccessMode getAccessMode() {
 
			return m_accessMode;
 
		}
 

	
 
		void addArg(const std::string &name, const std::string &label, const std::string &example = "") {
 
			Arg arg(name, label, example);
 
		void addArg(const std::string &name, const std::string &label, const std::string &type = "string", const std::string &example = "") {
 
			Arg arg(name, label, type, example);
 
			m_args.push_back(arg);
 
		}
 

	
 
		const std::list<Arg> &getArgs() {
 
			return m_args;
 
		}
 

	
 
		const std::string &getLabel() {
 
			return m_label;
 
		}
 

	
 
		virtual std::string handleSetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args);
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args);
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args);
 

	
 
	private:
 
		std::string m_name;
 
		Category m_category;
 
		Context m_context;
 
		AccessMode m_accessMode;
 
		Actions m_actions;
 
		std::string m_desc;
 
		std::list<Arg> m_args;
 
		std::string m_label;
 
};
 

	
 
}
libtransport/AdminInterface.cpp
Show inline comments
 
@@ -19,363 +19,364 @@
 
 */
 

	
 
#include "transport/AdminInterface.h"
 
#include "transport/AdminInterfaceCommand.h"
 
#include "transport/User.h"
 
#include "transport/Transport.h"
 
#include "transport/StorageBackend.h"
 
#include "transport/UserManager.h"
 
#include "transport/NetworkPluginServer.h"
 
#include "transport/Logging.h"
 
#include "transport/UserRegistration.h"
 
#include "transport/Frontend.h"
 
#include "transport/MemoryUsage.h"
 
#include "transport/Config.h"
 

	
 
#include <boost/foreach.hpp>
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "AdminInterface");
 

	
 
static std::string getArg(const std::string &body) {
 
	std::string ret;
 
	if (body.find(" ") == std::string::npos)
 
		return ret;
 

	
 
	return body.substr(body.find(" ") + 1);
 
}
 

	
 
class StatusCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		StatusCommand(NetworkPluginServer *server, UserManager *userManager) :
 
												AdminInterfaceCommand("status",
 
												AdminInterfaceCommand::General,
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
												AdminInterfaceCommand::Get) {
 
			m_server = server;
 
			m_userManager = userManager;
 
			setDescription("Shows instance status");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			int users = m_userManager->getUserCount();
 
			int backends = m_server->getBackendCount();
 
			ret = "Running (" + boost::lexical_cast<std::string>(users) + " users connected using " + boost::lexical_cast<std::string>(backends) + " backends)";
 
			return ret;
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_server;
 
		UserManager *m_userManager;
 
};
 

	
 
class UptimeCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		UptimeCommand() : AdminInterfaceCommand("uptime",
 
							AdminInterfaceCommand::General,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Get) {
 
			m_start = time(NULL);
 
			setDescription("Returns ptime in seconds");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			return boost::lexical_cast<std::string>(time(0) - m_start);
 
		}
 

	
 
	private:
 
		time_t m_start;
 
};
 

	
 
class OnlineUsersCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		OnlineUsersCommand(UserManager *userManager) : AdminInterfaceCommand("online_users",
 
							AdminInterfaceCommand::Users,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Get) {
 
							AdminInterfaceCommand::Execute,
 
							"Online users") {
 
			m_userManager = userManager;
 
			setDescription("Returns list of all online users");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			const std::map<std::string, User *> &users = m_userManager->getUsers();
 
			if (users.empty()) {
 
				ret = "0";
 
				ret = "hanzz@njs.netlab.cz \"3rd-party network username:\" \"me\"\n";
 
			}
 

	
 
			for (std::map<std::string, User *>::const_iterator it = users.begin(); it != users.end(); it ++) {
 
				ret += (*it).first + "\n";
 
				ret += (*it).first + " \"3rd-party network username:\" \"" + user->getUserInfo().uin + "\"\n";
 
			}
 
			return ret;
 
		}
 

	
 
	private:
 
		UserManager *m_userManager;
 
};
 

	
 
class OnlineUsersCountCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		OnlineUsersCountCommand(UserManager *userManager) : AdminInterfaceCommand("online_users_count",
 
							AdminInterfaceCommand::Users,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Get) {
 
			m_userManager = userManager;
 
			setDescription("Number of online users");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			int users = m_userManager->getUserCount();
 
			return boost::lexical_cast<std::string>(users);
 
		}
 

	
 
	private:
 
		UserManager *m_userManager;
 
};
 

	
 
class OnlineUsersPerBackendCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		OnlineUsersPerBackendCommand(NetworkPluginServer *server) :
 
												AdminInterfaceCommand("online_users_per_backend",
 
												AdminInterfaceCommand::General,
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
												AdminInterfaceCommand::Get) {
 
			m_server = server;
 
			setDescription("Shows online users per backends");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::string lst;
 
			int id = 1;
 

	
 
			const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
			for (std::list <NetworkPluginServer::Backend *>::const_iterator b = backends.begin(); b != backends.end(); b++) {
 
				NetworkPluginServer::Backend *backend = *b;
 
				lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + ")";
 
				lst += backend->acceptUsers ? "" : " - not-accepting";
 
				lst += backend->longRun ? " - long-running" : "";
 
				lst += ":\n";
 
				if (backend->users.size() == 0) {
 
					lst += "   waiting for users\n";
 
				}
 
				else {
 
					time_t now = time(NULL);
 
					for (std::list<User *>::const_iterator u = backend->users.begin(); u != backend->users.end(); u++) {
 
						User *user = *u;
 
						lst += "   " + user->getJID().toBare().toString();
 
						lst += " - non-active for " + boost::lexical_cast<std::string>(now - user->getLastActivity()) + " seconds";
 
						lst += "\n";
 
					}
 
				}
 
				id++;
 
			}
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_server;
 
};
 

	
 
class BackendsCountCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		BackendsCountCommand(NetworkPluginServer *server) :
 
												AdminInterfaceCommand("backends_count",
 
												AdminInterfaceCommand::Backends,
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
												AdminInterfaceCommand::Get) {
 
			m_server = server;
 
			setDescription("Number of active backends");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			int backends = m_server->getBackendCount();
 
			return boost::lexical_cast<std::string>(backends);
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_server;
 
};
 

	
 
class ReloadCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		ReloadCommand(Component *component) : AdminInterfaceCommand("reload",
 
							AdminInterfaceCommand::General,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute,
 
							"Reload Spectrum 2 configuration") {
 
			m_component = component;
 
			setDescription("Reloads config file");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			bool done = m_component->getConfig()->reload();
 
			if (done) {
 
				return "Config reloaded";
 
			}
 
			else {
 
				return "Error: Error during config reload";
 
			}
 
		}
 

	
 
	private:
 
		Component *m_component;
 
};
 

	
 
class HasOnlineUserCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		HasOnlineUserCommand(UserManager *userManager) : AdminInterfaceCommand("has_online_user",
 
							AdminInterfaceCommand::Users,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute, "Has online user") {
 
			m_userManager = userManager;
 
			setDescription("Returns 1 if user is online");
 
			addArg("username", "Username", "user@domain.tld");
 
			addArg("username", "Username", "string", "user@domain.tld");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (args.empty()) {
 
				return "Error: Missing user name as an argument";
 
			}
 

	
 
			user = m_userManager->getUser(args[0]);
 
			return boost::lexical_cast<std::string>(user != NULL);
 
		}
 

	
 
	private:
 
		UserManager *m_userManager;
 
};
 

	
 
class ResMemoryCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		ResMemoryCommand(NetworkPluginServer *server) :
 
												AdminInterfaceCommand("res_memory",
 
												AdminInterfaceCommand::Memory,
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
												AdminInterfaceCommand::Get) {
 
			m_server = server;
 
			setDescription("Total RESident memory Spectrum 2 and its backends use in KB");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			double shared = 0;
 
			double rss = 0;
 
			process_mem_usage(shared, rss);
 
			const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
			BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
				rss += backend->res;
 
			}
 

	
 
			return boost::lexical_cast<std::string>(rss);
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_server;
 
};
 

	
 
class ShrMemoryCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		ShrMemoryCommand(NetworkPluginServer *server) :
 
												AdminInterfaceCommand("shr_memory",
 
												AdminInterfaceCommand::Memory,
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
												AdminInterfaceCommand::Get) {
 
			m_server = server;
 
			setDescription("Total SHaRed memory spectrum2 backends share together in KB");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			double shared = 0;
 
			double rss = 0;
 
			process_mem_usage(shared, rss);
 
			const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
			BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
				shared += backend->shared;
 
			}
 

	
 
			return boost::lexical_cast<std::string>(shared);
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_server;
 
};
 

	
 
class UsedMemoryCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		UsedMemoryCommand(NetworkPluginServer *server) :
 
												AdminInterfaceCommand("used_memory",
 
												AdminInterfaceCommand::Memory,
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
@@ -624,320 +625,320 @@ class CrashedBackendsCommand : public AdminInterfaceCommand {
 
												AdminInterfaceCommand::GlobalContext,
 
												AdminInterfaceCommand::AdminMode,
 
												AdminInterfaceCommand::Get) {
 
			m_server = server;
 
			setDescription("Returns IDs of crashed backends");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::string lst;
 
			const std::vector<std::string> &backends = m_server->getCrashedBackends();
 
			BOOST_FOREACH(const std::string &backend, backends) {
 
				lst += backend + "\n";
 
			}
 
			return lst;
 
		}
 

	
 
	private:
 
		NetworkPluginServer *m_server;
 
};
 

	
 
class MessagesFromXMPPCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		MessagesFromXMPPCommand(UserManager *userManager) : AdminInterfaceCommand("messages_from_xmpp",
 
							AdminInterfaceCommand::Messages,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Get) {
 
			m_userManager = userManager;
 
			setDescription("Returns number of messages received from frontend network");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			int msgCount = m_userManager->getMessagesToBackend();
 
			return boost::lexical_cast<std::string>(msgCount);
 
		}
 

	
 
	private:
 
		UserManager *m_userManager;
 
};
 

	
 
class MessagesToXMPPCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		MessagesToXMPPCommand(UserManager *userManager) : AdminInterfaceCommand("messages_to_xmpp",
 
							AdminInterfaceCommand::Messages,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Get) {
 
			m_userManager = userManager;
 
			setDescription("Returns number of messages sent to Front network");
 
		}
 

	
 
		virtual std::string handleGetRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleGetRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			int msgCount = m_userManager->getMessagesToXMPP();
 
			return boost::lexical_cast<std::string>(msgCount);
 
		}
 

	
 
	private:
 
		UserManager *m_userManager;
 
};
 

	
 
class RegisterCommand : public AdminInterfaceCommand {
 
	public:
 
		RegisterCommand(UserRegistration *userRegistration, Component *component) : AdminInterfaceCommand("register",
 
							AdminInterfaceCommand::Users,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::UserMode,
 
							AdminInterfaceCommand::Execute,
 
							"Register") {
 
			m_userRegistration = userRegistration;
 
			setDescription("Registers the new user");
 

	
 
			std::string fields = component->getFrontend()->getRegistrationFields();
 
			std::vector<std::string> args;
 
			boost::split(args, fields, boost::is_any_of("\n"));
 
			addArg("username", args[0]);
 
			if (fields.size() > 1) {
 
				addArg("legacy_username", args[1]);
 
			}
 
			if (fields.size() > 2) {
 
				addArg("legacy_password", args[2]);
 
				addArg("legacy_password", args[2], "password");
 
			}
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (args.size() != 2 && args.size() != 3) {
 
				return "Error: Bad argument count";
 
			}
 

	
 
			UserInfo res;
 
			res.jid = args[0];
 
			res.uin = args[1];
 
			if (args.size() == 2) {
 
				res.password = "";
 
			}
 
			else {
 
				res.password = args[2];
 
			}
 
			res.language = "en";
 
			res.encoding = "utf-8";
 
			res.vip = 0;
 

	
 
			if (m_userRegistration->registerUser(res)) {
 
				return "User registered";
 
			}
 
			else {
 
				return "Error: User is already registered";
 
			}
 
		}
 

	
 
	private:
 
		UserRegistration *m_userRegistration;
 
};
 

	
 
class UnregisterCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		UnregisterCommand(UserRegistration *userRegistration, Component *component) : AdminInterfaceCommand("unregister",
 
							AdminInterfaceCommand::Users,
 
							AdminInterfaceCommand::UserContext,
 
							AdminInterfaceCommand::UserMode,
 
							AdminInterfaceCommand::Execute,
 
							"Unregister") {
 
			m_userRegistration = userRegistration;
 
			setDescription("Unregisters existing user");
 

	
 
// 			std::string fields = component->getFrontend()->getRegistrationFields();
 
// 			std::vector<std::string> args;
 
// 			boost::split(args, fields, boost::is_any_of("\n"));
 
// 			addArg("username", args[0]);
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (m_userRegistration->unregisterUser(uinfo.jid)) {
 
				return "User '" + args[0] + "' unregistered.";
 
			}
 
			else {
 
				return "Error: User '" + args[0] + "' is not registered";
 
			}
 
		}
 

	
 
	private:
 
		UserRegistration *m_userRegistration;
 
};
 

	
 
class SetOAuth2CodeCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		SetOAuth2CodeCommand(Component *component) : AdminInterfaceCommand("set_oauth2_code",
 
							AdminInterfaceCommand::Frontend,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute) {
 
			m_component = component;
 
			setDescription("set_oauth2_code <code> <state> - sets the OAuth2 code and state for this instance");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (args.size() != 2) {
 
				return "Error: Bad argument count";
 
			}
 

	
 
			ret = m_component->getFrontend()->setOAuth2Code(args[0], args[1]);
 
			if (ret.empty()) {
 
				return ret;
 
				
 
			}
 
			return "OAuth2 code and state set.";
 
		}
 

	
 
	private:
 
		Component *m_component;
 
};
 

	
 
class GetOAuth2URLCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		GetOAuth2URLCommand(Component *component) : AdminInterfaceCommand("get_oauth2_url",
 
							AdminInterfaceCommand::Frontend,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute) {
 
			m_component = component;
 
			setDescription("get_oauth2_code - Get OAUth2 URL");
 
			std::string fields = component->getFrontend()->getRegistrationFields();
 
			std::vector<std::string> args;
 
			boost::split(args, fields, boost::is_any_of("\n"));
 
			addArg("username", args[0]);
 
			if (fields.size() > 1) {
 
				addArg("legacy_username", args[1]);
 
			}
 
			if (fields.size() > 2) {
 
				addArg("legacy_password", args[2]);
 
				addArg("legacy_password", args[2], "password");
 
			}
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::string url = m_component->getFrontend()->getOAuth2URL(args);
 
			return url;
 
		}
 

	
 
	private:
 
		Component *m_component;
 
};
 

	
 
class HelpCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		HelpCommand(std::map<std::string, AdminInterfaceCommand *> *commands) : AdminInterfaceCommand("help",
 
							AdminInterfaceCommand::General,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute,
 
							"Help") {
 
			m_commands = commands;
 
			setDescription("Shows help message");
 
		}
 

	
 
		void generateCategory(AdminInterfaceCommand::Category category, std::string &output) {
 
			output += getCategoryName(category) + ":\n";
 

	
 
			for (std::map<std::string, AdminInterfaceCommand *>::iterator it = m_commands->begin(); it != m_commands->end(); it++) {
 
				AdminInterfaceCommand *command = it->second;
 
				if (command->getCategory() != category) {
 
					continue;
 
				}
 

	
 
				if (command->getActions() & AdminInterfaceCommand::Execute) {
 
					output += "   CMD   ";
 
				}
 
				else {
 
					output += "   VAR   ";
 
				}
 

	
 
				output += command->getName() + " - ";
 

	
 
				output += command->getDescription() + "\n";
 
			}
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::string help;
 
			generateCategory(AdminInterfaceCommand::General, help);
 
			generateCategory(AdminInterfaceCommand::Users, help);
 
			generateCategory(AdminInterfaceCommand::Messages, help);
 
			generateCategory(AdminInterfaceCommand::Frontend, help);
 
			generateCategory(AdminInterfaceCommand::Backends, help);
 
			generateCategory(AdminInterfaceCommand::Memory, help);
 
			return help;
 
		}
 

	
 
	private:
 
		std::map<std::string, AdminInterfaceCommand *> *m_commands;
 
};
 

	
 
class CommandsCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		CommandsCommand(std::map<std::string, AdminInterfaceCommand *> *commands) : AdminInterfaceCommand("commands",
 
							AdminInterfaceCommand::General,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute,
 
							"Available commands") {
 
			m_commands = commands;
 
			setDescription("Shows all the available commands with extended information.");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::string output;
 
			for (std::map<std::string, AdminInterfaceCommand *>::iterator it = m_commands->begin(); it != m_commands->end(); it++) {
 
				AdminInterfaceCommand *command = it->second;
 
				if ((command->getActions() & AdminInterfaceCommand::Execute) == 0) {
 
					continue;
 
@@ -958,244 +959,244 @@ class CommandsCommand : public AdminInterfaceCommand {
 
				output += " Context:";
 
				if (command->getContext() == AdminInterfaceCommand::UserContext) {
 
					output += " User";
 
				}
 
				else {
 
					output += " Global";
 
				}
 

	
 
				output += " Label: \"" + (command->getLabel().empty() ? command->getName() : command->getLabel()) + "\"";
 

	
 
				output += "\n";
 
			}
 

	
 
			return output;
 
		}
 

	
 
	private:
 
		std::map<std::string, AdminInterfaceCommand *> *m_commands;
 
};
 

	
 

	
 
class VariablesCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		VariablesCommand(std::map<std::string, AdminInterfaceCommand *> *commands) : AdminInterfaceCommand("variables",
 
							AdminInterfaceCommand::General,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute,
 
							"Available variables") {
 
			m_commands = commands;
 
			setDescription("Shows all the available variables.");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::string output;
 
			for (std::map<std::string, AdminInterfaceCommand *>::iterator it = m_commands->begin(); it != m_commands->end(); it++) {
 
				AdminInterfaceCommand *command = it->second;
 
				if ((command->getActions() & AdminInterfaceCommand::Get) == 0) {
 
					continue;
 
				}
 

	
 
				output += command->getName();
 
				output += " - \"" + command->getDescription() + "\"";
 
				output += " Value: \"" + command->handleGetRequest(uinfo, user, args) + "\"";
 

	
 
				if ((command->getActions() & AdminInterfaceCommand::Set) == 0) {
 
					output += " Read-only: true";
 
				}
 
				else {
 
					output += " Read-only: false";
 
				}
 

	
 
				output += " Category: " + command->getCategoryName(command->getCategory());
 

	
 
				output += " AccesMode:";
 
				if (command->getAccessMode() == AdminInterfaceCommand::UserMode) {
 
					output += " User";
 
				}
 
				else {
 
					output += " Admin";
 
				}
 

	
 
				output += " Context:";
 
				if (command->getContext() == AdminInterfaceCommand::UserContext) {
 
					output += " User";
 
				}
 
				else {
 
					output += " Global";
 
				}
 

	
 
				output += "\n";
 
			}
 

	
 
			return output;
 
		}
 

	
 
	private:
 
		std::map<std::string, AdminInterfaceCommand *> *m_commands;
 
};
 

	
 
class ArgsCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		ArgsCommand(std::map<std::string, AdminInterfaceCommand *> *commands) : AdminInterfaceCommand("args",
 
							AdminInterfaceCommand::General,
 
							AdminInterfaceCommand::GlobalContext,
 
							AdminInterfaceCommand::AdminMode,
 
							AdminInterfaceCommand::Execute, "Command's arguments") {
 
			m_commands = commands;
 
			setDescription("Shows descripton of arguments for command");
 
			addArg("command", "Command", "register");
 
			addArg("command", "Command", "string", "register");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			std::map<std::string, AdminInterfaceCommand *>::iterator it = m_commands->find(args[0]);
 
			if (it == m_commands->end()) {
 
				return "Error: Unknown command passed as an argument.";
 
			}
 
			AdminInterfaceCommand *command = it->second;
 

	
 
			BOOST_FOREACH(const AdminInterfaceCommand::Arg &arg, command->getArgs()) {
 
				ret += arg.name + " - \"" + arg.label + "\" " + "Example: \"" + arg.example + "\"\n";
 
				ret += arg.name + " - \"" + arg.label + "\" " + "Example: \"" + arg.example + "\" Type: \"" + arg.type + "\"\n";
 
			}
 

	
 
			return ret;
 
		}
 

	
 
	private:
 
		std::map<std::string, AdminInterfaceCommand *> *m_commands;
 
};
 

	
 

	
 
AdminInterface::AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend, UserRegistration *userRegistration) {
 
	m_component = component;
 
	m_storageBackend = storageBackend;
 
	m_userManager = userManager;
 
	m_server = server;
 
	m_userRegistration = userRegistration;
 

	
 
	m_component->getFrontend()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1));
 

	
 
	addCommand(new StatusCommand(m_server, m_userManager));
 
	addCommand(new UptimeCommand());
 
	addCommand(new OnlineUsersCommand(m_userManager));
 
	addCommand(new OnlineUsersCountCommand(m_userManager));
 
	addCommand(new ReloadCommand(m_component));
 
	addCommand(new OnlineUsersPerBackendCommand(m_server));
 
// 	addCommand(new OnlineUsersPerBackendCommand(m_server));
 
	addCommand(new HasOnlineUserCommand(m_userManager));
 
	addCommand(new BackendsCountCommand(m_server));
 
	addCommand(new ResMemoryCommand(m_server));
 
	addCommand(new ShrMemoryCommand(m_server));
 
	addCommand(new UsedMemoryCommand(m_server));
 
	addCommand(new AverageMemoryPerUserCommand(m_server, m_userManager));
 
	addCommand(new ResMemoryPerBackendCommand(m_server));
 
	addCommand(new ShrMemoryPerBackendCommand(m_server));
 
	addCommand(new UsedMemoryPerBackendCommand(m_server));
 
	addCommand(new AverageMemoryPerUserPerBackendCommand(m_server));
 
// 	addCommand(new ResMemoryPerBackendCommand(m_server));
 
// 	addCommand(new ShrMemoryPerBackendCommand(m_server));
 
// 	addCommand(new UsedMemoryPerBackendCommand(m_server));
 
// 	addCommand(new AverageMemoryPerUserPerBackendCommand(m_server));
 
	addCommand(new CrashedBackendsCountCommand(m_server));
 
	addCommand(new CrashedBackendsCommand(m_server));
 
	addCommand(new MessagesFromXMPPCommand(m_userManager));
 
	addCommand(new MessagesToXMPPCommand(m_userManager));
 
	addCommand(new SetOAuth2CodeCommand(m_component));
 
	addCommand(new GetOAuth2URLCommand(m_component));
 
	addCommand(new HelpCommand(&m_commands));
 
	addCommand(new ArgsCommand(&m_commands));
 
	addCommand(new CommandsCommand(&m_commands));
 
	addCommand(new VariablesCommand(&m_commands));
 

	
 
	if (m_userRegistration) {
 
		addCommand(new RegisterCommand(m_userRegistration, m_component));
 
		addCommand(new UnregisterCommand(m_userRegistration, m_component));
 
	}
 
}
 

	
 
AdminInterface::~AdminInterface() {
 
	for (std::map<std::string, AdminInterfaceCommand *>::iterator it = m_commands.begin(); it != m_commands.end(); it++) {
 
		delete it->second;
 
	}
 
}
 

	
 
void AdminInterface::addCommand(AdminInterfaceCommand *command) {
 
	m_commands[command->getName()] = command;
 
}
 

	
 
void AdminInterface::handleQuery(Swift::Message::ref message) {
 
#if HAVE_SWIFTEN_3
 
	std::string msg = message->getBody().get_value_or("");
 
#else
 
	std::string msg = message->getBody();
 
#endif
 
	LOG4CXX_INFO(logger, "Message from admin received: '" << msg << "'");
 
	message->setTo(message->getFrom());
 
	message->setFrom(m_component->getJID());
 

	
 
	std::string body = msg;
 
	std::vector<std::string> args;
 
	boost::split(args, body, boost::is_any_of(" "));
 

	
 
	if (args.empty()) {
 
		message->setBody("Error: Unknown variable or command");
 
		return;
 
	}
 

	
 
	// Check for 'get' and 'set' command.
 
	AdminInterfaceCommand::Actions action = AdminInterfaceCommand::None;
 
	if (args[0] == "set") {
 
		action = AdminInterfaceCommand::Set;
 
		args.erase(args.begin());
 
	}
 
	else if (args[0] == "get") {
 
		action = AdminInterfaceCommand::Get;
 
		args.erase(args.begin());
 
	}
 

	
 
	// We removed the 'get' and 'set' from args, so check we have more
 
	// data there.
 
	if (args.empty()) {
 
		message->setBody("Error: Unknown variable or command");
 
		return;
 
	}
 

	
 
	// Find the right AdminInterfaceCommand
 
	std::map<std::string, AdminInterfaceCommand *>::iterator it = m_commands.find(args[0]);
 
	if (it == m_commands.end()) {
 
		message->setBody("Error: Unknown variable or command");
 
		return;
 
	}
 
	AdminInterfaceCommand *command = it->second;
 
	args.erase(args.begin());
 

	
 
	// If action is None, then it's Get or Execute according to command type.
 
	if (action == AdminInterfaceCommand::None) {
 
		if (command->getActions() & AdminInterfaceCommand::Get) {
 
			action = AdminInterfaceCommand::Get;
 
		}
 
		else if (command->getActions() & AdminInterfaceCommand::Execute) {
 
			action = AdminInterfaceCommand::Execute;
 
		}
 
	}
 

	
 
	User *user = NULL;
 
	UserInfo uinfo;
 
	uinfo.id = -1;
 

	
 
	if (command->getContext() == AdminInterfaceCommand::UserContext) {
 
		if (args.empty()) {
 
			message->setBody("Error: No username given");
 
			return;
 
		}
 

	
 
		if (!m_storageBackend || !m_storageBackend->getUser(args[0], uinfo)) {
 
			uinfo.id = -1;
 
		}
spectrum/src/frontends/slack/SlackUserManager.cpp
Show inline comments
 
@@ -6,241 +6,243 @@
 
 * 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 "transport/AdminInterface.h"
 
#include "transport/AdminInterfaceCommand.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");
 

	
 
class ListRoomsCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		ListRoomsCommand(StorageBackend *storageBackend) : AdminInterfaceCommand("list_rooms",
 
							AdminInterfaceCommand::Frontend,
 
							AdminInterfaceCommand::UserContext,
 
							AdminInterfaceCommand::UserMode,
 
							AdminInterfaceCommand::Execute,
 
							"List joined 3rd-party network rooms") {
 
			m_storageBackend = storageBackend;
 
			setDescription("List connected rooms");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *user, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, user, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (uinfo.id == -1) {
 
				return "Error: Unknown user";
 
			}
 

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

	
 
	private:
 
		StorageBackend *m_storageBackend;
 
};
 

	
 
class JoinRoomCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		JoinRoomCommand(StorageBackend *storageBackend, Config *cfg) : AdminInterfaceCommand("join_room",
 
							AdminInterfaceCommand::Frontend,
 
							AdminInterfaceCommand::UserContext,
 
							AdminInterfaceCommand::UserMode,
 
							AdminInterfaceCommand::Execute,
 
							"Join 3rd-party network room") {
 
			m_storageBackend = storageBackend;
 
			setDescription("Join the room");
 

	
 
			std::string legacyRoomLabel = CONFIG_STRING_DEFAULTED(cfg, "service.join_room_room_label", "3rd-party room name");
 
			if (legacyRoomLabel[0] == '%') {
 
				legacyRoomLabel[0] = '#';
 
			}
 

	
 
			std::string legacyRoomExample = CONFIG_STRING_DEFAULTED(cfg, "service.join_room_room_example", "3rd-party room name");
 
			if (legacyRoomExample[0] == '%') {
 
				legacyRoomExample[0] = '#';
 
			}
 

	
 
			addArg("nickname",
 
				   CONFIG_STRING_DEFAULTED(cfg, "service.join_room_nickname_label", "Nickname in 3rd-party room"),
 
				   "string",
 
				   CONFIG_STRING_DEFAULTED(cfg, "service.join_room_nickname_example", "BotNickname"));
 
			addArg("legacy_room", legacyRoomLabel, legacyRoomExample);
 
			addArg("legacy_room", legacyRoomLabel, "string", legacyRoomExample);
 
			addArg("legacy_server",
 
				   CONFIG_STRING_DEFAULTED(cfg, "service.join_room_server_label", "3rd-party server"),
 
				   "string",
 
				   CONFIG_STRING_DEFAULTED(cfg, "service.join_room_server_example", "3rd.party.server.org"));
 
			addArg("slack_channel", "Slack Chanel", "mychannel");
 
			addArg("slack_channel", "Slack Chanel", "string", "mychannel");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *u, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, u, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (uinfo.id == -1) {
 
				return "Error: Unknown user";
 
			}
 

	
 
			std::string rooms = "";
 
			int type = (int) TYPE_STRING;
 
			m_storageBackend->getUserSetting(uinfo.id, "rooms", type, rooms);
 
			// 'unknown' is here to stay compatible in args.size() with older version.
 
			rooms += "connected room " + args[0] + " " + args[1] + " " + args[2] + " " + args[3] + "\n";
 
			m_storageBackend->updateUserSetting(uinfo.id, "rooms", rooms);
 

	
 
			SlackUser *user = static_cast<SlackUser *>(u);
 
			if (user) {
 
				user->getSession()->handleJoinMessage("", args, true);
 
			}
 
			return "Joined the room";
 
		}
 

	
 
	private:
 
		StorageBackend *m_storageBackend;
 
};
 

	
 
class LeaveRoomCommand : public AdminInterfaceCommand {
 
	public:
 
		
 
		LeaveRoomCommand(StorageBackend *storageBackend) : AdminInterfaceCommand("leave_room",
 
							AdminInterfaceCommand::Frontend,
 
							AdminInterfaceCommand::UserContext,
 
							AdminInterfaceCommand::UserMode,
 
							AdminInterfaceCommand::Execute,
 
							"Leave 3rd-party network room") {
 
			m_storageBackend = storageBackend;
 
			setDescription("Leave the room");
 

	
 
			addArg("slack_channel", "Slack Chanel", "mychannel");
 
			addArg("slack_channel", "Slack Chanel", "string", "mychannel");
 
		}
 

	
 
		virtual std::string handleExecuteRequest(UserInfo &uinfo, User *u, std::vector<std::string> &args) {
 
			std::string ret = AdminInterfaceCommand::handleExecuteRequest(uinfo, u, args);
 
			if (!ret.empty()) {
 
				return ret;
 
			}
 

	
 
			if (uinfo.id == -1) {
 
				return "Error: Unknown user";
 
			}
 

	
 
			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[0] != args2[5]) {
 
							rooms += command + "\n";
 
						}
 
					}
 
				}
 
			}
 

	
 
			m_storageBackend->updateUserSetting(uinfo.id, "rooms", rooms);
 

	
 
			SlackUser *user = static_cast<SlackUser *>(u);
 
			if (user) {
 
				user->getSession()->leaveRoom(args[0]);
 
			}
 
			return "Left the room";
 
		}
 

	
 
	private:
 
		StorageBackend *m_storageBackend;
 
};
 

	
 
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));
 
	m_component->onAdminInterfaceSet.connect(boost::bind(&SlackUserManager::handleAdminInterfaceSet, this));
 
}
 

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

	
 
void SlackUserManager::handleAdminInterfaceSet() {
 
	AdminInterface *adminInterface = m_component->getAdminInterface();
 
	if (adminInterface) {
 
		adminInterface->addCommand(new ListRoomsCommand(m_storageBackend));
 
		adminInterface->addCommand(new JoinRoomCommand(m_storageBackend, m_component->getConfig()));
 
		adminInterface->addCommand(new LeaveRoomCommand(m_storageBackend));
 
	}
 
}
 

	
 
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);
 
}
 

	
 
SlackSession *SlackUserManager::moveTempSession(const std::string &user) {
 
	if (m_tempSessions.find(user) != m_tempSessions.end()) {
 
		SlackSession *session = m_tempSessions[user];
 
		m_tempSessions.erase(user);
spectrum_manager/src/APIServer.cpp
Show inline comments
 
@@ -392,286 +392,340 @@ void APIServer::serve_instances_variables(Server *server, Server::session *sessi
 
		cmd.AddMember("desc", tokens[2].c_str(), json.GetAllocator());
 
		cmd.AddMember("value", tokens[4].c_str(), json.GetAllocator());
 
		cmd.AddMember("read_only", tokens[6].c_str(), json.GetAllocator());
 
		cmd.AddMember("category", tokens[8].c_str(), json.GetAllocator());
 
		cmd.AddMember("context", tokens[12].c_str(), json.GetAllocator());
 
		cmds.PushBack(cmd, json.GetAllocator());
 
	}
 

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

	
 

	
 
void APIServer::serve_instances_command_args(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 command = get_http_var(hm, "command");
 
	boost::trim(command);
 

	
 
	std::string response = server->send_command(instance, "commands");
 

	
 
	bool found = false;
 
	bool userContext = false;
 
	std::vector<std::string> commands;
 
	boost::split(commands, response, boost::is_any_of("\n"));
 
	BOOST_FOREACH(const std::string &cmd, commands) {
 
		escaped_list_separator<char> els('\\', ' ', '\"');
 
		tokenizer<escaped_list_separator<char> > tok(cmd, els);
 

	
 
		std::vector<std::string> tokens;
 
		for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg) {
 
			tokens.push_back(*beg);
 
		}
 

	
 
		if (tokens.size() != 11) {
 
			continue;
 
		}
 

	
 
		std::cout << tokens[0] << " " << command << "\n";
 
		if (tokens[0] != command) {
 
			continue;
 
		}
 

	
 
		if (!session->admin && tokens[6] == "Admin") {
 
			send_ack(conn, false, "Only admin is able to query this command.");
 
			return;
 
		}
 

	
 
		if (tokens[8] == "User") {
 
			userContext = true;
 
		}
 

	
 
		found = true;
 
		break;
 
	}
 

	
 
	if (!found) {
 
		command = "unknown";
 
	}
 

	
 
	response = server->send_command(instance, "args " + command);
 
	if (response.find("Error:") == 0) {
 
		send_ack(conn, false, response);
 
		return;
 
	}
 

	
 
	
 

	
 
	std::vector<std::string> args;
 
	boost::split(args, response, boost::is_any_of("\n"));
 

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

	
 
	std::vector<std::vector<std::string> > tmp;
 
	Value argList(kArrayType);
 

	
 
	if (userContext && session->admin) {
 
		Value arg;
 
		arg.SetObject();
 
		arg.AddMember("name", "username", json.GetAllocator());
 
		arg.AddMember("label", "Username", json.GetAllocator());
 
		arg.AddMember("example", "", json.GetAllocator());
 
		argList.PushBack(arg, json.GetAllocator());
 
	}
 

	
 
	BOOST_FOREACH(const std::string &argument, args) {
 
		escaped_list_separator<char> els('\\', ' ', '\"');
 
		tokenizer<escaped_list_separator<char> > tok(argument, els);
 

	
 
		std::vector<std::string> tokens;
 
		for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg) {
 
			tokens.push_back(*beg);
 
		}
 

	
 
		if (tokens.size() != 5) {
 
		if (tokens.size() != 7) {
 
			continue;
 
		}
 

	
 
		tmp.push_back(tokens);
 

	
 
		Value arg;
 
		arg.SetObject();
 
		arg.AddMember("name", tokens[0].c_str(), json.GetAllocator());
 
		arg.AddMember("label", tokens[2].c_str(), json.GetAllocator());
 
		arg.AddMember("example", tokens[4].c_str(), json.GetAllocator());
 
		arg.AddMember("type", tokens[6].c_str(), json.GetAllocator());
 
		argList.PushBack(arg, json.GetAllocator());
 
	}
 

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

	
 

	
 
void APIServer::serve_instances_execute(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 command = get_http_var(hm, "command");
 
	boost::trim(command);
 

	
 
	std::string response = server->send_command(instance, "commands");
 

	
 
	bool found = false;
 
	bool userContext = false;
 
	std::vector<std::string> commands;
 
	boost::split(commands, response, boost::is_any_of("\n"));
 
	BOOST_FOREACH(const std::string &cmd, commands) {
 
		escaped_list_separator<char> els('\\', ' ', '\"');
 
		tokenizer<escaped_list_separator<char> > tok(cmd, els);
 

	
 
		std::vector<std::string> tokens;
 
		for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg) {
 
			tokens.push_back(*beg);
 
		}
 

	
 
		if (tokens.size() != 11) {
 
			continue;
 
		}
 

	
 
		std::cout << tokens[0] << " " << command << "\n";
 
		if (tokens[0] != command) {
 
			continue;
 
		}
 

	
 
		if (!session->admin && tokens[6] == "Admin") {
 
			send_ack(conn, false, "Only admin is able to execute.");
 
			return;
 
		}
 

	
 
		if (tokens[8] == "User") {
 
			userContext = true;
 
		}
 

	
 
		found = true;
 
		break;
 
	}
 

	
 
	if (!found) {
 
		command = "unknown";
 
	}
 

	
 
	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 (userContext && !session->admin) {
 
		if (username.empty()) {
 
			send_ack(conn, false, "Error: You are not registered to this transport instance.");
 
			return;
 
		}
 

	
 
		command += " " + username;
 
	}
 

	
 
	for (int i = 0; i < 10; ++i) {
 
		std::string var = get_http_var(hm, std::string(std::string("command_arg") + boost::lexical_cast<std::string>(i)).c_str());
 
		if (!var.empty()) {
 
			command += " " + var;
 
		}
 
	}
 

	
 
	response = server->send_command(instance, command);
 
	boost::replace_all(response, "\n", "<br/>");
 
	if (response.find("Error:") == 0) {
 
		send_ack(conn, false, response);
 
	}
 

	
 
	std::vector<std::string> fields;
 
	boost::split(fields, response, boost::is_any_of("\n"));
 
	if (!fields.empty() && /*fields[0].find(" - ") != std::string::npos &&*/ (fields[0].find(": ") != std::string::npos || fields[0].find(":\"") != std::string::npos)) {
 
		Document json;
 
		json.SetObject();
 
		json.AddMember("error", 0, json.GetAllocator());
 

	
 
		std::vector<std::string> tmp;
 
		std::vector<std::string> tmp2;
 
		Value table(kArrayType);
 

	
 
		BOOST_FOREACH(const std::string &line, fields) {
 
			escaped_list_separator<char> els('\\', ' ', '\"');
 
			tokenizer<escaped_list_separator<char> > tok(line, els);
 

	
 
			Value arg;
 
			arg.SetObject();
 

	
 
			std::string key;
 
			int i = 0;
 
			bool hasDesc = true;
 
			for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg, ++i) {
 
				if (i == 1 && *beg != "-") {
 
					hasDesc = false;
 
				}
 
				if (i == 0) {
 
					tmp.push_back(*beg);
 
					arg.AddMember("Key", tmp.back().c_str(), json.GetAllocator());
 
				}
 
				else if (i == 2 && hasDesc) {
 
					tmp.push_back(*beg);
 
					arg.AddMember("Description", tmp.back().c_str(), json.GetAllocator());
 
				}
 
				else if (i > 1 || (!hasDesc && i > 0)) {
 
					if (key.empty()) {
 
						key = *beg;
 
					}
 
					else {
 
						tmp.push_back(key);
 
						tmp2.push_back(*beg);
 
						arg.AddMember(tmp.back().c_str(), tmp2.back().c_str(), json.GetAllocator());
 
						key = "";
 
					}
 
				}
 
			}
 
			table.PushBack(arg, json.GetAllocator());
 
		}
 

	
 
		json.AddMember("table", table, json.GetAllocator());
 
		json.AddMember("message", response.c_str(), json.GetAllocator());
 
		send_json(conn, json);
 
	}
 
	else {
 
		boost::replace_all(response, "\n", "<br/>");
 
		send_ack(conn, true, response);
 
	}
 
}
 

	
 
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);
 
}
 

	
 
void APIServer::serve_users_add(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string user = get_http_var(hm, "username");
 
	std::string password = get_http_var(hm, "password");
 

	
 
	if (!user.empty() && !password.empty()) {
 
		if (m_storage) {
 
			UserInfo dummy;
 
			bool registered = m_storage->getUser(user, dummy);
 
			if (!registered) {
 
				UserInfo info;
 
				info.jid = user;
 
				info.password = password;
 
				m_storage->setUser(info);
 
			}
 
			else {
 
				send_ack(conn, true, "This user is already registered");
 
				return;
 
			}
 
		}
 
		else {
 
			send_ack(conn, false, "Storage backend is not configured.");
 
		}
 
	}
 
	else {
 
		send_ack(conn, true, "Username or password has not been provided.");
 
		return;
 
	}
 
	send_ack(conn, false, "");
 
}
 

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

	
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string user = uri.substr(uri.rfind("/") + 1);
 

	
 
	if (!m_storage) {
 
		return;
 
	}
 

	
 
	UserInfo info;
 
	m_storage->getUser(user, info);
 
	m_storage->removeUser(info.id);
 

	
 
	send_ack(conn, false, "");
 
}
 

	
 
void APIServer::handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm) {
 
	if (has_prefix(&hm->uri, "/api/v1/instances/start/")) {
 
		serve_instances_start(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/stop/")) {
 
		serve_instances_stop(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/unregister/")) {
 
		serve_instances_unregister(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/register/")) {
 
		serve_instances_register(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/commands/")) {
 
		serve_instances_commands(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/variables/")) {
 
		serve_instances_variables(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/command_args/")) {
 
		serve_instances_command_args(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/execute/")) {
spectrum_manager/src/html/js/app.js
Show inline comments
 
@@ -42,237 +42,262 @@ function show_instances() {
 
			var row = '<tr>'
 
			row += '<td><a href="instance.shtml?id=' + instance.id + '">' + instance.name + '</a></td>'
 
			row += '<td>' + instance.status + '</td>'
 
			if (admin) {
 
				if (command == "") {
 
					row += '<td></td></tr>';
 
					$("#main_result  > tbody:last-child").append(row);
 
				}
 
				else {
 
					row += '<td>';
 
					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();
 
						});
 
					})
 
				}
 
			}
 
			else {
 
				row += '</tr>';
 
				$("#main_result  > tbody:last-child").append(row);
 
			}
 
		});
 
	});
 
}
 

	
 
function show_users() {
 
	var admin = $.cookie("admin") == "1";
 
	if (!admin) {
 
		$("#main_content").html("<h2>List of Spectrum 2 users</h2><p>Only administrator can list the users.</p>");
 
		return;
 
	}
 

	
 
	$.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_users_register_form() {
 
	$(".button").click(function(e) {
 
		e.preventDefault();
 

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

	
 
		$.post(BaseLocation + "api/v1/users/add", postdata, function(data) {
 
			if (data.error) {
 
				$('#error').text(data.message);
 
			}
 
			else {
 
				var query = getQueryParams(document.location.search);
 
				if (query.back_to_list == "1") {
 
					window.location.replace("list.shtml");
 
				}
 
				else {
 
					window.location.replace("../login/");
 
				}
 
			}
 
		});
 
	})
 
}
 

	
 
function execute_command(instance, command) {
 
	$.get($.cookie("base_location") +  'api/v1/instances/command_args/' + instance + '?command=' + command, function(data) {
 
		var form = '<div class="row">';
 

	
 
		if (data.args.length != 0) {
 
			form += '<div class="col-md-12"><form class="form-horizontal">';
 
			$.each(data.args, function(i, arg) {
 
				form += '<div class="form-group">';
 
				form += '<label class="col-md-4 control-label" for="' + arg.name + '">' + arg.label + ':</label>';
 
				form += '<div class="col-md-4">';
 
				if (arg.type == "password") {
 
					form += '<input id="command_arg' + i + '" name="command_arg' + i + '" type="password" placeholder="' + arg.example + '" class="form-control input-md"/>';
 
				}
 
				else {
 
					form += '<input id="command_arg' + i + '" name="command_arg' + i + '" type="text" placeholder="' + arg.example + '" class="form-control input-md"/>';
 
				}
 
				form += '</div></div>';
 
				console.log('command_arg' + i );
 
			});
 
		}
 
		else {
 
			form += '<div><form class="form-horizontal">';
 
			form += '<div class="form-group">';
 
			form += '<label class="control-label">No arguments needed for this command, you can just execute it.</label>';
 
			form += '</div>';
 
		}
 

	
 
		form += '</form></div></div>'
 

	
 
		bootbox.dialog({
 
			title: "Command execution: " + command + ".",
 
			message: form,
 
			buttons: {
 
				cancel: {
 
					label: "Cancel",
 
					className: "btn-cancel"
 
				},
 
				success: {
 
					label: "Execute",
 
					className: "btn-success",
 
					callback: function () {
 
						if (command == "register") {
 
							var postdata = {};
 
							if ($("#command_arg0").val()) {
 
								postdata["jid"] = $("#command_arg0").val();
 
							}
 
							if ($("#command_arg1").val()) {
 
								postdata["uin"] = $("#command_arg1").val();
 
							}
 
							if ($("#command_arg2").val()) {
 
								postdata["password"] = $("#command_arg2").val();
 
							}
 

	
 
							$.post($.cookie("base_location") + "api/v1/instances/register/" + instance, postdata, function(data) {
 
								if (data.oauth2_url) {
 
									window.location.replace(data.oauth2_url);
 
								}
 
								else {
 
									var dialog = bootbox.dialog({
 
										title: "Command result: " + command + ".",
 
										message: "<pre>" + data.message + "</pre>",
 
										buttons: {
 
											success: {
 
												label: "OK",
 
												className: "btn-success",
 
												callback: function () {
 
													 location.reload(); 
 
												}
 
											}
 
										}
 
									})
 
									dialog.find("div.modal-dialog").addClass("largeWidth");
 
									dialog.find("div.modal-body").addClass("maxHeight");
 
								}
 
							});
 
						}
 
						else {
 
							if (command == "unregister") {
 
								var posturl = $.cookie("base_location") + "api/v1/instances/unregister/" + instance;
 
							}
 
							else {
 
								var posturl = $.cookie("base_location") + "api/v1/instances/execute/" + instance + "?command=" + command;
 
							}
 
							var postdata = {}
 
							for (i = 0; i < 10; i++) {
 
								var val = $('#command_arg' + i).val();
 
								if (val) {
 
									postdata["command_arg" + i] = val;
 
								}
 
							}
 
							$.post(posturl, postdata, function(data) {
 
								if (data.table) {
 
									data.message = "<table>";
 
									data.message += "<tr>";
 
									for (var key in data.table[0]) {
 
										if (data.table[0].hasOwnProperty(key)) {
 
											data.message += "<th>" + key + "</th>";
 
										}
 
									}
 
									data.message += "</tr>";
 
									$.each(data.table, function(i, line) {
 
										data.message += "<tr>";
 
										for (var key in line) {
 
											if (line.hasOwnProperty(key)) {
 
												data.message += "<td>" + line[key] + "</td>";
 
											}
 
										}
 
										data.message += "</tr>";
 
									})
 
									data.message += "</table>";
 
								}
 
								var dialog = bootbox.dialog({
 
									title: "Command result: " + command + ".",
 
									message: "<pre>" + data.message + "</pre>",
 
									buttons: {
 
										success: {
 
											label: "OK",
 
											className: "btn-success",
 
											callback: function () {
 
												if (command == "unregister") {
 
													location.reload(); 
 
												}
 
											}
 
										}
 
									}
 
								})
 
								dialog.find("div.modal-dialog").addClass("largeWidth");
 
								dialog.find("div.modal-body").addClass("maxHeight");
 
							});
 
						}
 
					}
 
				}
 
			}
 
		})
 
	});
 
}
 

	
 
function show_instance() {
 
	var query = getQueryParams(document.location.search);
 

	
 
	$("#main_content").html("<h2>Instance: " + query.id + "</h2><h4>Available commands:</h4><table id='commands'><tr><th>Name<th>Category</th><th>Description</th></tr></table><h4>Available variables:</h4><table id='variables'><tr><th>Name<th>Value</th><th>Read-only</th><th>Desc</th></tr></table>");
 

	
 
	$.get($.cookie("base_location") + "api/v1/instances/commands/" + query.id, function(data) {
 
		$.each(data.commands, function(i, command) {
 
			var row = '<tr>'
 
			row += '<td><a class="button_command" command="' + command.name + '" instance="' + query.id + '" href="' + $.cookie("base_location") +  'api/v1/instances/command_args/' + query.id + '?command=' + command.name +'">' + command.label + '</a></td>';
 
			row += '<td>' + command.category + '</td>';
 
			row += '<td>' + command.desc + '</td>';
 
			row += '</tr>';
 
			$("#commands  > tbody:last-child").append(row);
 
		});
 

	
 
		$(".button_command").click(function(e) {
 
			e.preventDefault();
 

	
 
			var command = $(this).attr('command');
 
			var instance = $(this).attr('instance');
 
			execute_command(instance, command);
 
		})
 
	});
 

	
 
	$.get($.cookie("base_location") + "api/v1/instances/variables/" + query.id, function(data) {
 
		$.each(data.variables, function(i, variable) {
 
			var row = '<tr>'
 
			row += '<td>' + variable.name + '</td>';
 
			row += '<td>' + variable.value + '</td>';
 
			row += '<td>' + variable.read_only + '</td>';
 
			row += '<td>' + variable.desc + '</td>';
 
			row += '</tr>';
 
			$("#variables  > tbody:last-child").append(row);
 
		});
 
	});
 

	
 

	
 
}
 

	
tests/libtransport/AdminInterface.cpp
Show inline comments
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "BasicSlackTest.h"
 
#include "transport/AdminInterface.h"
 

	
 
#if !HAVE_SWIFTEN_3
 
#define get_value_or(X) substr()
 
#endif
 

	
 
using namespace Transport;
 

	
 
class AdminInterfaceTest : public CPPUNIT_NS :: TestFixture, public BasicSlackTest {
 
	CPPUNIT_TEST_SUITE(AdminInterfaceTest);
 
	CPPUNIT_TEST(helpCommand);
 
	CPPUNIT_TEST(statusCommand);
 
	CPPUNIT_TEST(joinRoomArgs);
 
	CPPUNIT_TEST(getOAuth2URLCommand);
 
	CPPUNIT_TEST(unknownCommand);
 
	CPPUNIT_TEST(listJoinLeaveRoomsCommand);
 
	CPPUNIT_TEST(badArgCount);
 
	CPPUNIT_TEST(commandsCommand);
 
	CPPUNIT_TEST(variablesCommand);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		AdminInterface *admin;
 
		NetworkPluginServer *serv;
 

	
 
		void setUp (void) {
 
			setMeUp();
 
			serv = new NetworkPluginServer(component, cfg, userManager, NULL);
 
			admin = new AdminInterface(component, userManager, serv, storage, NULL);
 
			component->setAdminInterface(admin);
 
		}
 

	
 
		void tearDown (void) {
 
			delete admin;
 
			delete serv;
 
			tearMeDown();
 
		}
 

	
 
	std::string sendAdminMessage(const std::string &cmd) {
 
		Swift::Message::ref msg = boost::shared_ptr<Swift::Message>(new Swift::Message());
 
		msg->setFrom(Swift::JID("me@localhost"));
 
		msg->setTo(Swift::JID("localhost"));
 
		msg->setBody(cmd);
 

	
 
		admin->handleMessageReceived(msg);
 
		return msg->getBody().get_value_or("");
 
	}
 

	
 
	void helpCommand() {
 
		std::string resp = sendAdminMessage("help");
 
		CPPUNIT_ASSERT(resp.find("   VAR   status - Shows instance status\n") != std::string::npos);
 
	}
 

	
 
	void statusCommand() {
 
		std::string resp = sendAdminMessage("status");
 
		CPPUNIT_ASSERT_EQUAL(std::string("Running (0 users connected using 0 backends)"), resp);
 
	}
 

	
 
	void joinRoomArgs() {
 
		std::string resp = sendAdminMessage("args join_room");
 
		CPPUNIT_ASSERT_EQUAL(std::string("nickname - \"Nickname in 3rd-party room\" Example: \"BotNickname\"\n"
 
							"legacy_room - \"3rd-party room name\" Example: \"3rd-party room name\"\n"
 
							"legacy_server - \"3rd-party server\" Example: \"3rd.party.server.org\"\n"
 
							"slack_channel - \"Slack Chanel\" Example: \"mychannel\"\n"), resp);
 
		CPPUNIT_ASSERT_EQUAL(std::string("nickname - \"Nickname in 3rd-party room\" Example: \"BotNickname\" Type: \"string\"\n"
 
							"legacy_room - \"3rd-party room name\" Example: \"3rd-party room name\" Type: \"string\"\n"
 
							"legacy_server - \"3rd-party server\" Example: \"3rd.party.server.org\" Type: \"string\"\n"
 
							"slack_channel - \"Slack Chanel\" Example: \"mychannel\" Type: \"string\"\n"), resp);
 
	}
 

	
 
	void getOAuth2URLCommand() {
 
		std::string resp = sendAdminMessage("get_oauth2_url x y z");
 
		CPPUNIT_ASSERT(resp.find("https://slack.com/oauth/authorize?client_id=&scope=channels%3Aread%20channels%3Awrite%20team%3Aread%20im%3Aread%20im%3Awrite%20chat%3Awrite%3Abot%20bot&redirect_uri=https%3A%2F%2Fslack.spectrum.im%2Foauth2%2Flocalhost&state=") != std::string::npos);
 
	}
 

	
 
	void unknownCommand() {
 
		std::string resp = sendAdminMessage("unknown_command test");
 
		CPPUNIT_ASSERT_EQUAL(std::string("Error: Unknown variable or command"), resp);
 
	}
 

	
 
	void listJoinLeaveRoomsCommand() {
 
		addUser();
 

	
 
		std::string resp = sendAdminMessage("list_rooms user@localhost");
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), resp);
 

	
 
		resp = sendAdminMessage("join_room user@localhost SlackBot spectrum conference.spectrum.im slack_channel");
 
		CPPUNIT_ASSERT_EQUAL(std::string("Joined the room"), resp);
 

	
 
		resp = sendAdminMessage("list_rooms user@localhost");
 
		CPPUNIT_ASSERT_EQUAL(std::string("connected room SlackBot spectrum conference.spectrum.im slack_channel\n"), resp);
 

	
 
		resp = sendAdminMessage("leave_room user@localhost slack_channel");
 
		CPPUNIT_ASSERT_EQUAL(std::string("Left the room"), resp);
 

	
 
		resp = sendAdminMessage("list_rooms user@localhost");
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), resp);
 
	}
 

	
 
	void badArgCount() {
 
		addUser();
 
		std::string resp;
 
		resp = sendAdminMessage("join_room user@localhost SlackBot spectrum conference.spectrum.im slack_channel unknown");
 
		CPPUNIT_ASSERT_EQUAL(std::string("Error: Too many arguments."), resp);
 

	
 
		resp = sendAdminMessage("join_room user@localhost SlackBot spectrum conference.spectrum.im");
 
		CPPUNIT_ASSERT_EQUAL(std::string("Error: Argument is missing."), resp);
 
	}
 

	
 
	void commandsCommand() {
 
		addUser();
 
		std::string resp;
 
		resp = sendAdminMessage("commands");
 
		CPPUNIT_ASSERT(resp.find("join_room - \"Join the room\" Category: Frontend AccesMode: User Context: User") != std::string::npos);
 
	}
 

	
 
	void variablesCommand() {
 
		addUser();
 
		std::string resp;
 
		resp = sendAdminMessage("variables");
 
		CPPUNIT_ASSERT(resp.find("backends_count - \"Number of active backends\" Value: \"0\" Read-only: true") != std::string::npos);
 
	}
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (AdminInterfaceTest);
0 comments (0 inline, 0 general)