types and db setup

This commit is contained in:
2026-03-11 00:10:34 +00:00
parent 2857c35936
commit 067d8434cd
9 changed files with 234 additions and 0 deletions

87
src/database.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include <pqxx/pqxx>
#include "database.hpp"
User PostgresDB::GetUser(const int uid) {
pqxx::connection C(conn_str);
pqxx::work W(C);
pqxx::result R = W.exec("SELECT * FROM users WHERE uid = $1", pqxx::params{uid});
if (R.empty()) {
W.commit();
throw std::runtime_error("User not found");
}
const pqxx::row& row = R[0];
User user;
user.uid = row["uid"].as<int>();
user.username = row["username"].as<std::string>();
user.password_hash = row["password_hash"].as<std::string>();
user.is_system = row["is_system"].as<bool>();
if (!user.is_system) {
W.commit();
return user;
}
pqxx::result R2 = W.exec("SELECT * FROM systems WHERE uid = $1", pqxx::params{user.uid});
if (R2.empty()) {
W.commit();
throw std::runtime_error("System not found");
}
const pqxx::row& row2 = R2[0];
user.system = new System;
user.system->sid = row2["sid"].as<int>();
user.system->uid = row2["uid"].as<int>();
pqxx::result R3 = W.exec("SELECT * FROM members WHERE sid = $1", pqxx::params{user.system->sid});
for (auto row : R3) {
Member member;
member.mid = row["mid"].as<int>();
member.sid = row["sid"].as<int>();
member.name = row["name"].as<std::string>();
member.pronouns = row["pronouns"].as<std::string>();
member.description = row["description"].as<std::string>();
user.system->members.push_back(member);
}
pqxx::result R4 = W.exec("SELECT * FROM access_tokens WHERE uid = $1", pqxx::params{user.uid});
if (!R4.empty()) {
const pqxx::row& row4 = R4[0];
user.accesstoken = new AcessToken;
user.accesstoken->uid = row4["uid"].as<int>();
user.accesstoken->token = row4["token"].as<std::string>();
}
W.commit();
return user;
}
User PostgresDB::GetUser(const std::string& username, const std::string& password) {
pqxx::connection C(conn_str);
pqxx::work W(C);
pqxx::result R = W.exec("SELECT * FROM users WHERE username = $1", pqxx::params{username});
if (R.size() == 0) {
W.commit();
throw std::runtime_error("User not found");
}
const pqxx::row& row = R[0];
User user;
user.password_hash = row["password_hash"].as<std::string>();
if (!user.CheckPassword(password)) {
W.commit();
throw std::runtime_error("Invalid password");
}
return PostgresDB::GetUser(row["uid"].as<int>());
}

27
src/hashing.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include <crypt.h>
#include <stdexcept>
#include "hashing.hpp"
std::string hashing::GenerateSetting(unsigned long cost) {
// "$y$" is the yescrypt prefix
const char* setting = crypt_gensalt("$y$", cost, nullptr, 0);
if (!setting)
throw std::runtime_error("crypt_gensalt() failed yescrypt may not be supported");
return setting;
}
std::string hashing::HashPassword(const std::string& password, const std::string& setting) {
crypt_data data{};
const char* hash = crypt_r(password.c_str(), setting.c_str(), &data);
if (!hash || hash[0] == '*')
throw std::runtime_error("crypt_r() failed");
return hash;
}
bool hashing::VerifyPassword(const std::string& password, const std::string& stored_hash) {
crypt_data data{};
const char* result = crypt_r(password.c_str(), stored_hash.c_str(), &data);
if (!result || result[0] == '*')
return false;
return stored_hash == result;
}

13
src/main.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "database.hpp"
#include "creds.hpp"
#include <iostream>
int main() {
PostgresDB db(DB_CREDS);
User user = db.GetUser("toaster", "password");
std::cout << "User: " << user.username << std::endl;
std::cout << "System id: " << user.system->sid << std::endl;
std::cout << "Member 0 Name: " << user.system->members[0].name << std::endl;
}