|
Leosac
0.8.0
Open Source Access Control
|
Go to the documentation of this file.
57 #include "core/auth/Token_odb.h"
69 #include <nlohmann/json.hpp>
70 #include <odb/session.hxx>
80 , dbsrv_(std::make_shared<
DBService>(database))
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.");
uint64_t gettid()
Return the Linux thread ID.
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.
bool unregister_service(RegistrationHandle h)
Unregister a service using the RegistrationHandle that was returned from the register_service() call.
An optional transaction is an object that behave like an odb::transaction if there is no currently ac...
virtual const char * what() const noexcept final
static MethodHandlerUPtr create(RequestContext)
void commit()
Commit the transaction, if there was no currently active transaction at the time of this object's cre...
@ SUCCESS
Indicate that the request's processing went well.
static CRUDResourceHandlerUPtr instanciate(RequestContext)
static MethodHandlerUPtr create(RequestContext)
json get_leosac_version(const json &)
Retrieve the current version number of Leosac.
WSServer(WebSockAPIModule &module, DBPtr database)
std::map< std::string, MethodHandler::Factory > individual_handlers_
#define BUILD_STR(param)
Internal macro.
An authentication token used for authenticating a user against Leosac.
APIStatusCode status_code
static MethodHandlerUPtr create(RequestContext)
void on_open(websocketpp::connection_hdl hdl)
A message sent by the server to a client.
ServiceRegistry & get_service_registry()
A function to retrieve the ServiceRegistry from pretty much anywhere.
void register_crud_handler_external(const std::string &resource_name, CRUDResourceHandler::Factory factory)
Register a CRUD handler from an external thread.
static MethodHandlerUPtr create(RequestContext)
static CRUDResourceHandlerUPtr instanciate(RequestContext)
std::map< std::string, CRUDResourceHandler::Factory > crud_handlers_
std::unique_ptr< CRUDResourceHandler > CRUDResourceHandlerUPtr
#define ASSERT_LOG(cond, msg)
static MethodHandlerUPtr create(RequestContext)
void unregister_handler(const std::string &name)
Remove an Asio based handler.
void run(const std::string &interface, uint16_t port)
std::shared_ptr< User > UserPtr
APIAuth & auth()
Retrieve the authentication helper.
This class is responsible for providing an API to manage authentication for Websocket client.
static MethodHandlerUPtr create(RequestContext)
A message sent by a client to Leosac.
void clear_user_sessions(Auth::UserPtr user, APIPtr exception)
Deauthenticate all the connections of user, except the exception APISession.
std::shared_ptr< odb::database > DBPtr
CRUDResourceHandlerUPtr(*)(RequestContext) Factory
void send_message(websocketpp::connection_hdl hdl, const ServerMessage &msg)
Send a message over a connection.
static MethodHandlerUPtr create(RequestContext)
static CRUDResourceHandlerUPtr instanciate(RequestContext)
static MethodHandlerUPtr create(RequestContext)
std::shared_ptr< IAuditEntry > IAuditEntryPtr
All modules that provides features to Leosac shall be in this namespace.
json logout(const json &req)
Log an user out.
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Provides various database-related services to consumer.
void on_message(websocketpp::connection_hdl hdl, Server::message_ptr msg)
A websocket message has been received.
std::map< std::string, Service::WSHandler > asio_handlers_
Handlers registered through the WebSockAPI::Service object.
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 MethodHandlerUPtr create(RequestContext)
This class is dedicated to converting exception thrown by various code into a ServerMessage that can ...
CoreUtilsPtr core_utils()
This module explicitly expose CoreUtils to other object in the module.
A module that provide a websocket interface to Leosac.
static MethodHandlerUPtr create(RequestContext)
json system_overview(const json &req)
Presents an overview of the system to the end user.
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
This is the header file for a generated source file, GitSHA1.cpp.
A service object provided by the Websocket module.
std::string status_string
static MethodHandlerUPtr create(RequestContext)
ConnectionAPIMap connection_session_
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
WebSockAPIModule & module_
A reference to the module.
void commit()
Commit the transaction.
void finalize_audit(const Audit::IWSAPICallPtr &audit, ServerMessage &msg)
Extract values from the msg and finalizes the audit object with them.
boost::optional< ServerMessage > handle_request(APIPtr api_handle, const ClientMessage &msg, Audit::IAuditEntryPtr)
Handle a request.
Acts like an odb::transaction, with the exception that it will becomes the active transaction at cons...
std::shared_ptr< DBService > DBServicePtr
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::function< boost::optional< json >(const RequestContext &)> WSHandler
bool has_handler(const std::string &name) const
Returns true if an handler named name already exists.
@ MALFORMED
The source packet was malformed.
static CRUDResourceHandlerUPtr instanciate(RequestContext)
static CRUDResourceHandlerUPtr instanciate(RequestContext)
std::string green(const T &in)
static CRUDResourceHandlerUPtr instanciate(RequestContext)
std::shared_ptr< IWSAPICall > IWSAPICallPtr
void on_close(websocketpp::connection_hdl hdl)
std::unique_ptr< MethodHandler > MethodHandlerUPtr
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
CoreUtilsPtr core_utils()
Retrieve the CoreUtils pointer.
RegistrationHandle register_service(std::unique_ptr< ServiceInterface > srv)
Register a service by passing an unique_ptr to it.
DBServicePtr dbsrv_
Database service object.
DBPtr db()
Retrieve database handle.
std::shared_ptr< APISession > APIPtr
ClientMessage parse_request(const json &in)
Create a ClientMessage object from a json request.
static MethodHandlerUPtr create(RequestContext)
void start_shutdown()
Start the process of shutting down the server.
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.
Holds valuable pointer to provide context to a request.
static CRUDResourceHandlerUPtr instanciate(RequestContext)
json authenticate_with_token(const json &req)
Attempt to authenticate with a (previously generated) authentication token.
static IWSAPICallPtr WSAPICall(const DBPtr &database)
DBServicePtr dbsrv()
Retrieve database service pointer.
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 attempt_unregister_ws_service()
std::shared_ptr< CoreUtils > CoreUtilsPtr
void register_crud_handler(const std::string &resource_name, CRUDResourceHandler::Factory factory)
An internal helper function to register a CRUD resource handler.
@ DATABASE_ERROR
An internal database operation threw an exception.
std::map< std::string, json(APISession::*)(const json &)> handlers_
This maps (string) command name to API method.
An exception that can be throw when the permission for a given operation is denied.
static MethodHandlerUPtr create(RequestContext)