cutelyst  3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
memcachedsessionstore.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2017-2022 Matthias Fehring <mf@huessenbergnetz.de>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include "memcachedsessionstore_p.h"
7 
8 #include <Cutelyst/Application>
9 #include <Cutelyst/Context>
10 #include <Cutelyst/Engine>
11 #include <Cutelyst/Plugins/Memcached/Memcached>
12 
13 #include <QCoreApplication>
14 #include <QLoggingCategory>
15 
16 using namespace Cutelyst;
17 
18 Q_LOGGING_CATEGORY(C_MEMCACHEDSESSIONSTORE, "cutelyst.plugin.memcachedsessionstore", QtWarningMsg)
19 
20 #define SESSION_STORE_MEMCD_SAVE QStringLiteral("_c_session_store_memcd_save")
21 #define SESSION_STORE_MEMCD_DATA QStringLiteral("_c_session_store_memcd_data")
22 
23 static QVariantHash loadMemcSessionData(Context *c, const QString &sid, const QString &groupKey);
24 
26  : SessionStore(parent)
27  , d_ptr(new MemcachedSessionStorePrivate)
28 {
30  Q_ASSERT_X(app,
31  "construct MemachedSessionStore",
32  "you have to specifiy a pointer to the Application object");
33  const QVariantMap map =
34  app->engine()->config(QStringLiteral("Cutelyst_MemcachedSessionStore_Plugin"));
35  d->groupKey = map.value(QStringLiteral("group_key")).toString();
36 }
37 
39 {
40 }
41 
43  const QString &sid,
44  const QString &key,
45  const QVariant &defaultValue)
46 {
47  QVariant data;
49  const QVariantHash hash = loadMemcSessionData(c, sid, d->groupKey);
50  data = hash.value(key, defaultValue);
51  return data;
52 }
53 
55  const QString &sid,
56  const QString &key,
57  const QVariant &value)
58 {
60  QVariantHash data = loadMemcSessionData(c, sid, d->groupKey);
61  data.insert(key, value);
62  c->setStash(SESSION_STORE_MEMCD_DATA, data);
63  c->setStash(SESSION_STORE_MEMCD_SAVE, true);
64 
65  return true;
66 }
67 
69 {
71  QVariantHash data = loadMemcSessionData(c, sid, d->groupKey);
72  data.remove(key);
73  c->setStash(SESSION_STORE_MEMCD_DATA, data);
74  c->setStash(SESSION_STORE_MEMCD_SAVE, true);
75 
76  return true;
77 }
78 
80 {
81  Q_UNUSED(c)
82  Q_UNUSED(expires)
83 
84  return true;
85 }
86 
88 {
90  d->groupKey = groupKey;
91 }
92 
93 QVariantHash loadMemcSessionData(Context *c, const QString &sid, const QString &groupKey)
94 {
95  QVariantHash data;
96  const QVariant sessionVariant = c->stash(SESSION_STORE_MEMCD_DATA);
97  if (!sessionVariant.isNull()) {
98  data = sessionVariant.toHash();
99  return data;
100  }
101 
102  const static QString sessionPrefix =
104  const QString sessionKey = sessionPrefix + sid;
105 
107  if (!c->stash(SESSION_STORE_MEMCD_SAVE).toBool()) {
108  return;
109  }
110 
111  const QVariantHash data = c->stash(SESSION_STORE_MEMCD_DATA).toHash();
112 
113  if (data.isEmpty()) {
114  bool ok = false;
115  if (groupKey.isEmpty()) {
116  ok = Memcached::remove(sessionKey);
117  } else {
118  ok = Memcached::removeByKey(groupKey, sessionKey);
119  }
120  if (!ok) {
121  qCWarning(C_MEMCACHEDSESSIONSTORE, "Failed to remove session from Memcached.");
122  }
123  } else {
124  bool ok = false;
125  const time_t expires = data.value(QStringLiteral("expires")).value<time_t>();
126  if (groupKey.isEmpty()) {
127  ok = Memcached::set(sessionKey, data, expires);
128  } else {
129  ok = Memcached::setByKey(groupKey, sessionKey, data, expires);
130  }
131  if (!ok) {
132  qCWarning(C_MEMCACHEDSESSIONSTORE, "Failed to store session to Memcached.");
133  }
134  }
135  });
136 
137  if (groupKey.isEmpty()) {
138  data = Memcached::get<QVariantHash>(sessionKey);
139  } else {
140  data = Memcached::getByKey<QVariantHash>(groupKey, sessionKey);
141  }
142 
143  c->setStash(SESSION_STORE_MEMCD_DATA, data);
144 
145  return data;
146 }
147 
148 #include "moc_memcachedsessionstore.cpp"
virtual bool storeSessionData(Context *c, const QString &sid, const QString &key, const QVariant &value) final
Memcached based session store.
QHash< QString, QVariant > toHash() const const
virtual bool deleteSessionData(Context *c, const QString &sid, const QString &key) final
T value() const const
void setStash(const QString &key, const QVariant &value)
Definition: context.cpp:217
MemcachedSessionStore(Application *app, QObject *parent=nullptr)
The Cutelyst Context.
Definition: context.h:38
virtual bool deleteExpiredSessions(Context *c, quint64 expires) final
virtual QVariant getSessionData(Context *c, const QString &sid, const QString &key, const QVariant &defaultValue) final
bool isNull() const const
void stash(const QVariantHash &unite)
Definition: context.cpp:566
QVariantMap config(const QString &entity) const
user configuration for the application
Definition: engine.cpp:290
bool isEmpty() const const
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:7
static bool setByKey(const QString &groupKey, const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
Definition: memcached.cpp:327
static bool removeByKey(const QString &groupKey, const QString &key, MemcachedReturnType *returnType=nullptr)
Definition: memcached.cpp:714
static bool remove(const QString &key, MemcachedReturnType *returnType=nullptr)
Definition: memcached.cpp:685
void setGroupKey(const QString &groupKey)
Application * app() const noexcept
Definition: context.cpp:90
void afterDispatch(Cutelyst::Context *c)
The Cutelyst Application.
Definition: application.h:42
Engine * engine() const noexcept
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString applicationName()
static bool set(const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
Definition: memcached.cpp:282