#include "user.h" #include #include #include #include #include #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()) 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); }