Leosac  0.7.0
OpenSourceAccessControl
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 }
static IUserEventPtr UserEvent(const DBPtr &database, Auth::UserPtr target_user, IAuditEntryPtr parent)
static json serialize(const Auth::User &in, const SecurityContext &sc)
An exception class for general API error.
This is the header file for a generated source file, GitSHA1.cpp.
static SecurityContext & instance()
virtual boost::optional< json > create_impl(const json &req) override
Definition: UserCRUD.cpp:47
virtual UserSecurityContext & security_context() const override
Helper function that returns the security context.
Audit::IAuditEntryPtr audit
The initial audit trail for the request.
Represent a user.
Definition: User.hpp:42
std::unique_ptr< CRUDResourceHandler > CRUDResourceHandlerUPtr
Definition: WebSockFwd.hpp:39
virtual boost::optional< json > update_impl(const json &req) override
Update information about a given user.
Definition: UserCRUD.cpp:107
unsigned long GroupId
Definition: AuthFwd.hpp:41
unsigned long UserId
Definition: AuthFwd.hpp:34
static CRUDResourceHandlerUPtr instanciate(RequestContext)
Definition: UserCRUD.cpp:41
bool is_self(Auth::UserId id) const
Return true if the owner of the security context is the user whose id is id.
std::shared_ptr< IUserEvent > IUserEventPtr
Definition: AuditFwd.hpp:46
odb::query< Tools::LogEntry > Query
Definition: LogEntry.cpp:36
std::shared_ptr< User > UserPtr
Definition: AuthFwd.hpp:31
All modules that provides features to Leosac shall be in this namespace.
static std::string serialize(const Auth::User &in, const SecurityContext &sc)
static void unserialize(Auth::User &out, const json &in, const SecurityContext &sc)
Base CRUD handler for use within the websocket module.
virtual std::vector< ActionActionParam > required_permission(Verb verb, const json &req) const override
Definition: UserCRUD.cpp:147
virtual boost::optional< json > read_impl(const json &req) override
Retrieve information about a given user, or about all users.
Definition: UserCRUD.cpp:77
#define BUILD_STR(param)
Internal macro.
Definition: log.hpp:66
A base class for Leosac specific exception.
virtual boost::optional< json > delete_impl(const json &req) override
Definition: UserCRUD.cpp:141
odb::result< Tools::LogEntry > Result
Definition: LogEntry.cpp:37
Holds valuable pointer to provide context to a request.
std::shared_ptr< odb::database > DBPtr
Definition: db_fwd.hpp:31