cutelyst 5.0.0
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-2023 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
16using namespace Cutelyst;
17using namespace Qt::Literals::StringLiterals;
18
19Q_LOGGING_CATEGORY(C_MEMCACHEDSESSIONSTORE, "cutelyst.plugin.sessionmemcached", QtWarningMsg)
20
21const QString MemcachedSessionStorePrivate::stashKeyMemcdSave{u"_c_session_store_memcd_save"_s};
22const QString MemcachedSessionStorePrivate::stashKeyMemcdData{u"_c_session_store_memcd_data"_s};
23
24static QVariantHash
25 loadMemcSessionData(Context *c, const QByteArray &sid, const QByteArray &groupKey);
26
28 : SessionStore(parent)
29 , d_ptr(new MemcachedSessionStorePrivate)
30{
32 Q_ASSERT_X(app,
33 "construct MemachedSessionStore",
34 "you have to specifiy a pointer to the Application object");
35 const QVariantMap map = app->engine()->config(u"Cutelyst_MemcachedSessionStore_Plugin"_s);
36 d->groupKey = map.value(u"group_key"_s).toString().toLatin1();
37}
38
40
42 const QByteArray &sid,
43 const QString &key,
44 const QVariant &defaultValue)
45{
46 QVariant data;
48 const QVariantHash hash = loadMemcSessionData(c, sid, d->groupKey);
49 data = hash.value(key, defaultValue);
50 return data;
51}
52
54 const QByteArray &sid,
55 const QString &key,
56 const QVariant &value)
57{
59 QVariantHash data = loadMemcSessionData(c, sid, d->groupKey);
60 data.insert(key, value);
61 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdData, data);
62 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdSave, true);
63
64 return true;
65}
66
68{
70 QVariantHash data = loadMemcSessionData(c, sid, d->groupKey);
71 data.remove(key);
72 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdData, data);
73 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdSave, true);
74
75 return true;
76}
77
79{
80 Q_UNUSED(c)
81 Q_UNUSED(expires)
82
83 return true;
84}
85
87{
89 d->groupKey = groupKey;
90}
91
92QVariantHash loadMemcSessionData(Context *c, const QByteArray &sid, const QByteArray &groupKey)
93{
94 QVariantHash data;
95 const QVariant sessionVariant = c->stash(MemcachedSessionStorePrivate::stashKeyMemcdData);
96 if (!sessionVariant.isNull()) {
97 data = sessionVariant.toHash();
98 return data;
99 }
100
101 const static QByteArray sessionPrefix =
102 QCoreApplication::applicationName().toLatin1() + "_sess_";
103 const QByteArray sessionKey = sessionPrefix + sid;
104
106 if (!c->stash(MemcachedSessionStorePrivate::stashKeyMemcdSave).toBool()) {
107 return;
108 }
109
110 const QVariantHash data =
111 c->stash(MemcachedSessionStorePrivate::stashKeyMemcdData).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)
122 << "Failed to remove session from Memcached." << groupKey << sessionKey;
123 }
124 } else {
125 bool ok = false;
126 const auto expires = data.value(u"expires"_s).value<time_t>();
127 if (groupKey.isEmpty()) {
128 ok = Memcached::set(sessionKey, data, expires);
129 } else {
130 ok = Memcached::setByKey(groupKey, sessionKey, data, expires);
131 }
132 if (!ok) {
133 qCWarning(C_MEMCACHEDSESSIONSTORE) << "Failed to store session to Memcached.";
134 }
135 }
136 });
137
138 if (groupKey.isEmpty()) {
139 data = Memcached::get<QVariantHash>(sessionKey);
140 } else {
141 data = Memcached::getByKey<QVariantHash>(groupKey, sessionKey);
142 }
143
144 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdData, data);
145
146 return data;
147}
148
149#include "moc_memcachedsessionstore.cpp"
The Cutelyst application.
Definition application.h:66
Engine * engine() const noexcept
void afterDispatch(Cutelyst::Context *c)
The Cutelyst Context.
Definition context.h:42
void stash(const QVariantHash &unite)
Definition context.cpp:563
void setStash(const QString &key, const QVariant &value)
Definition context.cpp:213
Application * app() const noexcept
Definition context.cpp:92
QVariantMap config(const QString &entity) const
Definition engine.cpp:122
Memcached based session store.
QVariant getSessionData(Context *c, const QByteArray &sid, const QString &key, const QVariant &defaultValue) override
void setGroupKey(const QByteArray &groupKey)
bool deleteExpiredSessions(Context *c, quint64 expires) override
bool deleteSessionData(Context *c, const QByteArray &sid, const QString &key) override
MemcachedSessionStore(Application *app, QObject *parent=nullptr)
bool storeSessionData(Context *c, const QByteArray &sid, const QString &key, const QVariant &value) override
static bool removeByKey(QByteArrayView groupKey, QByteArrayView key, ReturnType *returnType=nullptr)
static bool set(QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
static bool setByKey(QByteArrayView groupKey, QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
static bool remove(QByteArrayView key, ReturnType *returnType=nullptr)
Abstract class to create a session store.
Definition session.h:36
The Cutelyst namespace holds all public Cutelyst API.
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool isNull() const const
QHash< QString, QVariant > toHash() const const
T value() const const