cutelyst  4.4.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
roleacl.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2014-2022 Daniel Nicoletti <dantti12@gmail.com>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #include "common.h"
6 #include "roleacl_p.h"
7 
8 #include <Cutelyst/Controller>
9 #include <Cutelyst/Dispatcher>
10 #include <Cutelyst/Plugins/Authentication/authentication.h>
11 
12 using namespace Cutelyst;
13 
124  : Component(new RoleACLPrivate, parent)
125 {
126 }
127 
128 Component::Modifiers RoleACL::modifiers() const
129 {
130  return AroundExecute;
131 }
132 
133 bool RoleACL::init(Cutelyst::Application *application, const QVariantHash &args)
134 {
135  Q_D(RoleACL);
136  Q_UNUSED(application)
137 
138  const auto attributes = args.value(QLatin1String("attributes")).value<ParamsMultiMap>();
139  d->actionReverse = args.value(QLatin1String("reverse")).toString();
140 
141  if (!attributes.contains(QLatin1String("RequiresRole")) &&
142  !attributes.contains(QLatin1String("AllowedRole"))) {
143  qFatal("RoleACL: Action %s requires at least one RequiresRole or AllowedRole attribute",
144  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",
160  qPrintable(d->actionReverse));
161  }
162  d->aclDetachTo = it.value();
163 
164  return true;
165 }
166 
168 {
169  Q_D(const RoleACL);
170 
171  if (canVisit(c)) {
172  return Component::aroundExecute(c, stack);
173  }
174 
175  c->detach(d->detachTo);
176 
177  return false;
178 }
179 
181 {
182  Q_D(const RoleACL);
183 
184  const QStringList user_has =
185  Authentication::user(c).value(QStringLiteral("roles")).toStringList();
186 
187  const QStringList required = d->requiresRole;
188  const QStringList allowed = d->allowedRole;
189 
190  if (!required.isEmpty() && !allowed.isEmpty()) {
191  for (const QString &role : required) {
192  if (!user_has.contains(role)) {
193  return false;
194  }
195  }
196 
197  for (const QString &role : allowed) {
198  if (user_has.contains(role)) {
199  return true;
200  }
201  }
202  } else if (!required.isEmpty()) {
203  for (const QString &role : required) {
204  if (!user_has.contains(role)) {
205  return false;
206  }
207  }
208  return true;
209  } else if (!allowed.isEmpty()) {
210  for (const QString &role : allowed) {
211  if (user_has.contains(role)) {
212  return true;
213  }
214  }
215  }
216 
217  return false;
218 }
219 
220 bool RoleACL::dispatcherReady(const Dispatcher *dispatcher, Cutelyst::Controller *controller)
221 {
222  Q_D(RoleACL);
223  Q_UNUSED(dispatcher)
224 
225  d->detachTo = controller->actionFor(d->aclDetachTo);
226  if (!d->detachTo) {
227  d->detachTo = dispatcher->getActionByPath(d->aclDetachTo);
228  if (!d->detachTo) {
229  qFatal(
230  "RoleACL: Action '%s' requires a valid action set on the ACLDetachTo(%s) attribute",
231  qPrintable(d->actionReverse),
232  qPrintable(d->aclDetachTo));
233  }
234  }
235 
236  return true;
237 }
238 
239 #include "moc_roleacl.cpp"
The Cutelyst application.
Definition: application.h:66
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
static AuthenticationUser user(Context *c)
The Cutelyst Component base class.
Definition: component.h:30
virtual bool aroundExecute(Context *c, QStack< Component * > stack)
Definition: component.cpp:103
The Cutelyst Context.
Definition: context.h:42
void detach(Action *action=nullptr)
Definition: context.cpp:339
Cutelyst Controller base class.
Definition: controller.h:56
Action * actionFor(QStringView name) const
Definition: controller.cpp:259
The Cutelyst Dispatcher.
Definition: dispatcher.h:29
Action * getActionByPath(QStringView path) const
Definition: dispatcher.cpp:232
User role-based authorization action role.
Definition: roleacl.h:18
bool canVisit(Context *c) const
Definition: roleacl.cpp:180
bool init(Application *application, const QVariantHash &args) override
Definition: roleacl.cpp:133
RoleACL(QObject *parent=nullptr)
Definition: roleacl.cpp:123
bool aroundExecute(Context *c, QStack< Component * > stack) override
Definition: roleacl.cpp:167
Modifiers modifiers() const override
Definition: roleacl.cpp:128
bool dispatcherReady(const Dispatcher *dispatcher, Controller *controller) override
Definition: roleacl.cpp:220
The Cutelyst namespace holds all public Cutelyst API.
void append(QList::parameter_type value)
bool isEmpty() const const
T value(const Key &key, const T &defaultValue) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QStringList toStringList() const const