Changeset - 8c1c1970130e
[Not reviewed]
0 4 0
Jan Kaluza - 10 years ago 2016-01-07 21:08:38
jkaluza@redhat.com
Spectrum2 manager server: handle OAuth2
4 files changed with 22 insertions and 9 deletions:
0 comments (0 inline, 0 general)
libtransport/AdminInterface.cpp
Show inline comments
 
@@ -292,59 +292,54 @@ void AdminInterface::handleQuery(Swift::Message::ref message) {
 
				message->setBody("Unregistration failed: User '" + args[1] + "' is not registered");
 
			}
 
		}
 
		else {
 
			message->setBody("Bad argument count. See 'help'.");
 
		}
 
	}
 
	else if (message->getBody().find("set_oauth2_code ") == 0) {
 
		std::string body = message->getBody();
 
		std::vector<std::string> args;
 
		boost::split(args, body, boost::is_any_of(" "));
 
		if (args.size() == 3) {
 
			std::string error = m_component->getFrontend()->setOAuth2Code(args[1], args[2]);
 
			if (error.empty()) {
 
				message->setBody("OAuth2 code and state set.");
 
			}
 
			else {
 
				message->setBody(error);
 
			}
 
		}
 
		else {
 
			message->setBody("Bad argument count. See 'help'.");
 
		}
 
	}
 
	else if (message->getBody().find("get_oauth2_url ") == 0) {
 
	else if (message->getBody().find("get_oauth2_url") == 0) {
 
		std::string body = message->getBody();
 
		std::vector<std::string> args;
 
		boost::split(args, body, boost::is_any_of(" "));
 
		if (args.size() == 3) {
 
			std::string url = m_component->getFrontend()->getOAuth2URL(args);
 
			message->setBody(url);
 
		}
 
		else {
 
			message->setBody("Bad argument count. See 'help'.");
 
		}
 
		std::string url = m_component->getFrontend()->getOAuth2URL(args);
 
		message->setBody(url);
 
	}
 
	else if (message->getBody() == "registration_fields") {
 
		std::string fields = m_component->getFrontend()->getRegistrationFields();
 
		message->setBody(fields);
 
	}
 
	else if (message->getBody().find("help") == 0) {
 
		std::string help;
 
		help += "General:\n";
 
		help += "    status - shows instance status\n";
 
		help += "    reload - Reloads config file\n";
 
		help += "    uptime - returns ptime in seconds\n";
 
		help += "Users:\n";
 
		help += "    online_users - returns list of all online users\n";
 
		help += "    online_users_count - number of online users\n";
 
		help += "    online_users_per_backend - shows online users per backends\n";
 
		help += "    has_online_user <bare_JID> - returns 1 if user is online\n";
 
		if (m_userRegistration) {
 
			help += "    register <bare_JID> <legacyName> <password> - registers the new user\n";
 
			help += "    unregister <bare_JID> - unregisters existing user\n";
 
		}
 
		help += "Messages:\n";
 
		help += "    messages_from_xmpp - get number of messages received from XMPP users\n";
 
		help += "    messages_to_xmpp - get number of messages sent to XMPP users\n";
 
		help += "Frontend:\n";
spectrum/src/frontends/slack/SlackUserRegistration.cpp
Show inline comments
 
@@ -41,49 +41,49 @@
 
#include <boost/date_time/posix_time/posix_time.hpp>
 
#include <boost/regex.hpp> 
 

	
 
using namespace Swift;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SlackUserRegistration");
 

	
 
SlackUserRegistration::SlackUserRegistration(Component *component, UserManager *userManager,
 
								   StorageBackend *storageBackend)
 
: UserRegistration(component, userManager, storageBackend) {
 
	m_component = component;
 
	m_config = m_component->getConfig();
 
	m_storageBackend = storageBackend;
 
	m_userManager = userManager;
 

	
 
}
 

	
 
SlackUserRegistration::~SlackUserRegistration(){
 
	
 
}
 

	
 
std::string SlackUserRegistration::createOAuth2URL(const std::vector<std::string> &args) {
 
	std::string redirect_url = "http://slack.spectrum.im/auth/" + CONFIG_STRING(m_config, "service.jid");
 
	std::string redirect_url = "http://slack.spectrum.im/oauth2/" + CONFIG_STRING(m_config, "service.jid");
 
	OAuth2 *oauth2 = new OAuth2(CONFIG_STRING_DEFAULTED(m_config, "service.client_id",""),
 
						  CONFIG_STRING_DEFAULTED(m_config, "service.client_secret",""),
 
						  "https://slack.com/oauth/authorize",
 
						  "https://slack.com/api/oauth.access",
 
						  redirect_url,
 
						  "channels:read channels:write team:read im:read im:write chat:write:bot");
 
	std::string url = oauth2->generateAuthURL();
 

	
 
	m_auths[oauth2->getState()] = oauth2;
 
	m_authsData[oauth2->getState()] = args;
 

	
 
	return url;
 
}
 

	
 
std::string SlackUserRegistration::getTeamDomain(const std::string &token) {
 
	std::string url = "https://slack.com/api/team.info?token=" + Util::urlencode(token);
 

	
 
	rapidjson::Document resp;
 
	HTTPRequest req(HTTPRequest::Get, url);
 
	if (!req.execute(resp)) {
 
		LOG4CXX_ERROR(logger, req.getError());
 
		return "";
 
	}
 

	
spectrum_manager/src/server.cpp
Show inline comments
 
#include "server.h"
 
#include "methods.h"
 

	
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <assert.h>
 
#include <string.h>
 
#include <time.h>
 
#include <stdarg.h>
 
#include <pthread.h>
 
#include <fstream>
 
#include <string>
 
#include <cerrno>
 

	
 
#define SESSION_TTL 120
 

	
 
static struct mg_serve_http_opts s_http_server_opts;
 

	
 
static int has_prefix(const struct mg_str *uri, const char *prefix) {
 
	size_t prefix_len = strlen(prefix);
 
	return uri->len >= prefix_len && memcmp(uri->p, prefix, prefix_len) == 0;
 
}
 

	
 
static std::string get_http_var(const struct http_message *hm, const char *name) {
 
	char data[4096];
 
	data[0] = '\0';
 

	
 
	mg_get_http_var(&hm->body, name, data, sizeof(data));
 
	if (data[0] != '\0') {
 
		return data;
 
	}
 

	
 
	mg_get_http_var(&hm->query_string, name, data, sizeof(data));
 
	if (data[0] != '\0') {
 
		return data;
 
	}
 

	
 
	return "";
 
}
 

	
 
static void my_strlcpy(char *dst, const char *src, size_t len) {
 
  strncpy(dst, src, len);
 
  dst[len - 1] = '\0';
 
}
 

	
 
// Generate session ID. buf must be 33 bytes in size.
 
@@ -530,48 +534,55 @@ void Server::serve_instances_register(struct mg_connection *conn, struct http_me
 
				<input type=\"text\" id=\"jid\" name=\"jid\" placeholder=\""+ fields[0] +"\"></textarea> \
 
			</label> \
 
			<label> \
 
				<span>" + fields[1] + ":</span> \
 
				<input type=\"text\" id=\"uin\" name=\"uin\" placeholder=\"" + fields[1] + "\"></textarea> \
 
			</label> \
 
			<label><span>" + fields[2] + ":</span> \
 
				<input type=\"password\" id=\"password\" name=\"password\" placeholder=\"" + fields[2] + "\"></textarea> \
 
			</label> \
 
			<label> \
 
				<span>&nbsp;</span> \
 
				<input type=\"submit\" class=\"button\" value=\"Register\" />\
 
			</label> \
 
			<input type=\"hidden\" name=\"instance\" value=\"" + instance + "\"></input> \
 
			</form><br/>";
 
		print_html(conn, hm, html);
 
	}
 
	else {
 
		std::string response = send_command(instance, "register " + jid + " " + uin + " " + password);
 
		if (!response.empty()) {
 
			std::string value = jid;
 
			int type = (int) TYPE_STRING;
 
			m_storage->updateUserSetting(info.id, instance, value);
 
		}
 

	
 
		response = send_command(instance, "get_oauth2_url " + jid);
 
		if (!response.empty()) {
 
			redirect_to(conn, hm, response.c_str());
 
			return;
 
		}
 

	
 
		redirect_to(conn, hm, "/instances");
 
	}
 

	
 
}
 

	
 
void Server::serve_instances(struct mg_connection *conn, struct http_message *hm) {
 
	std::string jid = get_http_var(hm, "jid");
 
	if (!jid.empty()) {
 
		serve_instance(conn, hm, jid);
 
		return;
 
	}
 

	
 
	std::vector<std::string> list = show_list(m_config, false);
 
	std::string html = "<h2>List of Spectrum 2 instances</h2>";
 

	
 
	Server:session *session = get_session(hm);
 

	
 
	if (session->admin) {
 
		if (list.empty()) {
 
			html += "<p>There are no Spectrum 2 instances yet. You can create new instance by adding configuration files into <pre>/etc/spectrum2/transports</pre> directory. You can then maintain the Spectrum 2 instance here.</p>";
 
		}
 
		else {
 
			html += "<table><tr><th>Hostname<th>Status</th><th>Command</th><th>Run command</th></tr>";
 
			BOOST_FOREACH(std::string &instance, list) {
 
@@ -628,69 +639,75 @@ void Server::serve_instances(struct mg_connection *conn, struct http_message *hm
 

	
 
					if (!value.empty()) {
 
						html += "<td>Running. Registered as " + value + "</td>";
 
						html += "<td><a href=\"/instances/unregister?instance=" + instance + "\">Unregister</a></td>";
 
					}
 
					else {
 
						html += "<td>Running. No account registered yet.</td>";
 
						html += "<td><a href=\"/instances/register?instance=" + instance + "\">Register</a></td>";
 
					}
 
				}
 
				else {
 
					html += "<td>" + response + "</td>";
 
					html += "<td>No available action</td>";
 
				}
 

	
 
				html += "</tr>";
 
			}
 

	
 
			html += "</table>";
 
		}
 
	}
 
	print_html(conn, hm, html);
 
}
 

	
 
void Server::serve_oauth2(struct mg_connection *conn, struct http_message *hm) {
 
	std::cout << "OAUTH2 handler\n";
 
}
 

	
 
void Server::event_handler(struct mg_connection *conn, int ev, void *p) {
 
	struct http_message *hm = (struct http_message *) p;
 

	
 
	if (ev != MG_EV_HTTP_REQUEST) {
 
		return;
 
	}
 

	
 
	if (!is_authorized(conn, hm)) {
 
		redirect_to(conn, hm, "/login");
 
	} else if (mg_vcmp(&hm->uri, "/authorize") == 0) {
 
		authorize(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/") == 0) {
 
		serve_instances(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/logout") == 0) {
 
		serve_logout(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/instances") == 0) {
 
		serve_instances(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/onlineusers") == 0) {
 
		serve_onlineusers(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/cmd") == 0) {
 
		serve_cmd(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/instances/start") == 0) {
 
		serve_instances_start(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/instances/stop") == 0) {
 
		serve_instances_stop(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/instances/register") == 0) {
 
		serve_instances_register(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/instances/unregister") == 0) {
 
		serve_instances_unregister(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/users") == 0) {
 
		serve_users(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/users/add") == 0) {
 
		serve_users_add(conn, hm);
 
	} else if (mg_vcmp(&hm->uri, "/users/remove") == 0) {
 
		serve_users_remove(conn, hm);
 
	} else if (has_prefix(&hm->uri, "/oauth2") == 0) {
 
		serve_oauth2(conn, hm);
 
	} else {
 
		mg_serve_http(conn, hm, s_http_server_opts);
 
	}
 

	
 
	conn->flags |= MG_F_SEND_AND_CLOSE;
 
}
 

	
 

	
 

	
 

	
spectrum_manager/src/server.h
Show inline comments
 
@@ -51,48 +51,49 @@ class Server {
 

	
 
		/// Constructor.
 
		Server(ManagerConfig *config, const std::string &config_file);
 

	
 
		/// Destructor
 
		virtual ~Server();
 

	
 
		bool start();
 

	
 
		void event_handler(struct mg_connection *nc, int ev, void *p);
 

	
 
	private:
 
		void serve_instance(struct mg_connection *conn, struct http_message *hm, const std::string &jid);
 
		void serve_instances(struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_start(struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_stop(struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_register(struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_unregister(struct mg_connection *conn, struct http_message *hm);
 
		void serve_users(struct mg_connection *conn, struct http_message *hm);
 
		void serve_users_add(struct mg_connection *conn, struct http_message *hm);
 
		void serve_users_remove(struct mg_connection *conn, struct http_message *hm);
 
		void serve_logout(struct mg_connection *conn, struct http_message *hm);
 
		void serve_onlineusers(struct mg_connection *conn, struct http_message *hm);
 
		void serve_cmd(struct mg_connection *conn, struct http_message *hm);
 
		void serve_oauth2(struct mg_connection *conn, struct http_message *hm);
 
		void print_html(struct mg_connection *conn, struct http_message *hm, const std::string &html);
 
		std::string send_command(const std::string &jid, const std::string &cmd);
 

	
 
	private:
 
		bool check_password(const std::string &user, const std::string &password);
 
		session *new_session(const std::string &user);
 
		session *get_session(struct http_message *hm);
 

	
 
		void authorize(struct mg_connection *conn, struct http_message *hm);
 

	
 
		bool is_authorized(const struct mg_connection *conn, struct http_message *hm);
 

	
 
		void redirect_to(struct mg_connection *conn, struct http_message *hm, const char *where);
 

	
 
	private:
 
		struct mg_mgr m_mgr;
 
		struct mg_connection *m_nc;
 

	
 
		std::map<std::string, session *> sessions;
 
		std::string m_user;
 
		std::string m_password;
 
		ManagerConfig *m_config;
 
		std::string m_header;
 
		std::string m_footer;
0 comments (0 inline, 0 general)