Leosac  0.8.0
Open Source Access Control
UserCRUD.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/UserCRUD.hpp"
21 #include "Exceptions.hpp"
22 #include "api/APISession.hpp"
24 #include "core/audit/UserEvent.hpp"
25 #include "core/auth/User.hpp"
26 #include "core/auth/User_odb.h"
29 #include "tools/db/DBService.hpp"
30 #include "tools/log.hpp"
31 
32 using namespace Leosac;
33 using namespace Leosac::Module;
34 using namespace Leosac::Module::WebSockAPI;
35 
37  : CRUDResourceHandler(ctx)
38 {
39 }
40 
42 {
43  auto instance = CRUDResourceHandlerUPtr(new UserCRUD(ctx));
44  return instance;
45 }
46 
47 boost::optional<json> UserCRUD::create_impl(const json &req)
48 {
49  json rep;
50  using Query = odb::query<Auth::User>;
51  DBPtr db = ctx_.dbsrv->db();
52  odb::transaction t(db->begin());
53  json attributes = req.at("attributes");
54 
55  Auth::UserPtr new_user = std::make_shared<Auth::User>();
56  new_user->username(attributes.at("username"));
57  if (db->query_one<Auth::User>(Query::username == new_user->username()))
58  throw ModelException("data/attributes/username",
59  BUILD_STR("The username " << new_user->username()
60  << " is already in use."));
61 
62  UserJSONSerializer::unserialize(*new_user, attributes, security_context());
63  db->persist(new_user);
64 
66  audit->event_mask(Audit::EventType::USER_CREATED);
68  *new_user, SystemSecurityContext::instance()));
69  audit->finalize();
70  t.commit();
71 
72  rep["data"] = UserJSONSerializer::serialize(*new_user, security_context());
73 
74  return rep;
75 }
76 
77 boost::optional<json> UserCRUD::read_impl(const json &req)
78 {
79  json rep;
80 
81  using Result = odb::result<Auth::User>;
82  DBPtr db = ctx_.dbsrv->db();
83  odb::transaction t(db->begin());
84  auto uid = req.at("user_id").get<Auth::UserId>();
85 
86  if (uid != 0)
87  {
88  Auth::UserPtr user =
89  ctx_.dbsrv->find_user_by_id(uid, DBService::THROW_IF_NOT_FOUND);
90  rep["data"] = UserJSONSerializer::serialize(*user, security_context());
91  }
92  else
93  {
94  // All users.
95  Result result = db->query<Auth::User>();
96  rep["data"] = json::array();
97  for (const auto &user : result)
98  {
99  rep["data"].push_back(
101  }
102  }
103  t.commit();
104  return rep;
105 }
106 
107 boost::optional<json> UserCRUD::update_impl(const json &req)
108 {
109  json rep;
110 
111  DBPtr db = ctx_.dbsrv->db();
112  odb::transaction t(db->begin());
113  auto uid = req.at("user_id").get<Auth::UserId>();
114  auto attributes = req.at("attributes");
115 
116  Auth::UserPtr user =
117  ctx_.dbsrv->find_user_by_id(uid, DBService::THROW_IF_NOT_FOUND);
119  audit->event_mask(Audit::EventType::USER_EDITED);
122 
123  bool enabled_status = user->validity().is_enabled();
125 
126  // prevent user from disabling themselves
127  if (enabled_status && !user->validity().is_enabled() &&
128  security_context().is_self(user->id()))
129  {
130  throw LEOSACException("You cannot disable your own user account.");
131  }
132 
133  db->update(user);
136  audit->finalize();
137  t.commit();
138  return rep;
139 }
140 
141 boost::optional<json> UserCRUD::delete_impl(const json &)
142 {
143  throw LEOSACException("Not implemented.");
144 }
145 
146 std::vector<CRUDResourceHandler::ActionActionParam>
148 {
149  std::vector<CRUDResourceHandler::ActionActionParam> ret;
150 
152  try
153  {
154  uap.user_id = req.at("user_id").get<Auth::GroupId>();
155  }
156  catch (const json::out_of_range &e)
157  {
158  uap.user_id = 0;
159  }
160 
161  switch (verb)
162  {
163  case Verb::READ:
164  ret.emplace_back(SecurityContext::Action::USER_READ, uap);
165  break;
166  case Verb::CREATE:
167  ret.emplace_back(SecurityContext::Action::USER_CREATE, uap);
168  break;
169  case Verb::UPDATE:
170  ret.emplace_back(SecurityContext::Action::USER_UPDATE, uap);
171  break;
172  case Verb::DELETE:
173  ret.emplace_back(SecurityContext::Action::USER_DELETE, uap);
174  break;
175  }
176  return ret;
177 }
Leosac::Audit::EventType::USER_CREATED
@ USER_CREATED
AuditFactory.hpp
Leosac::SystemSecurityContext::instance
static SecurityContext & instance()
Definition: SecurityContext.cpp:64
Exceptions.hpp
BUILD_STR
#define BUILD_STR(param)
Internal macro.
Definition: log.hpp:63
Leosac::UserJSONSerializer::serialize
static json serialize(const Auth::User &in, const SecurityContext &sc)
Definition: UserSerializer.cpp:33
Leosac::Module::WebSockAPI::UserCRUD::instanciate
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: UserCRUD.cpp:41
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
Leosac::Auth::UserPtr
std::shared_ptr< User > UserPtr
Definition: AuthFwd.hpp:31
Leosac::Module::WebSockAPI::UserCRUD::update_impl
virtual boost::optional< json > update_impl(const json &req) override
Update information about a given user.
Definition: UserCRUD.cpp:107
User.hpp
Leosac::SecurityContext::UserActionParam
Definition: SecurityContext.hpp:172
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::DELETE
@ DELETE
Leosac::DBPtr
std::shared_ptr< odb::database > DBPtr
Definition: db_fwd.hpp:31
Leosac::SecurityContext::Action::USER_READ
@ USER_READ
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::CREATE
@ CREATE
Leosac::Module
All modules that provides features to Leosac shall be in this namespace.
Query
odb::query< Tools::LogEntry > Query
Definition: LogEntry.cpp:36
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::READ
@ READ
Leosac::SecurityContext::Action::USER_CREATE
@ USER_CREATE
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb::UPDATE
@ UPDATE
Leosac
This is the header file for a generated source file, GitSHA1.cpp.
Definition: APIStatusCode.hpp:22
Leosac::Auth::User
Represent a user.
Definition: User.hpp:42
Leosac::SecurityContext::Action::USER_DELETE
@ USER_DELETE
UserSerializer.hpp
Leosac::Audit::IUserEventPtr
std::shared_ptr< IUserEvent > IUserEventPtr
Definition: AuditFwd.hpp:46
LEOSACException
A base class for Leosac specific exception.
Definition: leosacexception.hpp:40
Leosac::Module::WebSockAPI::UserCRUD::delete_impl
virtual boost::optional< json > delete_impl(const json &req) override
Definition: UserCRUD.cpp:141
Leosac::Module::WebSockAPI::CRUDResourceHandler::ctx_
RequestContext ctx_
Definition: CRUDResourceHandler.hpp:95
Leosac::Module::WebSockAPI::UserCRUD::UserCRUD
UserCRUD(RequestContext ctx)
Definition: UserCRUD.cpp:36
ModelException.hpp
Leosac::Module::WebSockAPI::UserCRUD::required_permission
virtual std::vector< ActionActionParam > required_permission(Verb verb, const json &req) const override
Definition: UserCRUD.cpp:147
UserEvent.hpp
Leosac::UserJSONSerializer::unserialize
static void unserialize(Auth::User &out, const json &in, const SecurityContext &sc)
Definition: UserSerializer.cpp:105
ModelException
An exception class for general API error.
Definition: ModelException.hpp:33
Leosac::Audit::Factory::UserEvent
static IUserEventPtr UserEvent(const DBPtr &database, Auth::UserPtr target_user, IAuditEntryPtr parent)
Definition: AuditFactory.cpp:43
DBService.hpp
Leosac::Module::WebSockAPI::UserCRUD::create_impl
virtual boost::optional< json > create_impl(const json &req) override
Definition: UserCRUD.cpp:47
APISession.hpp
Leosac::Audit::EventType::USER_EDITED
@ USER_EDITED
Leosac::Auth::GroupId
unsigned long GroupId
Definition: AuthFwd.hpp:41
UserCRUD.hpp
Leosac::Module::WebSockAPI::RequestContext::audit
Audit::IAuditEntryPtr audit
The initial audit trail for the request.
Definition: RequestContext.hpp:55
log.hpp
Leosac::Module::WebSockAPI::UserCRUD::read_impl
virtual boost::optional< json > read_impl(const json &req) override
Retrieve information about a given user, or about all users.
Definition: UserCRUD.cpp:77
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::Auth::UserId
unsigned long UserId
Definition: AuthFwd.hpp:34
Leosac::Module::WebSockAPI::RequestContext
Holds valuable pointer to provide context to a request.
Definition: RequestContext.hpp:36
Leosac::Module::WebSockAPI
Definition: ActionActionParam.hpp:28
Leosac::SecurityContext::UserActionParam::user_id
Auth::UserId user_id
Definition: SecurityContext.hpp:174
Leosac::Module::WebSockAPI::ICRUDResourceHandler::Verb
Verb
Definition: CRUDResourceHandler.hpp:43
Leosac::SecurityContext::Action::USER_UPDATE
@ USER_UPDATE
Result
odb::result< Tools::LogEntry > Result
Definition: LogEntry.cpp:37
Leosac::UserJSONStringSerializer::serialize
static std::string serialize(const Auth::User &in, const SecurityContext &sc)
Definition: UserSerializer.cpp:133
Leosac::Module::WebSockAPI::CRUDResourceHandler::security_context
virtual UserSecurityContext & security_context() const override
Helper function that returns the security context.
Definition: CRUDResourceHandler.cpp:96