cutelyst 4.3.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;
17
18Q_LOGGING_CATEGORY(C_MEMCACHEDSESSIONSTORE, "cutelyst.plugin.sessionmemcached", QtWarningMsg)
19
20const QString MemcachedSessionStorePrivate::stashKeyMemcdSave{u"_c_session_store_memcd_save"_qs};
21const QString MemcachedSessionStorePrivate::stashKeyMemcdData{u"_c_session_store_memcd_data"_qs};
22
23static QVariantHash
24 loadMemcSessionData(Context *c, const QByteArray &sid, const QByteArray &groupKey);
25
27 : SessionStore(parent)
28 , d_ptr(new MemcachedSessionStorePrivate)
29{
31 Q_ASSERT_X(app,
32 "construct MemachedSessionStore",
33 "you have to specifiy a pointer to the Application object");
34 const QVariantMap map = app->engine()->config(u"Cutelyst_MemcachedSessionStore_Plugin"_qs);
35 d->groupKey = map.value(u"group_key"_qs).toString().toLatin1();
36}
37
39
41 const QByteArray &sid,
42 const QString &key,
43 const QVariant &defaultValue)
44{
45 QVariant data;
47 const QVariantHash hash = loadMemcSessionData(c, sid, d->groupKey);
48 data = hash.value(key, defaultValue);
49 return data;
50}
51
53 const QByteArray &sid,
54 const QString &key,
55 const QVariant &value)
56{
58 QVariantHash data = loadMemcSessionData(c, sid, d->groupKey);
59 data.insert(key, value);
60 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdData, data);
61 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdSave, true);
62
63 return true;
64}
65
67{
69 QVariantHash data = loadMemcSessionData(c, sid, d->groupKey);
70 data.remove(key);
71 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdData, data);
72 c->setStash(MemcachedSessionStorePrivate::stashKeyMemcdSave, true);
73
74 return true;
75}
76
78{
79 Q_UNUSED(c)
80 Q_UNUSED(expires)
81
82 return true;
83}
84
86{
88 d->groupKey = groupKey;
89}
90
91QVariantHash loadMemcSessionData(Context *c, const QByteArray &sid, const QByteArray &groupKey)
92{
93 QVariantHash data;
94 const QVariant sessionVariant = c->stash(MemcachedSessionStorePrivate::stashKeyMemcdData);
95 if (!sessionVariant.isNull()) {
96 data = sessionVariant.toHash();
97 return data;
98 }
99
100 const static QByteArray sessionPrefix =
101 QCoreApplication::applicationName().toLatin1() + "_sess_";
102 const QByteArray sessionKey = sessionPrefix + sid;
103
105 if (!c->stash(MemcachedSessionStorePrivate::stashKeyMemcdSave).toBool()) {
106 return;
107 }
108
109 const QVariantHash data =
110 c->stash(MemcachedSessionStorePrivate::stashKeyMemcdData).toHash();
111
112 if (data.isEmpty()) {
113 bool ok = false;
114 if (groupKey.isEmpty()) {
115 ok = Memcached::remove(sessionKey);
116 } else {
117 ok = Memcached::removeByKey(groupKey, sessionKey);
118 }
119 if (!ok) {
120 qCWarning(C_MEMCACHEDSESSIONSTORE)
121 << "Failed to remove session from Memcached." << groupKey << sessionKey;
122 }
123 } else {
124 bool ok = false;
125 const auto expires = data.value(u"expires"_qs).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(MemcachedSessionStorePrivate::stashKeyMemcdData, data);
144
145 return data;
146}
147
148#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:562
void setStash(const QString &key, const QVariant &value)
Definition context.cpp:212
Application * app() const noexcept
Definition context.cpp:91
QVariantMap config(const QString &entity) const
Definition engine.cpp:263
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