Cutelyst  2.13.0
roleacl.cpp
1 /*
2  * Copyright (C) 2014-2017 Daniel Nicoletti <dantti12@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 #include "roleacl_p.h"
19 
20 #include "common.h"
21 
22 #include <Cutelyst/Plugins/Authentication/authentication.h>
23 #include <Cutelyst/Controller>
24 #include <Cutelyst/Dispatcher>
25 
26 using namespace Cutelyst;
27 
126 RoleACL::RoleACL(QObject *parent) : Component(new RoleACLPrivate, parent)
127 {
128 }
129 
130 Component::Modifiers RoleACL::modifiers() const
131 {
132  return AroundExecute;
133 }
134 
135 bool RoleACL::init(Cutelyst::Application *application, const QVariantHash &args)
136 {
137  Q_D(RoleACL);
138  Q_UNUSED(application)
139 
140  const auto attributes = args.value(QLatin1String("attributes")).value<ParamsMultiMap>();
141  d->actionReverse = args.value(QLatin1String("reverse")).toString();
142 
143  if (!attributes.contains(QLatin1String("RequiresRole")) && !attributes.contains(QLatin1String("AllowedRole"))) {
144  qFatal("RoleACL: Action %s requires at least one RequiresRole or AllowedRole attribute", qPrintable(d->actionReverse));
145  } else {
146  const QStringList required = attributes.values(QLatin1String("RequiresRole"));
147  for (const QString &role : required) {
148  d->requiresRole.append(role);
149  }
150 
151  const QStringList allowed = attributes.values(QLatin1String("AllowedRole"));
152  for (const QString &role : allowed) {
153  d->allowedRole.append(role);
154  }
155  }
156 
157  auto it = attributes.constFind(QLatin1String("ACLDetachTo"));
158  if (it == attributes.constEnd() || it.value().isEmpty()) {
159  qFatal("RoleACL: Action %s requires the ACLDetachTo(<action>) attribute", qPrintable(d->actionReverse));
160  }
161  d->aclDetachTo = it.value();
162 
163  return true;
164 }
165 
166 bool RoleACL::aroundExecute(Context *c, QStack<Cutelyst::Component *> stack)
167 {
168  Q_D(const RoleACL);
169 
170  if (canVisit(c)) {
171  return Component::aroundExecute(c, stack);
172  }
173 
174  c->detach(d->detachTo);
175 
176  return false;
177 }
178 
180 {
181  Q_D(const RoleACL);
182 
183  const QStringList user_has = Authentication::user(c).value(QStringLiteral("roles")).toStringList();
184 
185  const QStringList required = d->requiresRole;
186  const QStringList allowed = d->allowedRole;
187 
188  if (!required.isEmpty() && !allowed.isEmpty()) {
189  for (const QString &role : required) {
190  if (!user_has.contains(role)) {
191  return false;
192  }
193  }
194 
195  for (const QString &role : allowed) {
196  if (user_has.contains(role)) {
197  return true;
198  }
199  }
200  } else if (!required.isEmpty()) {
201  for (const QString &role : required) {
202  if (!user_has.contains(role)) {
203  return false;
204  }
205  }
206  return true;
207  } else if (!allowed.isEmpty()) {
208  for (const QString &role : allowed) {
209  if (user_has.contains(role)) {
210  return true;
211  }
212  }
213  }
214 
215  return false;
216 }
217 
218 bool RoleACL::dispatcherReady(const Dispatcher *dispatcher, Cutelyst::Controller *controller)
219 {
220  Q_D(RoleACL);
221  Q_UNUSED(dispatcher)
222 
223  d->detachTo = controller->actionFor(d->aclDetachTo);
224  if (!d->detachTo) {
225  d->detachTo = dispatcher->getActionByPath(d->aclDetachTo);
226  if (!d->detachTo) {
227  qFatal("RoleACL: Action '%s' requires a valid action set on the ACLDetachTo(%s) attribute",
228  qPrintable(d->actionReverse), qPrintable(d->aclDetachTo));
229  }
230  }
231 
232  return true;
233 }
234 
235 #include "moc_roleacl.cpp"
Cutelyst::Controller
Cutelyst Controller base class
Definition: controller.h:102
Cutelyst::ParamsMultiMap
QMap< QString, QString > ParamsMultiMap
Definition: paramsmultimap.h:36
Cutelyst::RoleACL::canVisit
bool canVisit(Context *c) const
Definition: roleacl.cpp:179
Cutelyst::Dispatcher::getActionByPath
Action * getActionByPath(const QString &path) const
Definition: dispatcher.cpp:231
Cutelyst::Context::detach
void detach(Action *action=nullptr)
Definition: context.cpp:346
Cutelyst::Application
The Cutelyst Application.
Definition: application.h:55
Cutelyst::Dispatcher
The Cutelyst Dispatcher.
Definition: dispatcher.h:40
Cutelyst::Context
The Cutelyst Context.
Definition: context.h:50
Cutelyst::RoleACL::aroundExecute
virtual bool aroundExecute(Context *c, QStack< Component * > stack) override
Definition: roleacl.cpp:166
Cutelyst::Component
The Cutelyst Component base class.
Definition: component.h:38
Cutelyst::Controller::actionFor
Action * actionFor(const QString &name) const
Definition: controller.cpp:50
Cutelyst::RoleACL::modifiers
virtual Modifiers modifiers() const override
Definition: roleacl.cpp:130
Cutelyst::RoleACL::dispatcherReady
virtual bool dispatcherReady(const Dispatcher *dispatcher, Controller *controller) override
Definition: roleacl.cpp:218
Cutelyst::Component::aroundExecute
virtual bool aroundExecute(Context *c, QStack< Component * > stack)
Definition: component.cpp:114
Cutelyst
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:7
Cutelyst::RoleACL::init
virtual bool init(Application *application, const QVariantHash &args) override
Definition: roleacl.cpp:135
Cutelyst::Authentication::user
static AuthenticationUser user(Context *c)
Definition: authentication.cpp:113
Cutelyst::RoleACL
User role-based authorization action class.
Definition: roleacl.h:31
Cutelyst::RoleACL::RoleACL
RoleACL(QObject *parent=nullptr)
Definition: roleacl.cpp:126