blob: 4667ebf7cce022ee2649026e5632e8e839d54847 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#include "user.h"
#include <QCryptographicHash>
#include <QDebug>
#include <QRandomGenerator>
#include <QSqlError>
#include <QSqlQuery>
#include "constants.h"
#include "rsshit_db.h"
namespace rsshit {
QByteArray generateSalt()
{
constexpr qsizetype hashSizeBytes{32};
QByteArray saltArray{hashSizeBytes, char{0}};
auto generator = QRandomGenerator::global();
generator->fillRange((uint32_t *) saltArray.data(), hashSizeBytes);
return saltArray;
}
} // namespace rsshit
// FIXME: use better password hashing algo
User::User(const QString &login, const QString &password)
: login{login}
, salt{rsshit::generateSalt()}
, passwordHash{hashPassword(password)}
{
qDebug() << __func__ << "login:" << login;
qDebug() << __func__ << "salt size:" << salt.size();
qDebug() << __func__ << "passwordHash size:" << passwordHash.size();
}
int User::getDbId()
{
if (id != rsshit::db::IdNotFound)
return id;
const auto db = rsshit::db::open();
if (!db)
return rsshit::db::IdNotFound;
QSqlQuery selectQ{"select id from users where login=?"};
selectQ.addBindValue(login);
if (!selectQ.exec()) {
qWarning() << "cannot exec query" << selectQ.lastQuery() << ":"
<< selectQ.lastError().text();
return rsshit::db::IdNotFound;
}
if (!selectQ.next())
return rsshit::db::IdNotFound;
const auto idVariant = selectQ.value(rsshit::db::idTag);
if (!idVariant.isValid() || !idVariant.canConvert<int>())
return rsshit::db::IdNotFound;
bool ok{false};
const auto result = idVariant.toInt(&ok);
if (!ok) {
qWarning() << "got invalid id from db:" << idVariant;
return rsshit::db::IdNotFound;
}
return result;
}
int User::createInDb()
{
if (id != rsshit::db::IdNotFound)
return id;
const auto db = rsshit::db::open();
if (!db)
return rsshit::db::IdNotFound;
if (login.isEmpty() || salt.isEmpty() || passwordHash.isEmpty())
return rsshit::db::IdNotFound;
QSqlQuery insertQ{"insert into users(login, salt, password_hash) values(?, ?, ?)"};
insertQ.addBindValue(login);
insertQ.addBindValue(salt);
insertQ.addBindValue(passwordHash);
if (!insertQ.exec()) {
qWarning() << "cannot exec query" << insertQ.lastQuery() << ":"
<< insertQ.lastError().text();
return rsshit::db::IdNotFound;
}
return insertQ.lastInsertId().toInt();
}
int User::getOrInsertDbId()
{
const auto id = getDbId();
if (id != rsshit::db::IdNotFound)
return id;
return createInDb();
}
bool User::verifyPassword(const QString &password)
{
return hashPassword(password) == passwordHash;
}
QByteArray User::hashPassword(const QString &password)
{
return QCryptographicHash::hash(salt + password.toUtf8(), QCryptographicHash::Sha256);
}
|