Leosac  0.7.0
OpenSourceAccessControl
DoormanModule.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 "DoormanModule.hpp"
21 #include "DoormanInstance.hpp"
22 #include "core/Scheduler.hpp"
23 #include "core/auth/Auth.hpp"
24 #include "core/kernel.hpp"
25 #include "tools/log.hpp"
26 
27 using namespace Leosac::Module::Doorman;
28 using namespace Leosac::Auth;
29 
30 DoormanModule::DoormanModule(zmqpp::context &ctx, zmqpp::socket *pipe,
31  const boost::property_tree::ptree &cfg,
32  CoreUtilsPtr utils)
33  : BaseModule(ctx, pipe, cfg, utils)
34 {
35  try
36  {
38  }
39  catch (boost::property_tree::ptree_error &e)
40  {
41  std::throw_with_nested(
42  ConfigException("main", "Doorman module configuration is invalid"));
43  }
44 
45  for (auto &&doorman : doormen_)
46  {
47  reactor_.add(doorman->bus_sub(),
48  std::bind(&DoormanInstance::handle_bus_msg, doorman));
49  }
50 }
51 
53 {
54  boost::property_tree::ptree module_config = config_.get_child("module_config");
55 
56  auto doors_cfg = module_config.get_child_optional("doors");
57  if (doors_cfg)
58  process_doors_config(*doors_cfg);
59 
60  for (const auto &node : module_config.get_child("instances"))
61  {
62  // one doorman instance
63  boost::property_tree::ptree cfg_doorman = node.second;
64 
65  std::vector<std::string> auth_ctx_names;
66  std::vector<DoormanAction> actions;
67  std::string doorman_name = cfg_doorman.get_child("name").data();
68 
69  for (const auto &auth_contexts_node : cfg_doorman.get_child("auth_contexts"))
70  {
71  // each auth context we listen to
72  auth_ctx_names.push_back(
73  auth_contexts_node.second.get<std::string>("name"));
74  }
75 
76  for (const auto &action_node : cfg_doorman.get_child("actions"))
77  {
78  // every action we take
79  boost::property_tree::ptree cfg_action = action_node.second;
80  DoormanAction a;
81  std::string on_status;
82 
83  on_status = cfg_action.get<std::string>("on");
84  a.on_ = (on_status == "GRANTED" ? AccessStatus::GRANTED
85  : AccessStatus::DENIED);
86  a.target_ = cfg_action.get<std::string>("target");
88 
89  for (auto &cmd_node : cfg_action.get_child("cmd"))
90  {
91  // each frame in command
92  // fixme ORDER
93  // fixme ONLY ONE FRAME
94  a.cmd_.push_back(cmd_node.second.data());
95  }
96  actions.push_back(a);
97  }
98 
99  INFO("Creating Doorman instance " << doorman_name);
100  doormen_.push_back(std::make_shared<DoormanInstance>(
101  *this, ctx_, doorman_name, auth_ctx_names, actions));
102  }
103 }
104 
106 {
107  while (is_running_)
108  {
109  update();
110  reactor_.poll(2000);
111  }
112 }
113 
115  const boost::property_tree::ptree &doors_cfg)
116 {
117  DEBUG("Processing doors config");
118  for (const auto &door_cfg : doors_cfg)
119  {
120  std::string name = door_cfg.second.get<std::string>("name");
121  std::string gpio = door_cfg.second.get<std::string>("gpio");
122  const auto &open_schedule =
123  door_cfg.second.get_child_optional("on.schedules");
124  const auto &close_schedule =
125  door_cfg.second.get_child_optional("off.schedules");
126 
127  AuthTargetPtr door(new AuthTarget(name));
128  door->gpio(
129  std::unique_ptr<Hardware::FGPIO>(new Hardware::FGPIO(ctx_, gpio)));
130 
131  if (open_schedule)
132  {
133  Tools::XmlScheduleLoader xml_sched;
134  xml_sched.load(*open_schedule);
135  for (const auto &map_entry : xml_sched.schedules())
136  {
137  door->add_always_open_sched(map_entry.second);
138  }
139  }
140  if (close_schedule)
141  {
142  Tools::XmlScheduleLoader xml_sched;
143  xml_sched.load(*close_schedule);
144  for (const auto &map_entry : xml_sched.schedules())
145  {
146  door->add_always_close_sched(map_entry.second);
147  }
148  }
149  doors_.push_back(door);
150  }
151 }
152 
154 {
155  auto now = std::chrono::system_clock::now();
156 
157  for (auto &&door : doors_)
158  {
159  if (door->is_always_open(now) && door->is_always_closed(now))
160  {
161  WARN("Oops, door "
162  << door->name()
163  << " is both always open and always close at the same time.");
164  continue;
165  }
166  if (door->is_always_open(now) && !door->gpio()->isOn())
167  {
168  door->gpio()->turnOn();
169  }
170  if (door->is_always_closed(now) && !door->gpio()->isOff())
171  {
172  door->gpio()->turnOff();
173  }
174  }
175 }
176 
177 std::vector<AuthTargetPtr> const &DoormanModule::doors() const
178 {
179  return doors_;
180 }
std::shared_ptr< AuthTarget > AuthTargetPtr
Definition: AuthFwd.hpp:93
std::vector< std::shared_ptr< DoormanInstance > > doormen_
Authenticator instances.
Represent an object that we are authorizing against (a door).
Definition: AuthTarget.hpp:37
A Facade to a GPIO object.
Definition: FGPIO.hpp:45
DoormanModule(zmqpp::context &ctx, zmqpp::socket *pipe, const boost::property_tree::ptree &cfg, CoreUtilsPtr utils)
Definition: log.hpp:37
Helper struct to wrap an "action".
void process_config()
Processing the configuration tree, spawning AuthFileInstance object as described in the configuration...
virtual void run() override
This is the main loop of the module.
Definition: log.hpp:35
bool is_running_
Boolean indicating whether the main loop should run or not.
Definition: BaseModule.hpp:203
Holds classes relevant to the Authentication and Authorization subsystem.
Definition: AccessPoint.hpp:27
void process_doors_config(const boost::property_tree::ptree &t)
void config_check(const std::string &obj_name, ConfigChecker::ObjectType type)
An helper that checks configuration the existence of some objects.
Definition: BaseModule.cpp:143
const std::vector< Auth::AuthTargetPtr > & doors() const
Base class for module implementation.
Definition: BaseModule.hpp:110
zmqpp::context & ctx_
A reference to the ZeroMQ context in case you need it to create additional socket.
Definition: BaseModule.hpp:183
void handle_bus_msg()
Activity we care about happened on the bus.
const std::map< std::string, ISchedulePtr > & schedules() const
Access the map of stored schedules.
zmqpp::reactor reactor_
The reactor object we poll() on in the main loop.
Definition: BaseModule.hpp:214
Leosac::Auth::AccessStatus on_
When should this action be done? on GRANTED or DENIED ?
Definition: log.hpp:38
std::shared_ptr< CoreUtils > CoreUtilsPtr
Definition: LeosacFwd.hpp:35
bool load(const boost::property_tree::ptree &t)
Load all schedules from a tree and stores them in the map.
boost::property_tree::ptree config_
The configuration tree passed to the start_module function.
Definition: BaseModule.hpp:193
std::vector< std::string > cmd_
The command to be send.
std::vector< Auth::AuthTargetPtr > doors_
Doors, to manage the always-on or always off stuff.
std::string target_
Target component.
Load a list of schedules from a boost::property_tree.
Module that allows user to configure action to be taken to react to messages from other modules...