Leosac  0.7.0
OpenSourceAccessControl
WSServer.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2016 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "WSServer.hpp"
21 #include "ExceptionConverter.hpp"
22 #include "Exceptions.hpp"
23 #include "Service.hpp"
24 #include "WebSockAPI.hpp"
25 #include "api/AccessOverview.hpp"
26 #include "api/AccessPointCRUD.hpp"
27 #include "api/AuditGet.hpp"
28 #include "api/CredentialCRUD.hpp"
29 #include "api/DoorCRUD.hpp"
30 #include "api/GroupCRUD.hpp"
31 #include "api/LogGet.hpp"
32 #include "api/MembershipCRUD.hpp"
33 #include "api/PasswordChange.hpp"
34 #include "api/Restart.hpp"
35 #include "api/ScheduleCRUD.hpp"
36 #include "api/UserCRUD.hpp"
37 #include "api/ZoneCRUD.hpp"
53 #include "core/CoreUtils.hpp"
56 #include "core/audit/WSAPICall.hpp"
57 #include "core/auth/Token_odb.h"
58 #include "core/auth/User.hpp"
63 #include "tools/db/DBService.hpp"
67 #include "tools/log.hpp"
69 #include <json.hpp>
70 #include <odb/session.hxx>
71 
72 using namespace Leosac;
73 using namespace Leosac::Module;
74 using namespace Leosac::Module::WebSockAPI;
75 
77 
79  : auth_(*this)
80  , dbsrv_(std::make_shared<DBService>(database))
81  , module_(module)
82 {
83  ASSERT_LOG(database, "No database object passed into WSServer.");
84  using websocketpp::lib::placeholders::_1;
85  using websocketpp::lib::placeholders::_2;
86  srv_.init_asio();
87 
88  srv_.set_open_handler(std::bind(&WSServer::on_open, this, _1));
89  srv_.set_close_handler(std::bind(&WSServer::on_close, this, _1));
90  srv_.set_message_handler(std::bind(&WSServer::on_message, this, _1, _2));
91  srv_.set_reuse_addr(true);
92  // clear all logs.
93  // srv_.clear_access_channels(websocketpp::log::alevel::all);
94 
95 
96  // Register internal handlers, ie handler that are managed by the Websocket
97  // module itself.
98 
99  handlers_["get_leosac_version"] = &APISession::get_leosac_version;
100  handlers_["create_auth_token"] = &APISession::create_auth_token;
101  handlers_["authenticate_with_token"] = &APISession::authenticate_with_token;
102  handlers_["logout"] = &APISession::logout;
103  handlers_["system_overview"] = &APISession::system_overview;
104 
105  individual_handlers_["audit.get"] = &AuditGet::create;
106  individual_handlers_["get_logs"] = &LogGet::create;
107  individual_handlers_["password_change"] = &PasswordChange::create;
108  individual_handlers_["search.group_name"] = &GroupSearch::create;
109  individual_handlers_["search.door_alias"] = &DoorSearch::create;
110  individual_handlers_["search.access_point_alias"] = &AccessPointSearch::create;
111  individual_handlers_["search.schedule_name"] = &ScheduleSearch::create;
112  individual_handlers_["search.zone_alias"] = &ZoneSearch::create;
113  individual_handlers_["search.user_username"] = &UserSearch::create;
114  individual_handlers_["search.credential_alias"] = &CredentialSearch::create;
115  individual_handlers_["search.hardware_name"] = &HardwareSearch::create;
116  individual_handlers_["access_overview"] = &AccessOverview::create;
117  individual_handlers_["check_update"] = &CheckUpdate::create;
118  individual_handlers_["create_update"] = &CreateUpdate::create;
119  individual_handlers_["ack_update"] = &AckUpdate::create;
120  individual_handlers_["cancel_update"] = &CancelUpdate::create;
121  individual_handlers_["get_update_history"] = &UpdateHistory::create;
122  individual_handlers_["get_pending_update"] = &PendingUpdateGet::create;
123  individual_handlers_["get_update"] = &UpdateGet::create;
125 
128  register_crud_handler("user-group-membership",
135 }
136 
138 {
139  ASSERT_LOG(get_service_registry().use_count<Service>() <= 0,
140  "Someone is still using the WSService");
141 }
142 
143 void WSServer::on_open(websocketpp::connection_hdl hdl)
144 {
145  INFO("New WebSocket connection !");
146  connection_session_.insert(
147  std::make_pair(hdl, std::make_shared<APISession>(*this)));
148 }
149 
150 void WSServer::on_close(websocketpp::connection_hdl hdl)
151 {
152  INFO("WebSocket connection closed.");
153  connection_session_.erase(hdl);
154 }
155 
156 void WSServer::on_message(websocketpp::connection_hdl hdl, Server::message_ptr msg)
157 {
159  "Cannot retrieve API pointer from connection handle.");
160  auto session_handle = connection_session_.find(hdl)->second;
161 
162  // todo maybe parse first so be we can have better error handling.
163  auto db_req_counter = dbsrv_->operation_count();
164  Audit::IWSAPICallPtr audit;
165  boost::optional<ServerMessage> response = ServerMessage();
166  json req;
167  try
168  {
169  audit = Audit::Factory::WSAPICall(dbsrv_->db());
170  }
171  catch (const odb::exception &e)
172  {
173  WARN("Database Error in WServer::on_message. Aborting request processing. "
174  "Error: "
175  << e.what());
176  response->status_code = APIStatusCode::DATABASE_ERROR;
177  response->status_string = e.what();
178  send_message(hdl, *response);
179  return;
180  }
181  try
182  {
183  audit->event_mask(Audit::EventType::WSAPI_CALL);
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());
188 
189  // todo careful potential DDOS as we store the full content without checking
190  // for now.
191  audit->request_content(msg->get_payload());
192  // Parse request, and copy uuid/method into the audit object.
193  req = json::parse(msg->get_payload());
194  INFO("Incoming payload: \n" << req.dump(4));
195 
196  ClientMessage input_msg = parse_request(req);
197  audit->uuid(input_msg.uuid);
198  audit->method(input_msg.type);
199  dbsrv_->update(*audit); // update audit with new info
200  response = handle_request(session_handle, input_msg, audit);
201  }
202  catch (const std::invalid_argument &e)
203  {
204  // JSON parse error
205  response->status_code = APIStatusCode::MALFORMED;
206  response->status_string = "Failed to parse JSON.";
207  }
208  catch (const MalformedMessage &e)
209  {
210  response->status_code = APIStatusCode::MALFORMED;
211  response->status_string = e.what();
212  }
213 
214  if (response)
215  {
216  audit->database_operations(
217  static_cast<uint16_t>(dbsrv_->operation_count() - db_req_counter));
218  finalize_audit(audit, *response);
219  send_message(hdl, *response);
220  }
221 }
222 
223 void WSServer::run(const std::string &interface, uint16_t port)
224 {
225  INFO("WebSockAPI server thread id is " << gettid());
226 
227  boost::asio::ip::tcp::endpoint endpoint(
228  boost::asio::ip::address::from_string(interface), port);
229  srv_.listen(endpoint);
230  srv_.start_accept();
231 
232  // std::this_thread::sleep_for(std::chrono::milliseconds(2000));
233 
235  std::make_unique<Service>(*this));
236  work_ = std::make_unique<boost::asio::io_service::work>(srv_.get_io_service());
237  srv_.run();
238  DEBUG("END OF WSServer::run()");
239  ASSERT_LOG(get_service_registry().get_service<Service>() == nullptr,
240  "Service has not been unregistered");
241 }
242 
244 {
245  srv_.get_io_service().post([this]() {
247  srv_.stop_listening();
248  for (auto con_session : connection_session_)
249  {
250  websocketpp::lib::error_code ec;
251  srv_.close(con_session.first, 0, "bye", ec);
252  if (ec.value() == websocketpp::error::value::invalid_state)
253  {
254  // Maybe the connection is already dead at this point.
255  // We can then safely ignore this error code.
256  continue;
257  }
258  ASSERT_LOG(ec.value() == 0,
259  BUILD_STR("Websocketpp error: " << ec.message()));
260  }
261  });
262 }
263 
265 {
266  return auth_;
267 }
268 
269 boost::optional<json> WSServer::dispatch_request(APIPtr api_handle,
270  const ClientMessage &in,
271  Audit::IAuditEntryPtr audit)
272 {
273  // Handlers registered by others modules.
274  auto asio_handler = asio_handlers_.find(in.type);
275  if (asio_handler != asio_handlers_.end())
276  {
277  RequestContext ctx{.session = api_handle,
278  .dbsrv = dbsrv_,
279  .server = *this,
280  .original_msg = in,
281  .security_ctx = api_handle->security_context(),
282  .audit = audit};
283  // Will block the current thread until the response has been built.
284  return asio_handler->second(ctx);
285  }
286 
287  // A request is an "Unit-of-Work" for the application.
288  // We create a default database session for the request.
289  odb::session database_session;
290  auto handler_factory = individual_handlers_.find(in.type);
291  api_handle->hook_before_request();
292 
293  if (handler_factory != individual_handlers_.end())
294  {
295  RequestContext ctx{.session = api_handle,
296  .dbsrv = dbsrv_,
297  .server = *this,
298  .original_msg = in,
299  .security_ctx = api_handle->security_context(),
300  .audit = audit};
301 
302  MethodHandlerUPtr method_handler = handler_factory->second(ctx);
303  return method_handler->process(in);
304  }
305 
306  auto handler_method = handlers_.find(in.type);
307  if (handler_method != handlers_.end())
308  {
309  if (api_handle->allowed(in.type))
310  {
311  auto method_ptr = handler_method->second;
312  return ((*api_handle).*method_ptr)(in.content);
313  }
314  else
315  {
316  throw PermissionDenied();
317  }
318  }
319 
320  auto crud_handler_factory = crud_handlers_.find(in.type);
321  if (crud_handler_factory == crud_handlers_.end())
322  throw InvalidCall();
323  else
324  {
325  RequestContext ctx{.session = api_handle,
326  .dbsrv = dbsrv_,
327  .server = *this,
328  .original_msg = in,
329  .security_ctx = api_handle->security_context(),
330  .audit = audit};
331 
332  CRUDResourceHandlerUPtr crud_handler = crud_handler_factory->second(ctx);
333  return crud_handler->process(in);
334  }
335 }
336 
338 {
339  return dbsrv_->db();
340 }
341 
343 {
344  return module_.core_utils();
345 }
346 
347 void WSServer::send_message(websocketpp::connection_hdl hdl,
348  const ServerMessage &msg)
349 {
350  json json_message;
351 
352  json_message["uuid"] = msg.uuid;
353  json_message["type"] = msg.type;
354  json_message["status_code"] = static_cast<int64_t>(msg.status_code);
355  json_message["status_string"] = msg.status_string;
356  json_message["content"] = msg.content;
357 
358  srv_.send(hdl, json_message.dump(4), websocketpp::frame::opcode::text);
359 }
360 
362 {
363  ClientMessage msg;
364 
365  try
366  {
367  // Extract general message argument.
368  msg.uuid = req.at("uuid");
369  msg.type = req.at("type");
370  msg.content = req.at("content");
371  }
372  catch (const json::out_of_range &e)
373  {
374  throw MalformedMessage();
375  }
376  catch (const std::domain_error &e)
377  {
378  throw MalformedMessage();
379  }
380  return msg;
381 }
382 
383 boost::optional<ServerMessage> WSServer::handle_request(APIPtr api_handle,
384  const ClientMessage &msg,
385  Audit::IAuditEntryPtr audit)
386 {
387  ServerMessage response;
389  response.content = {};
390  try
391  {
392  response.uuid = msg.uuid;
393  response.type = msg.type;
394  auto opt_json = dispatch_request(api_handle, msg, audit);
395  if (opt_json)
396  {
397  response.content = *opt_json;
398  return response;
399  }
400  return boost::none;
401  }
402  catch (...)
403  {
404  return ExceptionConverter().convert_merge(std::current_exception(),
405  response);
406  }
407  return response;
408 }
409 
411 {
412  db::OptionalTransaction t(dbsrv_->db()->begin());
413 
414  std::vector<Auth::TokenPtr> tokens_to_remove;
415  for (const auto &connection_to_session : connection_session_)
416  {
417  const auto &session = connection_to_session.second;
418  if (session->current_user_id() == user->id() && exception != session)
419  {
420  // Mark the token for invalidation.
421  if (auto token = session->current_token())
422  tokens_to_remove.push_back(token);
423 
424  // Clear authentication status from this user.
425  session->abort_session();
426  // Notify them
427  ServerMessage msg;
428  msg.content["reason"] = "Session cleared.";
430  msg.type = "session_closed";
431  send_message(connection_to_session.first, msg);
432  }
433  }
434 
435  for (const auto &token : tokens_to_remove)
436  {
437  dbsrv_->db()->erase<Auth::Token>(token->id());
438  }
439  t.commit();
440 }
441 
442 void WSServer::register_crud_handler(const std::string &resource_name,
444 {
445  using namespace Colorize;
446  DEBUG("Performing registration of CRUD handler for resource "
447  << green(resource_name));
448  crud_handlers_[resource_name + ".read"] = factory;
449  crud_handlers_[resource_name + ".update"] = factory;
450  crud_handlers_[resource_name + ".create"] = factory;
451  crud_handlers_[resource_name + ".delete"] = factory;
452 }
453 
455 {
456  return dbsrv_;
457 }
458 
459 bool WSServer::has_handler(const std::string &name) const
460 {
461  return handlers_.count(name) || individual_handlers_.count(name) ||
462  crud_handlers_.count(name) || asio_handlers_.count(name);
463 }
464 
466 {
467  try
468  {
469  db::MultiplexedTransaction t(dbsrv_->db()->begin());
470  // If something went wrong while processing the request, the audit object
471  // may need to be reload. We might as well reload it every time.
472  audit->reload();
473  // Update audit value.
474  audit->uuid(msg.uuid);
475  audit->method(msg.type);
476  audit->status_code(msg.status_code);
477  audit->status_string(msg.status_string);
478  // audit->response_content(msg.content.dump(4));
479  audit->finalize();
480  t.commit();
481  }
482  catch (const odb::exception &e)
483  {
484  WARN("Database Error in WServer::on_message. Failed to persist final audit: "
485  << e.what());
487  msg.status_string = e.what();
488  return;
489  }
490 }
491 
493  const std::string &name)
494 {
495  DEBUG("Scheduling ASIO-based-handler registration. (name: " << name << ')');
496  std::packaged_task<bool()> pt([=]() {
497  if (has_handler(name))
498  return false;
499  DEBUG("Performing registration of ASIO-based-handler. (name: " << name
500  << ')');
501  asio_handlers_[name] = handler;
502  return true;
503  });
504  std::future<bool> future = pt.get_future();
505 
506  srv_.get_io_service().post([&]() { pt(); });
507  return future.get();
508 }
509 
510 void WSServer::unregister_handler(const std::string &name)
511 {
512  DEBUG("Scheduling removal of ASIO-based-handler (name " << name << ')');
513  std::promise<void> p;
514 
515  srv_.get_io_service().post([&]() {
516  asio_handlers_.erase(name);
517  handlers_.erase(name);
518  individual_handlers_.erase(name);
519  crud_handlers_.erase(name);
520  p.set_value();
521  });
522 
523  return p.get_future().get();
524 }
525 
526 void WSServer::register_crud_handler_external(const std::string &resource_name,
528 {
529  std::promise<void> p;
530 
531  srv_.get_io_service().post([&]() {
532  register_crud_handler(resource_name, factory);
533  p.set_value();
534  });
535 
536  return p.get_future().get();
537 }
538 
540 {
542  if (ok)
543  {
544  INFO("WebSocket service has been unregistered.");
545  // Nobody relies on our Service anymore. We can remove work_
546  // and let the io_service run out of work.
547  work_ = nullptr;
548  }
549  else
550  {
551  srv_.get_io_service().post([this]() { attempt_unregister_ws_service(); });
552  }
553 }
json system_overview(const json &req)
Presents an overview of the system to the end user.
Definition: APISession.cpp:113
ClientMessage parse_request(const json &in)
Create a ClientMessage object from a json request.
Definition: WSServer.cpp:361
uint64_t gettid()
Return the Linux thread ID.
Definition: ThreadUtils.cpp:32
static CRUDResourceHandlerUPtr instanciate(RequestContext)
An authentication token used for authenticating a user against Leosac.
Definition: Token.hpp:42
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...
nlohmann::json json
CRUDResourceHandlerUPtr(*)(RequestContext) Factory
A service object provided by the Websocket module.
Definition: Service.hpp:45
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.
Definition: WSServer.cpp:459
This class is dedicated to converting exception thrown by various code into a ServerMessage that can ...
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: DoorCRUD.cpp:44
void register_crud_handler(const std::string &resource_name, CRUDResourceHandler::Factory factory)
An internal helper function to register a CRUD resource handler.
Definition: WSServer.cpp:442
static MethodHandlerUPtr create(RequestContext)
STL namespace.
Definition: log.hpp:37
std::shared_ptr< IWSAPICall > IWSAPICallPtr
Definition: AuditFwd.hpp:52
static CRUDResourceHandlerUPtr instanciate(RequestContext)
std::map< std::string, json(APISession::*)(const json &)> handlers_
This maps (string) command name to API method.
Definition: WSServer.hpp:237
boost::optional< ServerMessage > handle_request(APIPtr api_handle, const ClientMessage &msg, Audit::IAuditEntryPtr)
Handle a request.
Definition: WSServer.cpp:383
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
void commit()
Commit the transaction.
void on_close(websocketpp::connection_hdl hdl)
Definition: WSServer.cpp:150
void register_crud_handler_external(const std::string &resource_name, CRUDResourceHandler::Factory factory)
Register a CRUD handler from an external thread.
Definition: WSServer.cpp:526
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
Definition: AuditFwd.hpp:40
std::unique_ptr< CRUDResourceHandler > CRUDResourceHandlerUPtr
Definition: WebSockFwd.hpp:39
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.
Definition: WSServer.cpp:465
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: GroupCRUD.cpp:42
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: UserCRUD.cpp:41
Definition: log.hpp:35
static CRUDResourceHandlerUPtr instanciate(RequestContext)
json logout(const json &req)
Log an user out.
Definition: APISession.cpp:104
DBServicePtr dbsrv_
Database service object.
Definition: WSServer.hpp:251
static MethodHandlerUPtr create(RequestContext)
Definition: Restart.cpp:36
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
Definition: WebSockFwd.hpp:36
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.
Definition: WSServer.cpp:269
static MethodHandlerUPtr create(RequestContext)
Definition: LogGet.cpp:36
An exception that can be throw when the permission for a given operation is denied.
APIAuth & auth()
Retrieve the authentication helper.
Definition: WSServer.cpp:264
json get_leosac_version(const json &)
Retrieve the current version number of Leosac.
Definition: APISession.cpp:48
std::string green(const T &in)
Definition: Colorize.hpp:82
bool unregister_service(RegistrationHandle h)
Unregister a service using the RegistrationHandle that was returned from the register_service() call...
DBPtr db()
Retrieve database handle.
Definition: WSServer.cpp:337
std::shared_ptr< DBService > DBServicePtr
Definition: db_fwd.hpp:34
std::shared_ptr< User > UserPtr
Definition: AuthFwd.hpp:31
All modules that provides features to Leosac shall be in this namespace.
static CRUDResourceHandlerUPtr instanciate(RequestContext)
CoreUtilsPtr core_utils()
Retrieve the CoreUtils pointer.
Definition: WSServer.cpp:342
static MethodHandlerUPtr create(RequestContext)
Definition: CheckUpdate.cpp:37
Provides various database-related services to consumer.
Definition: DBService.hpp:34
WSServer(WebSockAPIModule &module, DBPtr database)
Definition: WSServer.cpp:78
The source packet was malformed.
std::map< std::string, MethodHandler::Factory > individual_handlers_
Definition: WSServer.hpp:239
#define ASSERT_LOG(cond, msg)
Definition: log.hpp:221
std::map< std::string, CRUDResourceHandler::Factory > crud_handlers_
Definition: WSServer.hpp:241
std::map< std::string, Service::WSHandler > asio_handlers_
Handlers registered through the WebSockAPI::Service object.
Definition: WSServer.hpp:246
void clear_user_sessions(Auth::UserPtr user, APIPtr exception)
Deauthenticate all the connections of user, except the exception APISession.
Definition: WSServer.cpp:410
static MethodHandlerUPtr create(RequestContext)
Definition: UpdateGet.cpp:37
void run(const std::string &interface, uint16_t port)
Definition: WSServer.cpp:223
WebSockAPIModule & module_
A reference to the module.
Definition: WSServer.hpp:258
static MethodHandlerUPtr create(RequestContext)
nlohmann::json json
Definition: WSServer.cpp:76
json authenticate_with_token(const json &req)
Attempt to authenticate with a (previously generated) authentication token.
Definition: APISession.cpp:82
std::shared_ptr< APISession > APIPtr
Definition: WebSockFwd.hpp:33
Definition: log.hpp:38
#define BUILD_STR(param)
Internal macro.
Definition: log.hpp:66
static MethodHandlerUPtr create(RequestContext)
Definition: ZoneSearch.cpp:34
A message sent by the server to a client.
Definition: Messages.hpp:38
std::shared_ptr< CoreUtils > CoreUtilsPtr
Definition: LeosacFwd.hpp:35
static MethodHandlerUPtr create(RequestContext)
Definition: GroupSearch.cpp:37
A message sent by a client to Leosac.
Definition: Messages.hpp:54
static MethodHandlerUPtr create(RequestContext)
static MethodHandlerUPtr create(RequestContext)
Definition: AckUpdate.cpp:37
void start_shutdown()
Start the process of shutting down the server.
Definition: WSServer.cpp:243
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: ZoneCRUD.cpp:39
json create_auth_token(const json &req)
Generate an authentication token using the user credential, and logs the user in on success...
Definition: APISession.cpp:56
static MethodHandlerUPtr create(RequestContext)
Definition: UserSearch.cpp:34
void on_message(websocketpp::connection_hdl hdl, Server::message_ptr msg)
A websocket message has been received.
Definition: WSServer.cpp:156
Holds valuable pointer to provide context to a request.
DBServicePtr dbsrv()
Retrieve database service pointer.
Definition: WSServer.cpp:454
static MethodHandlerUPtr create(RequestContext)
Definition: AuditGet.cpp:45
Indicate that the request&#39;s processing went well.
std::shared_ptr< odb::database > DBPtr
Definition: db_fwd.hpp:31
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...
Definition: WSServer.cpp:492
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...
Definition: WSServer.hpp:264
This class is responsible for providing an API to manage authentication for Websocket client...
Definition: APIAuth.hpp:41
void on_open(websocketpp::connection_hdl hdl)
Definition: WSServer.cpp:143
static MethodHandlerUPtr create(RequestContext)
Definition: DoorSearch.cpp:37
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.
Definition: WSServer.cpp:347
A module that provide a websocket interface to Leosac.
Definition: WebSockAPI.hpp:46
void unregister_handler(const std::string &name)
Remove an Asio based handler.
Definition: WSServer.cpp:510
std::function< boost::optional< json >(const RequestContext &)> WSHandler
Definition: Service.hpp:53
CoreUtilsPtr core_utils()
This module explicitly expose CoreUtils to other object in the module.
Definition: WebSockAPI.cpp:60