cutelyst 5.0.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
htpasswd.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2014-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "htpasswd.h"
6
7#include "common.h"
8
9#include <QFile>
10#include <QLoggingCategory>
11#include <QTemporaryFile>
12
13using namespace Cutelyst;
14using namespace Qt::StringLiterals;
15
16Q_LOGGING_CATEGORY(C_AUTH_HTPASSWD, "cutelyst.plugin.authentication.htpasswd", QtWarningMsg)
17
19 : m_filename(name)
20{
21}
22
26
28{
29 const QString username = user.value(u"username"_s);
30
31 QTemporaryFile tmp(m_filename + u"-XXXXXXX");
32 tmp.setAutoRemove(false); // sort of a backup
33 if (!tmp.open()) {
34 qCWarning(C_AUTH_HTPASSWD) << "Failed to open temporary file for writing";
35 return;
36 }
37
38 bool wrote = false;
39 QFile file(m_filename);
40 if (file.exists() && file.open(QFile::ReadWrite | QFile::Text)) {
41 while (!file.atEnd()) {
42 QByteArray line = file.readLine();
43 QByteArrayList parts = line.split(':');
44 if (!wrote && parts.size() >= 2 && parts.first() == username.toLatin1()) {
45 line = username.toLatin1() + ':' +
46 user.value(u"password"_s).toLatin1().replace(':', ',') + '\n';
47 wrote = true;
48 }
49 tmp.write(line);
50 }
51 file.close();
52 }
53
54 if (!wrote) {
55 QByteArray line = username.toLatin1() + ':' +
56 user.value(u"password"_s).toLatin1().replace(':', ',') + '\n';
57 tmp.write(line);
58 }
59
60 if (file.exists() && !file.remove()) {
61 qCWarning(C_AUTH_HTPASSWD) << "Failed to remove auth file for replacement";
62 return;
63 }
64
65 if (!tmp.rename(m_filename)) {
66 qCWarning(C_AUTH_HTPASSWD) << "Failed to rename temporary file";
67 }
68}
69
71{
72 Q_UNUSED(c);
74 const QString username = userInfo.value(u"username"_s);
75
76 QFile file(m_filename);
77 if (file.open(QFile::ReadOnly | QFile::Text)) {
78 while (!file.atEnd()) {
79 QByteArray line = file.readLine();
80 QByteArrayList parts = line.trimmed().split(':');
81 if (parts.size() >= 2 && !parts.first().startsWith('#') &&
82 parts.first() == username.toLatin1()) {
83 ret.insert(u"username"_s, username);
84 ret.setId(username);
85 QByteArray password = parts.at(1);
86 ret.insert(u"password"_s, QString::fromLatin1(password.replace(',', ':')));
87 break;
88 }
89 }
90 }
91 return ret;
92}
93
95{
96 Q_UNUSED(c);
97 return user.id();
98}
99
101{
102 return findUser(c, {{u"username"_s, frozenUser.toString()}});
103}
Container for user data retrieved from an AuthenticationStore.
void setId(const QVariant &id)
void insert(const QString &key, const QVariant &value)
The Cutelyst Context.
Definition context.h:42
Authentication data store using a flat file.
Definition htpasswd.h:21
virtual ~StoreHtpasswd() override
Definition htpasswd.cpp:23
QVariant forSession(Context *c, const AuthenticationUser &user) override final
Definition htpasswd.cpp:94
AuthenticationUser findUser(Context *c, const ParamsMultiMap &userInfo) override final
Definition htpasswd.cpp:70
AuthenticationUser fromSession(Context *c, const QVariant &frozenUser) override final
Definition htpasswd.cpp:100
void addUser(const ParamsMultiMap &user)
Definition htpasswd.cpp:27
The Cutelyst namespace holds all public Cutelyst API.
QByteArray & replace(QByteArrayView before, QByteArrayView after)
QList< QByteArray > split(char sep) const const
QByteArray trimmed() const const
bool exists(const QString &fileName)
bool open(FILE *fh, QIODeviceBase::OpenMode mode, QFileDevice::FileHandleFlags handleFlags)
bool remove()
virtual bool atEnd() const const override
virtual void close() override
QByteArray readLine(qint64 maxSize)
qint64 write(const QByteArray &data)
QList::const_reference at(qsizetype i) const const
T & first()
qsizetype size() const const
T value(const Key &key, const T &defaultValue) const const
QString fromLatin1(QByteArrayView str)
QByteArray toLatin1() const const
bool rename(const QString &newName)
void setAutoRemove(bool b)
QString toString() const const