cutelyst  3.7.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 "roleacl_p.h"
6 
7 #include "common.h"
8 
9 #include <Cutelyst/Plugins/Authentication/authentication.h>
10 #include <Cutelyst/Controller>
11 #include <Cutelyst/Dispatcher>
12 
13 using namespace Cutelyst;
14 
113 RoleACL::RoleACL(QObject *parent) : Component(new RoleACLPrivate, parent)
114 {
115 }
116 
117 Component::Modifiers RoleACL::modifiers() const
118 {
119  return AroundExecute;
120 }
121 
122 bool RoleACL::init(Cutelyst::Application *application, const QVariantHash &args)
123 {
124  Q_D(RoleACL);
125  Q_UNUSED(application)
126 
127  const auto attributes = args.value(QLatin1String("attributes")).value<ParamsMultiMap>();
128  d->actionReverse = args.value(QLatin1String("reverse")).toString();
129 
130  if (!attributes.contains(QLatin1String("RequiresRole")) && !attributes.contains(QLatin1String("AllowedRole"))) {
131  qFatal("RoleACL: Action %s requires at least one RequiresRole or AllowedRole attribute", qPrintable(d->actionReverse));
132  } else {
133  const QStringList required = attributes.values(QLatin1String("RequiresRole"));
134  for (const QString &role : required) {
135  d->requiresRole.append(role);
136  }
137 
138  const QStringList allowed = attributes.values(QLatin1String("AllowedRole"));
139  for (const QString &role : allowed) {
140  d->allowedRole.append(role);
141  }
142  }
143 
144  auto it = attributes.constFind(QLatin1String("ACLDetachTo"));
145  if (it == attributes.constEnd() || it.value().isEmpty()) {
146  qFatal("RoleACL: Action %s requires the ACLDetachTo(<action>) attribute", qPrintable(d->actionReverse));
147  }
148  d->aclDetachTo = it.value();
149 
150  return true;
151 }
152 
153 bool RoleACL::aroundExecute(Context *c, QStack<Cutelyst::Component *> stack)
154 {
155  Q_D(const RoleACL);
156 
157  if (canVisit(c)) {
158  return Component::aroundExecute(c, stack);
159  }
160 
161  c->detach(d->detachTo);
162 
163  return false;
164 }
165 
167 {
168  Q_D(const RoleACL);
169 
170  const QStringList user_has = Authentication::user(c).value(QStringLiteral("roles")).toStringList();
171 
172  const QStringList required = d->requiresRole;
173  const QStringList allowed = d->allowedRole;
174 
175  if (!required.isEmpty() && !allowed.isEmpty()) {
176  for (const QString &role : required) {
177  if (!user_has.contains(role)) {
178  return false;
179  }
180  }
181 
182  for (const QString &role : allowed) {
183  if (user_has.contains(role)) {
184  return true;
185  }
186  }
187  } else if (!required.isEmpty()) {
188  for (const QString &role : required) {
189  if (!user_has.contains(role)) {
190  return false;
191  }
192  }
193  return true;
194  } else if (!allowed.isEmpty()) {
195  for (const QString &role : allowed) {
196  if (user_has.contains(role)) {
197  return true;
198  }
199  }
200  }
201 
202  return false;
203 }
204 
205 bool RoleACL::dispatcherReady(const Dispatcher *dispatcher, Cutelyst::Controller *controller)
206 {
207  Q_D(RoleACL);
208  Q_UNUSED(dispatcher)
209 
210  d->detachTo = controller->actionFor(d->aclDetachTo);
211  if (!d->detachTo) {
212  d->detachTo = dispatcher->getActionByPath(d->aclDetachTo);
213  if (!d->detachTo) {
214  qFatal("RoleACL: Action '%s' requires a valid action set on the ACLDetachTo(%s) attribute",
215  qPrintable(d->actionReverse), qPrintable(d->aclDetachTo));
216  }
217  }
218 
219  return true;
220 }
221 
222 #include "moc_roleacl.cpp"
The Cutelyst Application.
Definition: application.h:43
static AuthenticationUser user(Context *c)
The Cutelyst Component base class.
Definition: component.h:26
virtual bool aroundExecute(Context *c, QStack< Component * > stack)
Definition: component.cpp:101
The Cutelyst Context.
Definition: context.h:39
void detach(Action *action=nullptr)
Definition: context.cpp:339
Cutelyst Controller base class
Definition: controller.h:90
Action * actionFor(const QString &name) const
Definition: controller.cpp:37
The Cutelyst Dispatcher.
Definition: dispatcher.h:28
Action * getActionByPath(const QString &path) const
Definition: dispatcher.cpp:220
User role-based authorization action class.
Definition: roleacl.h:19
bool canVisit(Context *c) const
Definition: roleacl.cpp:166
virtual bool init(Application *application, const QVariantHash &args) override
Definition: roleacl.cpp:122
RoleACL(QObject *parent=nullptr)
Definition: roleacl.cpp:113
virtual bool aroundExecute(Context *c, QStack< Component * > stack) override
Definition: roleacl.cpp:153
virtual Modifiers modifiers() const override
Definition: roleacl.cpp:117
virtual bool dispatcherReady(const Dispatcher *dispatcher, Controller *controller) override
Definition: roleacl.cpp:205
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:8
QMultiMap< QString, QString > ParamsMultiMap