Leosac  0.8.0
Open Source Access Control
DoormanInstance.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 "DoormanInstance.hpp"
21 #include "DoormanModule.hpp"
22 #include "core/auth/Auth.hpp"
23 #include "tools/log.hpp"
24 
25 using namespace Leosac::Module::Doorman;
26 
27 DoormanInstance::DoormanInstance(DoormanModule &module, zmqpp::context &ctx,
28  std::string const &name,
29  const std::vector<std::string> &auth_contexts,
30  const std::vector<DoormanAction> &actions)
31  : name_(name)
32  , actions_(actions)
33  , bus_sub_(ctx, zmqpp::socket_type::sub)
34 {
35  bus_sub_.connect("inproc://zmq-bus-pub");
36  for (auto &endpoint : auth_contexts)
37  {
38  bus_sub_.subscribe("S_" + endpoint);
39  }
40 
41  for (auto &action : actions_)
42  {
43  if (targets_.count(action.target_))
44  continue; // already have a socket to this target.
45 
46  // create socket (and connect them) to target
47  zmqpp::socket target_socket(ctx, zmqpp::socket_type::req);
48  target_socket.connect("inproc://" + action.target_);
49  targets_.insert(std::make_pair(action.target_, std::move(target_socket)));
50  }
51 
52  for (auto &door : module.doors())
53  {
54  doors_.push_back(std::make_shared<DoormanDoor>(door, ctx));
55  }
56 }
57 
58 zmqpp::socket &DoormanInstance::bus_sub()
59 {
60  return bus_sub_;
61 }
62 
64 {
65  zmqpp::message bus_msg;
66  std::string auth_name; // name of the auth context that sent the message.
67  Leosac::Auth::AccessStatus access_status;
68 
69  bus_sub_.receive(bus_msg);
70  assert(bus_msg.parts() >= 2);
71  bus_msg >> auth_name >> access_status;
72  DEBUG("DOORMAN HERE");
73 
74  for (auto &action : actions_)
75  {
76  if (ignore_action(action, access_status))
77  continue;
78  DEBUG("ACTION (target = " << action.target_ << ")");
79 
80  zmqpp::message msg;
81  for (auto &frame : action.cmd_)
82  {
83  // we try to convert argument to int. if it works we send as int64_t,
84  // otherwise as string
85  bool err = false;
86  int v = 0;
87  try
88  {
89  v = std::stoi(frame);
90  }
91  catch (...)
92  {
93  err = true;
94  }
95  if (err)
96  msg << frame;
97  else
98  msg << static_cast<int64_t>(v);
99  DEBUG("would do : " << frame << " to target: " << action.target_);
100  }
101  command_send_recv(action.target_, std::move(msg));
102  }
103 }
104 
105 void DoormanInstance::command_send_recv(std::string const &target_name,
106  zmqpp::message msg)
107 {
108  zmqpp::socket &target_socket = targets_.at(target_name);
109  zmqpp::message response;
110 
111  target_socket.send(msg);
112  target_socket.receive(response);
113 
114  std::string req_status;
115  response >> req_status;
116 
117  if (req_status != "OK")
118  {
119  WARN("Command failed :(");
120  }
121 }
122 
124 DoormanInstance::find_target(const std::string &name) const
125 {
126  for (const auto &d : doors())
127  {
128  if (d->door()->gpio()->name() == name)
129  return d->door();
130  }
131  return nullptr;
132 }
133 
135  Leosac::Auth::AccessStatus status) const
136 {
137  if (action.on_ != status)
138  return true;
139 
140  auto target = find_target(action.target_);
141  if (target && (target->is_always_closed(std::chrono::system_clock::now()) ||
142  target->is_always_open(std::chrono::system_clock::now())))
143  {
144  INFO("Door " << target->name() << " is in immutable state (always open, "
145  "or always closed) so we ignore this "
146  "action against it");
147  return true;
148  }
149  return false;
150 }
151 
152 const std::vector<std::shared_ptr<DoormanDoor>> &DoormanInstance::doors() const
153 {
154  return doors_;
155 }
Leosac::Module::Doorman::DoormanInstance::actions_
std::vector< DoormanAction > actions_
Definition: DoormanInstance.hpp:119
Leosac::Module::Doorman::DoormanAction::on_
Leosac::Auth::AccessStatus on_
When should this action be done? on GRANTED or DENIED ?
Definition: DoormanInstance.hpp:50
WARN
@ WARN
Definition: log.hpp:33
zmqpp
Definition: CoreUtils.hpp:27
DEBUG
@ DEBUG
Definition: log.hpp:35
Auth.hpp
Leosac::Module::Doorman::DoormanAction::target_
std::string target_
Target component.
Definition: DoormanInstance.hpp:45
DoormanModule.hpp
INFO
@ INFO
Definition: log.hpp:34
DoormanInstance.hpp
Leosac::Module::Doorman::DoormanInstance::bus_sub_
zmqpp::socket bus_sub_
Definition: DoormanInstance.hpp:121
Leosac::Module::Doorman::DoormanAction
Helper struct to wrap an "action".
Definition: DoormanInstance.hpp:40
Leosac::Module::Doorman::DoormanInstance::doors_
std::vector< std::shared_ptr< DoormanDoor > > doors_
Definition: DoormanInstance.hpp:107
Leosac::Auth::AuthTargetPtr
std::shared_ptr< AuthTarget > AuthTargetPtr
Definition: AuthFwd.hpp:93
Leosac::Module::Doorman::DoormanInstance::doors
const std::vector< std::shared_ptr< DoormanDoor > > & doors() const
Definition: DoormanInstance.cpp:152
Leosac::Module::Doorman::DoormanInstance::ignore_action
bool ignore_action(const DoormanAction &action, Auth::AccessStatus status) const
Should we ignore this action.
Definition: DoormanInstance.cpp:134
Leosac::Auth::AccessStatus
AccessStatus
Definition: Auth.hpp:54
Leosac::Module::Doorman::DoormanInstance::DoormanInstance
DoormanInstance(DoormanModule &module, zmqpp::context &ctx, const std::string &name, const std::vector< std::string > &auth_contexts, const std::vector< DoormanAction > &actions)
Create a new doorman.
Definition: DoormanInstance.cpp:27
Leosac::Module::Doorman::DoormanInstance::find_target
Auth::AuthTargetPtr find_target(const std::string &name) const
Definition: DoormanInstance.cpp:124
Leosac::Module::Doorman::DoormanInstance::targets_
std::map< std::string, zmqpp::socket > targets_
Socket (REP) connected to each target this doorman may have.
Definition: DoormanInstance.hpp:126
Leosac::Module::Doorman::DoormanInstance::bus_sub
zmqpp::socket & bus_sub()
Definition: DoormanInstance.cpp:58
log.hpp
Leosac::Module::Doorman
Module that allows user to configure action to be taken to react to messages from other modules.
Definition: DoormanDoor.hpp:31
Leosac::Module::Doorman::DoormanInstance::command_send_recv
void command_send_recv(const std::string &target_name, zmqpp::message msg)
Send a command to a target and wait for response.
Definition: DoormanInstance.cpp:105
Leosac::Module::Doorman::DoormanInstance::handle_bus_msg
void handle_bus_msg()
Activity we care about happened on the bus.
Definition: DoormanInstance.cpp:63
Leosac::Module::Doorman::DoormanModule::doors
const std::vector< Auth::AuthTargetPtr > & doors() const
Definition: DoormanModule.cpp:189
Leosac::Module::Doorman::DoormanModule
Main class for the module, it create handlers and run them to, well, handle events and send command.
Definition: DoormanModule.hpp:52