diff --git a/spectrum_manager/src/server.cpp b/spectrum_manager/src/server.cpp index 65152e6d6d63522076e7e2cf94a903c16d398e8f..b255f505934c3a4f725026130a9c421433f69db5 100644 --- a/spectrum_manager/src/server.cpp +++ b/spectrum_manager/src/server.cpp @@ -51,7 +51,7 @@ static void _event_handler(struct mg_connection *nc, int ev, void *p) { static_cast(nc->mgr->user_data)->event_handler(nc, ev, p); } -Server::Server(ManagerConfig *config) { +Server::Server(ManagerConfig *config, const std::string &config_file) { srand((unsigned) time(0)); m_config = config; m_user = CONFIG_STRING(m_config, "service.admin_username"); @@ -80,10 +80,29 @@ Server::Server(ManagerConfig *config) { footer.read(&m_footer[0], m_footer.size()); footer.close(); } + + m_storageCfg = new Config(); + m_storageCfg->load(config_file); + + std::string error; + m_storage = StorageBackend::createBackend(m_storageCfg, error); + if (m_storage == NULL) { + std::cerr << "Error creating StorageBackend! " << error << "\n"; + std::cerr << "Registering new Spectrum 2 manager users won't work" << "\n"; + } + else if (!m_storage->connect()) { + delete m_storage; + m_storage = NULL; + std::cerr << "Can't connect to database!\n"; + } } Server::~Server() { mg_mgr_free(&m_mgr); + if (m_storage) { + delete m_storage; + } + delete m_storageCfg; } bool Server::start() { @@ -95,7 +114,16 @@ bool Server::start() { } bool Server::check_password(const std::string &user, const std::string &password) { - return (m_user == user && m_password == password); + if (m_user == user && m_password == password) { + return true; + } + + UserInfo info; + if (m_storage && m_storage->getUser(user, info) == true && info.password == password) { + return true; + } + + return false; } // Allocate new session object @@ -192,6 +220,25 @@ void Server::print_html(struct mg_connection *conn, struct http_message *hm, con (int) html.size() + m_header.size() + m_footer.size(), m_header.c_str(), html.c_str(), m_footer.c_str()); } +std::string Server::send_command(const std::string &jid, const std::string &cmd) { + Swift::SimpleEventLoop eventLoop; + Swift::BoostNetworkFactories networkFactories(&eventLoop); + + ask_local_server(m_config, networkFactories, jid, cmd); + eventLoop.runUntilEvents(); + struct timeval td_start,td_end; + float elapsed = 0; + gettimeofday(&td_start, NULL); + + time_t started = time(NULL); + while(get_response().empty() && td_end.tv_sec - td_start.tv_sec < 1) { + gettimeofday(&td_end, NULL); + eventLoop.runOnce(); + } + + return get_response(); +} + void Server::serve_onlineusers(struct mg_connection *conn, struct http_message *hm) { std::string html; std::string jid = get_http_var(hm, "jid"); @@ -244,18 +291,80 @@ void Server::serve_cmd(struct mg_connection *conn, struct http_message *hm) { print_html(conn, hm, html); } +void Server::serve_users_add(struct mg_connection *conn, struct http_message *hm) { + std::string user = get_http_var(hm, "user"); + std::string password = get_http_var(hm, "password"); + + if (!user.empty() && !password.empty()) { + UserInfo info; + info.jid = user; + info.password = password; + if (m_storage) { + m_storage->setUser(info); + } + } + redirect_to(conn, hm, "/users"); +} + +void Server::serve_users(struct mg_connection *conn, struct http_message *hm) { + std::string html = "

Spectrum 2 manager users

"; + + html += "

Here, you can add new users who will have access to this web interface. " + "These users will be able to register new accounts on all Spectrum 2 instances " + "running on these server. They won't be able to change any Spectrum 2 instance " + "configuration influencing other users.

"; + + if (!m_storage) { + print_html(conn, hm, html); + return; + } + + html += "
\ +

Add user \ + Add new user to Spectrum 2 manager web interface. \ +

\ + \ + \ + \ +

"; + std::vector users; + m_storage->getUsers(users); + + html += ""; + BOOST_FOREACH(std::string &jid, users) { + html += ""; + html += ""; + html += ""; + html += ""; + } + html += "
UserAction
" + jid + "
"; + + print_html(conn, hm, html); +} -void Server::serve_start(struct mg_connection *conn, struct http_message *hm) { +void Server::serve_instances_start(struct mg_connection *conn, struct http_message *hm) { std::string html; std::string jid = get_http_var(hm, "jid"); + if (jid.empty()) { + redirect_to(conn, hm, "/"); + return; + } start_instances(m_config, jid); + html += "

Starting Spectrum 2 instance

"; html += "" + get_response() + "
Back to main page"; - html += ""; print_html(conn, hm, html); } -void Server::serve_stop(struct mg_connection *conn, struct http_message *hm) { +void Server::serve_instances_stop(struct mg_connection *conn, struct http_message *hm) { std::string html; std::string jid = get_http_var(hm, "jid"); @@ -264,44 +373,154 @@ void Server::serve_stop(struct mg_connection *conn, struct http_message *hm) { html += ""; print_html(conn, hm, html); } -void Server::serve_root(struct mg_connection *conn, struct http_message *hm) { - std::vector list = show_list(m_config, false); - std::string html = "

List of instances

"; - if (list.empty()) { - html += "

There are no Spectrum 2 instances yet. You can create new instance by adding configuration files into

/etc/spectrum2/transports
directory. You can then maintain the Spectrum 2 instance here.

"; +void Server::serve_instance(struct mg_connection *conn, struct http_message *hm, const std::string &jid) { + std::string html = "

Spectrum 2 instance: " + jid + "

"; + + print_html(conn, hm, html); +} + +void Server::serve_instances_unregister(struct mg_connection *conn, struct http_message *hm) { + +} + +void Server::serve_instances_register(struct mg_connection *conn, struct http_message *hm) { + std::string instance = get_http_var(hm, "instance"); + if (!instance.empty()) { + serve_instance(conn, hm, instance); + return; + } + + std::string jid = get_http_var(hm, "jid"); + std::string uin = get_http_var(hm, "uin"); + std::string password = get_http_var(hm, "password"); + Server:session *session = get_session(hm); + UserInfo info; + m_storage->getUser(session->user, info); + + if (uin.empty() || password.empty()) { + std::string html = "

Register Spectrum 2 instance

"; + html += "
\ +

Register Spectrum 2 instance \ + Write the Slack team name, 3rd-party network username and password. \ +

\ + \ + \ + \ + \ +

"; + print_html(conn, hm, html); } else { - html += ""; - BOOST_FOREACH(std::string &instance, list) { - html += ""; - html += ""; - Swift::SimpleEventLoop eventLoop; - Swift::BoostNetworkFactories networkFactories(&eventLoop); - - ask_local_server(m_config, networkFactories, instance, "status"); - eventLoop.runUntilEvents(); - while(get_response().empty()) { - eventLoop.runUntilEvents(); - } - html += ""; - if (get_response().find("Running") == 0) { - html += ""; - html += ""; - } - else { - html += ""; - html += ""; + std::string response = send_command(jid, "register " + jid + " " + uin + " " + password); + if (!response.empty()) { + std::string value = jid; + int type = (int) TYPE_STRING; + m_storage->updateUserSetting(info.id, jid, value); + } + 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 list = show_list(m_config, false); + std::string html = "

List of Spectrum 2 instances

"; + + Server:session *session = get_session(hm); + + if (session->admin) { + if (list.empty()) { + html += "

There are no Spectrum 2 instances yet. You can create new instance by adding configuration files into

/etc/spectrum2/transports
directory. You can then maintain the Spectrum 2 instance here.

"; + } + else { + html += "
JIDStatusCommandRun command
" + instance + "" + get_response() + "Stop
"; - html += ""; - html += ""; - html += ""; - html += "
Start
"; + BOOST_FOREACH(std::string &instance, list) { + html += ""; + html += ""; + + std::string response = send_command(instance, "status"); + if (response.empty()) { + response = "Cannot get the server status"; + } + + html += ""; + if (response.find("Running") == 0) { + html += ""; + html += ""; + } + else { + html += ""; + html += ""; + } + + html += ""; } - html += ""; + html += "
HostnameStatusCommandRun command
" + instance + "" + response + "Stop
"; + html += ""; + html += ""; + html += ""; + html += "
Start
"; } + } + else { + UserInfo info; + m_storage->getUser(session->user, info); - html += ""; + if (list.empty()) { + html += "

There are no Spectrum 2 instances yet.

"; + } + else { + html += ""; + BOOST_FOREACH(std::string &instance, list) { + html += ""; + html += ""; + + std::string response = send_command(instance, "status"); + if (response.empty()) { + response = "Cannot get the server status"; + } + + html += ""; + if (response.find("Running") == 0) { + std::string value = ""; + int type = (int) TYPE_STRING; + m_storage->getUserSetting(info.id, instance, type, value); + + if (!value.empty()) { + html += ""; + } + else { + html += ""; + } + } + else { + html += ""; + } + + html += ""; + } + + html += "
HostnameStatusAction
" + instance + "" + response + "UnregisterRegisterNo available action
"; + } } print_html(conn, hm, html); } @@ -318,15 +537,25 @@ void Server::event_handler(struct mg_connection *conn, int ev, void *p) { } else if (mg_vcmp(&hm->uri, "/authorize") == 0) { authorize(conn, hm); } else if (mg_vcmp(&hm->uri, "/") == 0) { - serve_root(conn, hm); + serve_instances(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, "/start") == 0) { - serve_start(conn, hm); - } else if (mg_vcmp(&hm->uri, "/stop") == 0) { - serve_stop(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 { mg_serve_http(conn, hm, s_http_server_opts); }