Leosac  0.8.0
Open Source Access Control
DoorCRUD.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 "api/DoorCRUD.hpp"
21 #include "Exceptions.hpp"
22 #include "api/APISession.hpp"
25 #include "core/auth/Door_odb.h"
26 #include "core/auth/User.hpp"
29 #include "tools/AssertCast.hpp"
30 #include "tools/db/DBService.hpp"
32 #include "tools/enforce.hpp"
33 
34 
35 using namespace Leosac;
36 using namespace Leosac::Module;
37 using namespace Leosac::Module::WebSockAPI;
38 
40  : CRUDResourceHandler(ctx)
41 {
42 }
43 
45 {
46  auto instance = CRUDResourceHandlerUPtr(new DoorCRUD(ctx));
47  return instance;
48 }
49 
50 boost::optional<json> DoorCRUD::create_impl(const json &req)
51 {
52  json rep;
53  DBPtr db = ctx_.dbsrv->db();
54  odb::transaction t(db->begin());
55 
56  Auth::DoorPtr new_door = std::make_shared<Auth::Door>();
57  DoorJSONSerializer::unserialize(*new_door, req.at("attributes"),
59  enforce_ap_not_already_referenced(new_door->access_point_id());
60  db->persist(new_door);
61 
62  auto audit = Audit::Factory::DoorEvent(db, new_door, ctx_.audit);
63  audit->event_mask(Audit::EventType::DOOR_CREATED);
65  *new_door, SystemSecurityContext::instance()));
66 
67  audit->access_point_id_after(new_door->access_point_id());
68  audit->finalize();
69 
70  rep["data"] = DoorJSONSerializer::serialize(*new_door, security_context());
71  t.commit();
72  return rep;
73 }
74 
75 boost::optional<json> DoorCRUD::read_impl(const json &req)
76 {
77  json rep;
78 
79  using Result = odb::result<Auth::Door>;
80  DBPtr db = ctx_.dbsrv->db();
81  odb::transaction t(db->begin());
82  auto did = req.at("door_id").get<Auth::DoorId>();
83 
84  if (did != 0)
85  {
86  auto door = ctx_.dbsrv->find_door_by_id(did, DBService::THROW_IF_NOT_FOUND);
87  rep["data"] = DoorJSONSerializer::serialize(*door, security_context());
88  }
89  else
90  {
91  Result result = db->query<Auth::Door>();
92  rep["data"] = json::array();
93  auto current_user = ctx_.session->current_user();
94 
95  // fixme: may be rather slow.
96  for (const auto &door : result)
97  {
98  SecurityContext::DoorActionParam dap{.door_id = door.id()};
99  if (ctx_.session->security_context().check_permission(
101  {
102  rep["data"].push_back(
104  }
105  }
106  }
107  t.commit();
108  return rep;
109 }
110 
111 boost::optional<json> DoorCRUD::update_impl(const json &req)
112 {
113  json rep;
114  DBPtr db = ctx_.dbsrv->db();
115  odb::transaction t(db->begin());
116  auto did = req.at("door_id").get<Auth::DoorId>();
117 
118  auto door = ctx_.dbsrv->find_door_by_id(did, DBService::THROW_IF_NOT_FOUND);
119  auto door_odb = assert_cast<Auth::DoorPtr>(door);
120  auto audit = Audit::Factory::DoorEvent(db, door, ctx_.audit);
121  audit->event_mask(Audit::EventType::DOOR_UPDATED);
124  audit->access_point_id_before(door->access_point_id());
125 
126  DoorJSONSerializer::unserialize(*door, req.at("attributes"), security_context());
127  enforce_ap_not_already_referenced(door->access_point_id());
128 
129  db->update(door_odb);
132  audit->access_point_id_after(door->access_point_id());
133 
134  audit->finalize();
135  rep["data"] = DoorJSONSerializer::serialize(*door, security_context());
136  t.commit();
137  return rep;
138 }
139 
140 boost::optional<json> DoorCRUD::delete_impl(const json &req)
141 {
142  auto did = req.at("door_id").get<Auth::DoorId>();
143  DBPtr db = ctx_.dbsrv->db();
144  odb::transaction t(db->begin());
145 
146  auto door = ctx_.dbsrv->find_door_by_id(did, DBService::THROW_IF_NOT_FOUND);
147  auto door_odb = assert_cast<Auth::DoorPtr>(door);
148  auto audit = Audit::Factory::DoorEvent(db, door, ctx_.audit);
149  audit->event_mask(Audit::EventType::DOOR_DELETED);
150 
151  audit->access_point_id_before(door->access_point_id());
154 
155  audit->finalize();
156  db->erase(door_odb);
157  t.commit();
158 
159  return json{};
160 }
161 
162 std::vector<CRUDResourceHandler::ActionActionParam>
164 {
165  std::vector<CRUDResourceHandler::ActionActionParam> ret;
167  try
168  {
169  dap.door_id = req.at("door_id").get<Auth::DoorId>();
170  }
171  catch (json::out_of_range &e)
172  {
173  dap.door_id = 0;
174  }
175  switch (verb)
176  {
177  case Verb::READ:
178  ret.push_back(std::make_pair(SecurityContext::Action::DOOR_READ, dap));
179  break;
180  case Verb::CREATE:
181  ret.push_back(std::make_pair(SecurityContext::Action::DOOR_CREATE, dap));
182  break;
183  case Verb::UPDATE:
184  ret.push_back(std::make_pair(SecurityContext::Action::DOOR_UPDATE, dap));
185  break;
186  case Verb::DELETE:
187  ret.push_back(std::make_pair(SecurityContext::Action::DOOR_DELETE, dap));
188  break;
189  }
190  return ret;
191 }
192 
194 {
195  if (apid == 0)
196  return;
197 
198  db::OptionalTransaction t(ctx_.dbsrv->db()->begin());
199  auto ret = ctx_.dbsrv->db()->query<Auth::Door>(
200  odb::query<Auth::Door>::access_point == apid);
201 
202  if (!ret.empty())
203  {
204  Auth::DoorPtr door = LEOSAC_ENFORCE(ret.begin().load(), "Failed to load");
206  "The AccessPoint with id {} is already referenced by door with id {}.",
207  apid, door->id()));
208  }
209 
210  t.commit();
211 }
Leosac::db::OptionalTransaction
An optional transaction is an object that behave like an odb::transaction if there is no currently ac...
Definition: OptionalTransaction.hpp:43
Leosac::SecurityContext::Action::DOOR_READ
@ DOOR_READ
AuditFactory.hpp
Leosac::db::OptionalTransaction::commit
void commit()
Commit the transaction, if there was no currently active transaction at the time of this object's cre...
Definition: OptionalTransaction.cpp:38
Leosac::SystemSecurityContext::instance
static SecurityContext & instance()
Definition: SecurityContext.cpp:64
DoorSerializer.hpp
Leosac::Module::WebSockAPI::DoorCRUD::DoorCRUD
DoorCRUD(RequestContext ctx)
Definition: DoorCRUD.cpp:39
Exceptions.hpp
Leosac::Audit::EventType::DOOR_UPDATED
@ DOOR_UPDATED
Leosac::Module::WebSockAPI::DoorCRUD::delete_impl
virtual boost::optional< json > delete_impl(const json &req) override
Definition: DoorCRUD.cpp:140
Leosac::DoorJSONSerializer::serialize
static json serialize(const Auth::IDoor &door, const SecurityContext &sc)
Definition: DoorSerializer.cpp:31
Leosac::Module::WebSockAPI::DoorCRUD::create_impl
virtual boost::optional< json > create_impl(const json &req) override
Definition: DoorCRUD.cpp:50
Leosac::Module::WebSockAPI::CRUDResourceHandlerUPtr
std::unique_ptr< CRUDResourceHandler > CRUDResourceHandlerUPtr
Definition: WebSockFwd.hpp:39
Leosac::Module::WebSockAPI::RequestContext::dbsrv
DBServicePtr dbsrv
Definition: RequestContext.hpp:39
Leosac::Module::WebSockAPI::CRUDResourceHandler
Base CRUD handler for use within the websocket module.
Definition: CRUDResourceHandler.hpp:84
User.hpp
Leosac::Audit::Factory::DoorEvent
static IDoorEventPtr DoorEvent(const DBPtr &database, Auth::IDoorPtr target_door, IAuditEntryPtr parent)
Definition: AuditFactory.cpp:124
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::DELETE
@ DELETE
Leosac::DBPtr
std::shared_ptr< odb::database > DBPtr
Definition: db_fwd.hpp:31
Leosac::DoorJSONSerializer::unserialize
static void unserialize(Auth::IDoor &out, const json &in, const SecurityContext &sc)
Definition: DoorSerializer.cpp:49
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::CREATE
@ CREATE
IDoorEvent.hpp
Leosac::Module
All modules that provides features to Leosac shall be in this namespace.
Leosac::SecurityContext::Action::DOOR_CREATE
@ DOOR_CREATE
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::READ
@ READ
Leosac::Module::WebSockAPI::DoorCRUD::instanciate
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: DoorCRUD.cpp:44
Leosac::SecurityContext::DoorActionParam
Definition: SecurityContext.hpp:203
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::UPDATE
@ UPDATE
enforce.hpp
Leosac
This is the header file for a generated source file, GitSHA1.cpp.
Definition: APIStatusCode.hpp:22
OptionalTransaction.hpp
Leosac::SecurityContext::Action::DOOR_UPDATE
@ DOOR_UPDATE
Leosac::Module::WebSockAPI::DoorCRUD::required_permission
virtual std::vector< ActionActionParam > required_permission(Verb verb, const json &req) const override
Definition: DoorCRUD.cpp:163
Leosac::Auth::DoorPtr
std::shared_ptr< Door > DoorPtr
Definition: AuthFwd.hpp:112
Leosac::Auth::DoorId
unsigned long DoorId
Definition: AuthFwd.hpp:107
LEOSACException
A base class for Leosac specific exception.
Definition: leosacexception.hpp:40
Leosac::DoorJSONStringSerializer::serialize
static std::string serialize(const Auth::IDoor &in, const SecurityContext &sc)
Definition: DoorSerializer.cpp:79
Leosac::SecurityContext::DoorActionParam::door_id
Auth::DoorId door_id
Definition: SecurityContext.hpp:205
Leosac::Auth::Door
Represent a door.
Definition: Door.hpp:35
Leosac::Module::WebSockAPI::CRUDResourceHandler::ctx_
RequestContext ctx_
Definition: CRUDResourceHandler.hpp:95
DoorCRUD.hpp
ModelException.hpp
Leosac::Module::WebSockAPI::DoorCRUD::read_impl
virtual boost::optional< json > read_impl(const json &req) override
Definition: DoorCRUD.cpp:75
Leosac::SecurityContext::Action::DOOR_DELETE
@ DOOR_DELETE
DBService.hpp
Leosac::Audit::EventType::DOOR_DELETED
@ DOOR_DELETED
APISession.hpp
Leosac::Module::WebSockAPI::RequestContext::audit
Audit::IAuditEntryPtr audit
The initial audit trail for the request.
Definition: RequestContext.hpp:55
Leosac::Colorize::detail::format
std::string format(const std::string &escape_code, const T &in)
Return a string containing the escape code, a string representation of T and the clear escape string.
Definition: Colorize.hpp:49
Leosac::Audit::EventType::DOOR_CREATED
@ DOOR_CREATED
Leosac::DBService::THROW_IF_NOT_FOUND
@ THROW_IF_NOT_FOUND
Definition: DBService.hpp:40
Leosac::Module::WebSockAPI::json
nlohmann::json json
Definition: AccessOverview.hpp:30
Leosac::Module::WebSockAPI::RequestContext
Holds valuable pointer to provide context to a request.
Definition: RequestContext.hpp:36
Leosac::Module::WebSockAPI::DoorCRUD::enforce_ap_not_already_referenced
void enforce_ap_not_already_referenced(Auth::AccessPointId apid)
Make sure that the AccessPoint with id apid is not already referenced by a door.
Definition: DoorCRUD.cpp:193
Leosac::Module::WebSockAPI
Definition: ActionActionParam.hpp:28
LEOSAC_ENFORCE
#define LEOSAC_ENFORCE(cond,...)
Similar to enforce, except that it will throw a LEOSACException.
Definition: enforce.hpp:47
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb
Verb
Definition: CRUDResourceHandler.hpp:43
Result
odb::result< Tools::LogEntry > Result
Definition: LogEntry.cpp:37
Leosac::Module::WebSockAPI::DoorCRUD::update_impl
virtual boost::optional< json > update_impl(const json &req) override
Definition: DoorCRUD.cpp:111
Leosac::Module::WebSockAPI::RequestContext::session
APIPtr session
Definition: RequestContext.hpp:38
AssertCast.hpp
Leosac::Auth::AccessPointId
unsigned long AccessPointId
Definition: AuthFwd.hpp:128
Leosac::Module::WebSockAPI::CRUDResourceHandler::security_context
virtual UserSecurityContext & security_context() const override
Helper function that returns the security context.
Definition: CRUDResourceHandler.cpp:96