cutelyst  5.0.1
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 Qt::StringLiterals;
13 using namespace Cutelyst;
14 
124 RoleACL::RoleACL(QObject *parent)
125  : Component(new RoleACLPrivate, parent)
126 {
127 }
128 
129 Component::Modifiers RoleACL::modifiers() const
130 {
131  return AroundExecute;
132 }
133 
134 bool RoleACL::init(Cutelyst::Application *application, const QVariantHash &args)
135 {
136  Q_D(RoleACL);
137  Q_UNUSED(application)
138 
139  const auto attributes = args.value(u"attributes"_s).value<ParamsMultiMap>();
140  d->actionReverse = args.value(u"reverse"_s).toString();
141 
142  if (!attributes.contains(u"RequiresRole"_s) && !attributes.contains(u"AllowedRole"_s)) {
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(u"RequiresRole"_s);
147  for (const QString &role : required) {
148  d->requiresRole.append(role);
149  }
150 
151  const QStringList allowed = attributes.values(u"AllowedRole"_s);
152  for (const QString &role : allowed) {
153  d->allowedRole.append(role);
154  }
155  }
156 
157  auto it = attributes.constFind(u"ACLDetachTo"_s);
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 = Authentication::user(c).value(u"roles"_s).toStringList();
185 
186  const QStringList required = d->requiresRole;
187  const QStringList allowed = d->allowedRole;
188 
189  if (!required.isEmpty() && !allowed.isEmpty()) {
190  bool allRequired = std::ranges::all_of(
191  required, [&user_has](const QString &role) { return user_has.contains(role); });
192  if (!allRequired) {
193  return false;
194  }
195 
196  return std::ranges::any_of(
197  allowed, [&user_has](const QString &role) { return user_has.contains(role); });
198  } else if (!required.isEmpty()) {
199  return std::ranges::all_of(
200  required, [&user_has](const QString &role) { return user_has.contains(role); });
201  } else if (!allowed.isEmpty()) {
202  return std::ranges::any_of(
203  allowed, [&user_has](const QString &role) { return user_has.contains(role); });
204  }
205 
206  return false;
207 }
208 
209 bool RoleACL::dispatcherReady(const Dispatcher *dispatcher, Cutelyst::Controller *controller)
210 {
211  Q_D(RoleACL);
212  Q_UNUSED(dispatcher)
213 
214  d->detachTo = controller->actionFor(d->aclDetachTo);
215  if (!d->detachTo) {
216  d->detachTo = dispatcher->getActionByPath(d->aclDetachTo);
217  if (!d->detachTo) {
218  qFatal(
219  "RoleACL: Action '%s' requires a valid action set on the ACLDetachTo(%s) attribute",
220  qPrintable(d->actionReverse),
221  qPrintable(d->aclDetachTo));
222  }
223  }
224 
225  return true;
226 }
227 
228 #include "moc_roleacl.cpp"
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
bool init(Application *application, const QVariantHash &args) override
Definition: roleacl.cpp:134
void detach(Action *action=nullptr)
Definition: context.cpp:338
Action * getActionByPath(QStringView path) const
Definition: dispatcher.cpp:235
bool aroundExecute(Context *c, QStack< Component *> stack) override
Definition: roleacl.cpp:167
The Cutelyst Component base class.
Definition: component.h:30
The Cutelyst Context.
Definition: context.h:42
Cutelyst Controller base class.
Definition: controller.h:55
bool canVisit(Context *c) const
Definition: roleacl.cpp:180
User role-based authorization action role.
Definition: roleacl.h:17
bool isEmpty() const const
Modifiers modifiers() const override
Definition: roleacl.cpp:129
The Cutelyst namespace holds all public Cutelyst API.
bool dispatcherReady(const Dispatcher *dispatcher, Controller *controller) override
Definition: roleacl.cpp:209
QStringList toStringList() const const
void append(QList< T > &&value)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
virtual bool aroundExecute(Context *c, QStack< Component *> stack)
Definition: component.cpp:101
The Cutelyst application.
Definition: application.h:72
static AuthenticationUser user(Context *c)
Action * actionFor(QStringView name) const
Definition: controller.cpp:262
The Cutelyst Dispatcher.
Definition: dispatcher.h:28
T value(const Key &key, const T &defaultValue) const const