57 #include "core/auth/Token_odb.h"    70 #include <odb/session.hxx>    83     ASSERT_LOG(database, 
"No database object passed into WSServer.");
    84     using websocketpp::lib::placeholders::_1;
    85     using websocketpp::lib::placeholders::_2;
    91     srv_.set_reuse_addr(
true);
   140                "Someone is still using the WSService");
   145     INFO(
"New WebSocket connection !");
   147         std::make_pair(hdl, std::make_shared<APISession>(*
this)));
   152     INFO(
"WebSocket connection closed.");
   159                "Cannot retrieve API pointer from connection handle.");
   163     auto db_req_counter = 
dbsrv_->operation_count();
   171     catch (
const odb::exception &e)
   173         WARN(
"Database Error in WServer::on_message. Aborting request processing. "   177         response->status_string = e.what();
   184         audit->author(session_handle->current_user());
   185         auto ws_connection_ptr = 
srv_.get_con_from_hdl(hdl);
   186         ASSERT_LOG(ws_connection_ptr, 
"No websocket connection object from handle.");
   187         audit->source_endpoint(ws_connection_ptr->get_remote_endpoint());
   191         audit->request_content(msg->get_payload());
   193         req = json::parse(msg->get_payload());
   194         INFO(
"Incoming payload: \n" << req.dump(4));
   197         audit->uuid(input_msg.uuid);
   198         audit->method(input_msg.type);
   202     catch (
const std::invalid_argument &e)
   206         response->status_string = 
"Failed to parse JSON.";
   211         response->status_string = e.
what();
   216         audit->database_operations(
   217             static_cast<uint16_t>(
dbsrv_->operation_count() - db_req_counter));
   225     INFO(
"WebSockAPI server thread id is " << 
gettid());
   227     boost::asio::ip::tcp::endpoint endpoint(
   228         boost::asio::ip::address::from_string(interface), port);
   229     srv_.listen(endpoint);
   235         std::make_unique<Service>(*this));
   236     work_ = std::make_unique<boost::asio::io_service::work>(
srv_.get_io_service());
   238     DEBUG(
"END OF WSServer::run()");
   240                "Service has not been unregistered");
   245     srv_.get_io_service().post([
this]() {
   247         srv_.stop_listening();
   250             websocketpp::lib::error_code ec;
   251             srv_.close(con_session.first, 0, 
"bye", ec);
   252             if (ec.value() == websocketpp::error::value::invalid_state)
   259                        BUILD_STR(
"Websocketpp error: " << ec.message()));
   281                            .security_ctx = api_handle->security_context(),
   284         return asio_handler->second(ctx);
   289     odb::session database_session;
   291     api_handle->hook_before_request();
   299                            .security_ctx = api_handle->security_context(),
   303         return method_handler->process(in);
   309         if (api_handle->allowed(in.
type))
   311             auto method_ptr = handler_method->second;
   312             return ((*api_handle).*method_ptr)(in.
content);
   329                            .security_ctx = api_handle->security_context(),
   333         return crud_handler->process(in);
   352     json_message[
"uuid"]          = msg.
uuid;
   353     json_message[
"type"]          = msg.
type;
   354     json_message[
"status_code"]   = 
static_cast<int64_t
>(msg.
status_code);
   356     json_message[
"content"]       = msg.
content;
   358     srv_.send(hdl, json_message.dump(4), websocketpp::frame::opcode::text);
   368         msg.
uuid    = req.at(
"uuid");
   369         msg.
type    = req.at(
"type");
   370         msg.
content = req.at(
"content");
   372     catch (
const json::out_of_range &e)
   376     catch (
const std::domain_error &e)
   414     std::vector<Auth::TokenPtr> tokens_to_remove;
   417         const auto &session = connection_to_session.second;
   418         if (session->current_user_id() == user->id() && exception != session)
   421             if (
auto token = session->current_token())
   422                 tokens_to_remove.push_back(token);
   425             session->abort_session();
   428             msg.
content[
"reason"] = 
"Session cleared.";
   430             msg.
type              = 
"session_closed";
   435     for (
const auto &token : tokens_to_remove)
   445     using namespace Colorize;
   446     DEBUG(
"Performing registration of CRUD handler for resource "   447           << 
green(resource_name));
   474         audit->uuid(msg.
uuid);
   475         audit->method(msg.
type);
   482     catch (
const odb::exception &e)
   484         WARN(
"Database Error in WServer::on_message. Failed to persist final audit: "   493                                      const std::string &name)
   495     DEBUG(
"Scheduling ASIO-based-handler registration. (name: " << name << 
')');
   496     std::packaged_task<bool()> pt([=]() {
   499         DEBUG(
"Performing registration of ASIO-based-handler. (name: " << name
   504     std::future<bool> future = pt.get_future();
   506     srv_.get_io_service().post([&]() { pt(); });
   512     DEBUG(
"Scheduling removal of ASIO-based-handler (name " << name << 
')');
   513     std::promise<void> p;
   515     srv_.get_io_service().post([&]() {
   523     return p.get_future().get();
   529     std::promise<void> p;
   531     srv_.get_io_service().post([&]() {
   536     return p.get_future().get();
   544         INFO(
"WebSocket service has been unregistered.");
 
json system_overview(const json &req)
Presents an overview of the system to the end user. 
ClientMessage parse_request(const json &in)
Create a ClientMessage object from a json request. 
uint64_t gettid()
Return the Linux thread ID. 
static CRUDResourceHandlerUPtr instanciate(RequestContext)
An authentication token used for authenticating a user against Leosac. 
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
Acts like an odb::transaction, with the exception that it will becomes the active transaction at cons...
CRUDResourceHandlerUPtr(*)(RequestContext) Factory
A service object provided by the Websocket module. 
An internal database operation threw an exception. 
This is the header file for a generated source file, GitSHA1.cpp. 
bool has_handler(const std::string &name) const
Returns true if an handler named name already exists. 
std::string status_string
This class is dedicated to converting exception thrown by various code into a ServerMessage that can ...
static CRUDResourceHandlerUPtr instanciate(RequestContext)
void register_crud_handler(const std::string &resource_name, CRUDResourceHandler::Factory factory)
An internal helper function to register a CRUD resource handler. 
static MethodHandlerUPtr create(RequestContext)
std::shared_ptr< IWSAPICall > IWSAPICallPtr
static CRUDResourceHandlerUPtr instanciate(RequestContext)
std::map< std::string, json(APISession::*)(const json &)> handlers_
This maps (string) command name to API method. 
APIStatusCode status_code
boost::optional< ServerMessage > handle_request(APIPtr api_handle, const ClientMessage &msg, Audit::IAuditEntryPtr)
Handle a request. 
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
void commit()
Commit the transaction. 
void on_close(websocketpp::connection_hdl hdl)
void register_crud_handler_external(const std::string &resource_name, CRUDResourceHandler::Factory factory)
Register a CRUD handler from an external thread. 
ServiceRegistry & get_service_registry()
A function to retrieve the ServiceRegistry from pretty much anywhere. 
An optional transaction is an object that behave like an odb::transaction if there is no currently ac...
std::shared_ptr< IAuditEntry > IAuditEntryPtr
std::unique_ptr< CRUDResourceHandler > CRUDResourceHandlerUPtr
static MethodHandlerUPtr create(RequestContext)
void finalize_audit(const Audit::IWSAPICallPtr &audit, ServerMessage &msg)
Extract values from the msg and finalizes the audit object with them. 
static CRUDResourceHandlerUPtr instanciate(RequestContext)
static CRUDResourceHandlerUPtr instanciate(RequestContext)
static CRUDResourceHandlerUPtr instanciate(RequestContext)
json logout(const json &req)
Log an user out. 
DBServicePtr dbsrv_
Database service object. 
static MethodHandlerUPtr create(RequestContext)
virtual const char * what() const noexcept final
RegistrationHandle register_service(std::unique_ptr< ServiceInterface > srv)
Register a service by passing an unique_ptr to it. 
std::unique_ptr< MethodHandler > MethodHandlerUPtr
static MethodHandlerUPtr create(RequestContext)
boost::optional< json > dispatch_request(APIPtr api_handle, const ClientMessage &in, Audit::IAuditEntryPtr)
Dispatch the request from a client, so that it is processed by the appropriate handler. 
static MethodHandlerUPtr create(RequestContext)
An exception that can be throw when the permission for a given operation is denied. 
APIAuth & auth()
Retrieve the authentication helper. 
json get_leosac_version(const json &)
Retrieve the current version number of Leosac. 
std::string green(const T &in)
void attempt_unregister_ws_service()
bool unregister_service(RegistrationHandle h)
Unregister a service using the RegistrationHandle that was returned from the register_service() call...
DBPtr db()
Retrieve database handle. 
std::shared_ptr< DBService > DBServicePtr
std::shared_ptr< User > UserPtr
All modules that provides features to Leosac shall be in this namespace. 
static CRUDResourceHandlerUPtr instanciate(RequestContext)
CoreUtilsPtr core_utils()
Retrieve the CoreUtils pointer. 
static MethodHandlerUPtr create(RequestContext)
Provides various database-related services to consumer. 
WSServer(WebSockAPIModule &module, DBPtr database)
The source packet was malformed. 
std::map< std::string, MethodHandler::Factory > individual_handlers_
#define ASSERT_LOG(cond, msg)
std::map< std::string, CRUDResourceHandler::Factory > crud_handlers_
std::map< std::string, Service::WSHandler > asio_handlers_
Handlers registered through the WebSockAPI::Service object. 
void clear_user_sessions(Auth::UserPtr user, APIPtr exception)
Deauthenticate all the connections of user, except the exception APISession. 
static MethodHandlerUPtr create(RequestContext)
void run(const std::string &interface, uint16_t port)
WebSockAPIModule & module_
A reference to the module. 
static MethodHandlerUPtr create(RequestContext)
json authenticate_with_token(const json &req)
Attempt to authenticate with a (previously generated) authentication token. 
std::shared_ptr< APISession > APIPtr
#define BUILD_STR(param)
Internal macro. 
static MethodHandlerUPtr create(RequestContext)
A message sent by the server to a client. 
std::shared_ptr< CoreUtils > CoreUtilsPtr
static MethodHandlerUPtr create(RequestContext)
A message sent by a client to Leosac. 
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
ConnectionAPIMap connection_session_
void start_shutdown()
Start the process of shutting down the server. 
static CRUDResourceHandlerUPtr instanciate(RequestContext)
json create_auth_token(const json &req)
Generate an authentication token using the user credential, and logs the user in on success...
static MethodHandlerUPtr create(RequestContext)
void on_message(websocketpp::connection_hdl hdl, Server::message_ptr msg)
A websocket message has been received. 
Holds valuable pointer to provide context to a request. 
DBServicePtr dbsrv()
Retrieve database service pointer. 
static MethodHandlerUPtr create(RequestContext)
Indicate that the request's processing went well. 
std::shared_ptr< odb::database > DBPtr
bool register_asio_handler(const Service::WSHandler &handler, const std::string &name)
This function block the calling thread until the WebSocket thread has processed the handler registrat...
std::unique_ptr< boost::asio::io_service::work > work_
Work used to keep the io_service alive while someone has a reference to (WS) Service object...
This class is responsible for providing an API to manage authentication for Websocket client...
void on_open(websocketpp::connection_hdl hdl)
static MethodHandlerUPtr create(RequestContext)
ServerMessage convert_merge(const std::exception_ptr &ptr, const ServerMessage &msg)
Convert the exception_ptr to a ServerMessage and merge it with an other message. 
static IWSAPICallPtr WSAPICall(const DBPtr &database)
void send_message(websocketpp::connection_hdl hdl, const ServerMessage &msg)
Send a message over a connection. 
A module that provide a websocket interface to Leosac. 
void unregister_handler(const std::string &name)
Remove an Asio based handler. 
std::function< boost::optional< json >(const RequestContext &)> WSHandler
CoreUtilsPtr core_utils()
This module explicitly expose CoreUtils to other object in the module.