Database Pool

This commit is contained in:
Blue 2023-12-29 14:40:00 -03:00
parent 59c1ffd027
commit fe2fbb9ad0
Signed by: blue
GPG Key ID: 9B203B252A63EE38
23 changed files with 268 additions and 63 deletions

View File

@ -40,6 +40,7 @@ message("Compile options: " ${COMPILE_OPTIONS_STRING})
find_package(nlohmann_json REQUIRED) find_package(nlohmann_json REQUIRED)
find_package(FCGI REQUIRED) find_package(FCGI REQUIRED)
find_package(Argon2 REQUIRED) find_package(Argon2 REQUIRED)
find_package(Threads REQUIRED)
add_executable(${PROJECT_NAME} main.cpp) add_executable(${PROJECT_NAME} main.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
@ -63,6 +64,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
FCGI::FCGI++ FCGI::FCGI++
nlohmann_json::nlohmann_json nlohmann_json::nlohmann_json
Argon2::Argon2 Argon2::Argon2
Threads::Threads
) )
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@ -1,11 +1,15 @@
set(HEADERS set(HEADERS
dbinterface.h interface.h
exceptions.h exceptions.h
pool.h
resource.h
) )
set(SOURCES set(SOURCES
dbinterface.cpp interface.cpp
exceptions.cpp exceptions.cpp
pool.cpp
resource.cpp
) )
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES}) target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})

View File

@ -3,18 +3,18 @@
#include "exceptions.h" #include "exceptions.h"
DBInterface::Duplicate::Duplicate(const std::string& text): DB::Duplicate::Duplicate(const std::string& text):
std::runtime_error(text) std::runtime_error(text)
{} {}
DBInterface::DuplicateLogin::DuplicateLogin(const std::string& text): DB::DuplicateLogin::DuplicateLogin(const std::string& text):
Duplicate(text) Duplicate(text)
{} {}
DBInterface::EmptyResult::EmptyResult(const std::string& text): DB::EmptyResult::EmptyResult(const std::string& text):
std::runtime_error(text) std::runtime_error(text)
{} {}
DBInterface::NoLogin::NoLogin(const std::string& text): DB::NoLogin::NoLogin(const std::string& text):
EmptyResult(text) EmptyResult(text)
{} {}

View File

@ -3,24 +3,27 @@
#pragma once #pragma once
#include "dbinterface.h" #include <string>
#include <stdexcept>
class DBInterface::Duplicate : public std::runtime_error { namespace DB {
class Duplicate : public std::runtime_error {
public: public:
explicit Duplicate(const std::string& text); explicit Duplicate(const std::string& text);
}; };
class DBInterface::DuplicateLogin : public DBInterface::Duplicate { class DuplicateLogin : public Duplicate {
public: public:
explicit DuplicateLogin(const std::string& text); explicit DuplicateLogin(const std::string& text);
}; };
class DBInterface::EmptyResult : public std::runtime_error { class EmptyResult : public std::runtime_error {
public: public:
explicit EmptyResult(const std::string& text); explicit EmptyResult(const std::string& text);
}; };
class DBInterface::NoLogin : public DBInterface::EmptyResult { class NoLogin : public EmptyResult {
public: public:
explicit NoLogin(const std::string& text); explicit NoLogin(const std::string& text);
}; };
}

View File

@ -1,18 +1,18 @@
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me> // SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#include "dbinterface.h" #include "interface.h"
#include "mysql/mysql.h" #include "mysql/mysql.h"
DBInterface::DBInterface(Type type): DB::Interface::Interface(Type type):
type(type), type(type),
state(State::disconnected) state(State::disconnected)
{} {}
DBInterface::~DBInterface() {} DB::Interface::~Interface() {}
std::unique_ptr<DBInterface> DBInterface::create(Type type) { std::unique_ptr<DB::Interface> DB::Interface::create(Type type) {
switch (type) { switch (type) {
case Type::mysql: case Type::mysql:
return std::make_unique<MySQL>(); return std::make_unique<MySQL>();
@ -21,6 +21,6 @@ std::unique_ptr<DBInterface> DBInterface::create(Type type) {
throw std::runtime_error("Unexpected database type: " + std::to_string((uint8_t)type)); throw std::runtime_error("Unexpected database type: " + std::to_string((uint8_t)type));
} }
DBInterface::State DBInterface::currentState() const { DB::Interface::State DB::Interface::currentState() const {
return state; return state;
} }

View File

@ -8,7 +8,8 @@
#include <memory> #include <memory>
#include <stdint.h> #include <stdint.h>
class DBInterface { namespace DB {
class Interface {
public: public:
enum class Type { enum class Type {
mysql mysql
@ -18,19 +19,14 @@ public:
connecting, connecting,
connected connected
}; };
static std::unique_ptr<DBInterface> create(Type type); static std::unique_ptr<Interface> create(Type type);
virtual ~DBInterface(); virtual ~Interface();
State currentState() const; State currentState() const;
const Type type; const Type type;
class Duplicate;
class DuplicateLogin;
class EmptyResult;
class NoLogin;
public: public:
virtual void connect(const std::string& path) = 0; virtual void connect(const std::string& path) = 0;
virtual void disconnect() = 0; virtual void disconnect() = 0;
@ -46,8 +42,9 @@ public:
virtual unsigned int createSession(const std::string& login, const std::string& access, const std::string& renew) = 0; virtual unsigned int createSession(const std::string& login, const std::string& access, const std::string& renew) = 0;
protected: protected:
DBInterface(Type type); Interface(Type type);
protected: protected:
State state; State state;
}; };
}

View File

@ -23,8 +23,8 @@ constexpr const char* createSessionQuery = "INSERT INTO sessions (`owner`, `acce
static const std::filesystem::path buildSQLPath = "database"; static const std::filesystem::path buildSQLPath = "database";
MySQL::MySQL(): DB::MySQL::MySQL():
DBInterface(Type::mysql), Interface(Type::mysql),
connection(), connection(),
login(), login(),
password(), password(),
@ -33,11 +33,11 @@ MySQL::MySQL():
mysql_init(&connection); mysql_init(&connection);
} }
MySQL::~MySQL() { DB::MySQL::~MySQL() {
mysql_close(&connection); mysql_close(&connection);
} }
void MySQL::connect(const std::string& path) { void DB::MySQL::connect(const std::string& path) {
if (state != State::disconnected) if (state != State::disconnected)
return; return;
@ -59,7 +59,7 @@ void MySQL::connect(const std::string& path) {
state = State::connected; state = State::connected;
} }
void MySQL::setCredentials(const std::string& login, const std::string& password) { void DB::MySQL::setCredentials(const std::string& login, const std::string& password) {
if (MySQL::login == login && MySQL::password == password) if (MySQL::login == login && MySQL::password == password)
return; return;
@ -81,7 +81,7 @@ void MySQL::setCredentials(const std::string& login, const std::string& password
throw std::runtime_error(std::string("Error changing credetials: ") + mysql_error(con)); throw std::runtime_error(std::string("Error changing credetials: ") + mysql_error(con));
} }
void MySQL::setDatabase(const std::string& database) { void DB::MySQL::setDatabase(const std::string& database) {
if (MySQL::database == database) if (MySQL::database == database)
return; return;
@ -97,7 +97,7 @@ void MySQL::setDatabase(const std::string& database) {
throw std::runtime_error(std::string("Error changing db: ") + mysql_error(con)); throw std::runtime_error(std::string("Error changing db: ") + mysql_error(con));
} }
void MySQL::disconnect() { void DB::MySQL::disconnect() {
if (state == State::disconnected) if (state == State::disconnected)
return; return;
@ -106,7 +106,7 @@ void MySQL::disconnect() {
mysql_init(con); //this is ridiculous! mysql_init(con); //this is ridiculous!
} }
void MySQL::executeFile(const std::filesystem::path& relativePath) { void DB::MySQL::executeFile(const std::filesystem::path& relativePath) {
MYSQL* con = &connection; MYSQL* con = &connection;
std::filesystem::path path = sharedPath() / relativePath; std::filesystem::path path = sharedPath() / relativePath;
if (!std::filesystem::exists(path)) if (!std::filesystem::exists(path))
@ -138,7 +138,7 @@ void MySQL::executeFile(const std::filesystem::path& relativePath) {
} }
} }
uint8_t MySQL::getVersion() { uint8_t DB::MySQL::getVersion() {
MYSQL* con = &connection; MYSQL* con = &connection;
int result = mysql_query(con, versionQuery); int result = mysql_query(con, versionQuery);
@ -161,14 +161,14 @@ uint8_t MySQL::getVersion() {
return 0; return 0;
} }
void MySQL::setVersion(uint8_t version) { void DB::MySQL::setVersion(uint8_t version) {
std::string strVersion = std::to_string(version); std::string strVersion = std::to_string(version);
Statement statement(&connection, updateQuery); Statement statement(&connection, updateQuery);
statement.bind(strVersion.data(), MYSQL_TYPE_VAR_STRING); statement.bind(strVersion.data(), MYSQL_TYPE_VAR_STRING);
statement.execute(); statement.execute();
} }
void MySQL::migrate(uint8_t targetVersion) { void DB::MySQL::migrate(uint8_t targetVersion) {
uint8_t currentVersion = getVersion(); uint8_t currentVersion = getVersion();
while (currentVersion < targetVersion) { while (currentVersion < targetVersion) {
@ -190,7 +190,7 @@ void MySQL::migrate(uint8_t targetVersion) {
std::cout << "Database is now on actual version " << std::to_string(targetVersion) << std::endl; std::cout << "Database is now on actual version " << std::to_string(targetVersion) << std::endl;
} }
std::optional<std::string> MySQL::getComment(std::string& string) { std::optional<std::string> DB::MySQL::getComment(std::string& string) {
ltrim(string); ltrim(string);
if (string.length() < 2) if (string.length() < 2)
return std::nullopt; return std::nullopt;
@ -218,7 +218,7 @@ std::optional<std::string> MySQL::getComment(std::string& string) {
return std::nullopt; return std::nullopt;
} }
unsigned int MySQL::registerAccount(const std::string& login, const std::string& hash) { unsigned int DB::MySQL::registerAccount(const std::string& login, const std::string& hash) {
//TODO validate filed lengths! //TODO validate filed lengths!
MYSQL* con = &connection; MYSQL* con = &connection;
MySQL::Transaction txn(con); MySQL::Transaction txn(con);
@ -247,7 +247,7 @@ unsigned int MySQL::registerAccount(const std::string& login, const std::string&
return id; return id;
} }
std::string MySQL::getAccountHash(const std::string& login) { std::string DB::MySQL::getAccountHash(const std::string& login) {
std::string l = login; std::string l = login;
MYSQL* con = &connection; MYSQL* con = &connection;
@ -265,7 +265,7 @@ std::string MySQL::getAccountHash(const std::string& login) {
return std::any_cast<const std::string&>(result[0][0]); return std::any_cast<const std::string&>(result[0][0]);
} }
unsigned int MySQL::createSession(const std::string& login, const std::string& access, const std::string& renew) { unsigned int DB::MySQL::createSession(const std::string& login, const std::string& access, const std::string& renew) {
std::string l = login, a = access, r = renew; std::string l = login, a = access, r = renew;
static std::string testingDevice("Testing..."); static std::string testingDevice("Testing...");
@ -281,7 +281,7 @@ unsigned int MySQL::createSession(const std::string& login, const std::string& a
return lastInsertedId(); return lastInsertedId();
} }
unsigned int MySQL::lastInsertedId() { unsigned int DB::MySQL::lastInsertedId() {
MYSQL* con = &connection; MYSQL* con = &connection;
int result = mysql_query(con, lastIdQuery); int result = mysql_query(con, lastIdQuery);

View File

@ -9,10 +9,11 @@
#include <mysql.h> #include <mysql.h>
#include "database/dbinterface.h" #include "database/interface.h"
#include "utils/helpers.h" #include "utils/helpers.h"
class MySQL : public DBInterface { namespace DB {
class MySQL : public Interface {
class Statement; class Statement;
class Transaction; class Transaction;
@ -51,3 +52,4 @@ struct ResDeleter {
} }
}; };
}; };
}

View File

@ -9,7 +9,7 @@
static uint64_t TIME_LENGTH = sizeof(MYSQL_TIME); static uint64_t TIME_LENGTH = sizeof(MYSQL_TIME);
MySQL::Statement::Statement(MYSQL* connection, const char* statement): DB::MySQL::Statement::Statement(MYSQL* connection, const char* statement):
stmt(mysql_stmt_init(connection)), stmt(mysql_stmt_init(connection)),
param() param()
{ {
@ -18,7 +18,7 @@ MySQL::Statement::Statement(MYSQL* connection, const char* statement):
throw std::runtime_error(std::string("Error preparing statement: ") + mysql_stmt_error(stmt.get())); throw std::runtime_error(std::string("Error preparing statement: ") + mysql_stmt_error(stmt.get()));
} }
void MySQL::Statement::bind(void* value, enum_field_types type, bool usigned) { void DB::MySQL::Statement::bind(void* value, enum_field_types type, bool usigned) {
MYSQL_BIND& result = param.emplace_back(); MYSQL_BIND& result = param.emplace_back();
std::memset(&result, 0, sizeof(result)); std::memset(&result, 0, sizeof(result));
@ -45,7 +45,7 @@ void MySQL::Statement::bind(void* value, enum_field_types type, bool usigned) {
} }
} }
void MySQL::Statement::execute() { void DB::MySQL::Statement::execute() {
MYSQL_STMT* raw = stmt.get(); MYSQL_STMT* raw = stmt.get();
int result = mysql_stmt_bind_param(raw, param.data()); int result = mysql_stmt_bind_param(raw, param.data());
if (result != 0) if (result != 0)
@ -64,7 +64,7 @@ void MySQL::Statement::execute() {
} }
} }
std::vector<std::vector<std::any>> MySQL::Statement::fetchResult() { std::vector<std::vector<std::any>> DB::MySQL::Statement::fetchResult() {
MYSQL_STMT* raw = stmt.get(); MYSQL_STMT* raw = stmt.get();
if (mysql_stmt_store_result(raw) != 0) if (mysql_stmt_store_result(raw) != 0)
throw std::runtime_error(std::string("Error fetching statement result: ") + mysql_stmt_error(raw)); //TODO not sure if it's valid here throw std::runtime_error(std::string("Error fetching statement result: ") + mysql_stmt_error(raw)); //TODO not sure if it's valid here

View File

@ -10,6 +10,7 @@
#include "mysql.h" #include "mysql.h"
namespace DB {
class MySQL::Statement { class MySQL::Statement {
struct STMTDeleter { struct STMTDeleter {
void operator () (MYSQL_STMT* stmt) { void operator () (MYSQL_STMT* stmt) {
@ -27,3 +28,4 @@ private:
std::unique_ptr<MYSQL_STMT, STMTDeleter> stmt; std::unique_ptr<MYSQL_STMT, STMTDeleter> stmt;
std::vector<MYSQL_BIND> param; std::vector<MYSQL_BIND> param;
}; };
}

View File

@ -3,7 +3,7 @@
#include "transaction.h" #include "transaction.h"
MySQL::Transaction::Transaction(MYSQL* connection): DB::MySQL::Transaction::Transaction(MYSQL* connection):
con(connection), con(connection),
opened(false) opened(false)
{ {
@ -13,12 +13,12 @@ MySQL::Transaction::Transaction(MYSQL* connection):
opened = true; opened = true;
} }
MySQL::Transaction::~Transaction() { DB::MySQL::Transaction::~Transaction() {
if (opened) if (opened)
abort(); abort();
} }
void MySQL::Transaction::commit() { void DB::MySQL::Transaction::commit() {
if (mysql_commit(con) != 0) if (mysql_commit(con) != 0)
throw std::runtime_error(std::string("Failed to commit transaction") + mysql_error(con)); throw std::runtime_error(std::string("Failed to commit transaction") + mysql_error(con));
@ -27,7 +27,7 @@ void MySQL::Transaction::commit() {
throw std::runtime_error(std::string("Failed to return autocommit") + mysql_error(con)); throw std::runtime_error(std::string("Failed to return autocommit") + mysql_error(con));
} }
void MySQL::Transaction::abort() { void DB::MySQL::Transaction::abort() {
opened = false; opened = false;
if (mysql_rollback(con) != 0) if (mysql_rollback(con) != 0)
throw std::runtime_error(std::string("Failed to rollback transaction") + mysql_error(con)); throw std::runtime_error(std::string("Failed to rollback transaction") + mysql_error(con));

View File

@ -5,6 +5,7 @@
#include "mysql.h" #include "mysql.h"
namespace DB {
class MySQL::Transaction { class MySQL::Transaction {
public: public:
Transaction(MYSQL* connection); Transaction(MYSQL* connection);
@ -17,3 +18,4 @@ private:
MYSQL* con; MYSQL* con;
bool opened; bool opened;
}; };
}

57
database/pool.cpp Normal file
View File

@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "pool.h"
DB::Pool::Pool (Private):
std::enable_shared_from_this<Pool>(),
mutex(),
conditional(),
interfaces()
{}
DB::Pool::~Pool () {
}
std::shared_ptr<DB::Pool> DB::Pool::create () {
return std::make_shared<Pool>(Private());
}
void DB::Pool::addInterfaces (
Interface::Type type,
std::size_t amount,
const std::string & login,
const std::string & password,
const std::string & database,
const std::string& path
) {
std::unique_lock lock(mutex);
for (std::size_t i = 0; i < amount; ++i) {
const std::unique_ptr<Interface>& ref = interfaces.emplace(Interface::create(type));
ref->setCredentials(login, password);
ref->setDatabase(database);
ref->connect(path);
}
lock.unlock();
conditional.notify_all();
}
DB::Resource DB::Pool::request () {
std::unique_lock lock(mutex);
while (interfaces.empty())
conditional.wait(lock);
std::unique_ptr<Interface> interface = std::move(interfaces.front());
interfaces.pop();
return Resource(std::move(interface), shared_from_this());
}
void DB::Pool::free (std::unique_ptr<Interface> interface) {
std::unique_lock lock(mutex);
interfaces.push(std::move(interface));
lock.unlock();
conditional.notify_one();
}

47
database/pool.h Normal file
View File

@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <string>
#include <memory>
#include <queue>
#include <mutex>
#include <condition_variable>
#include "interface.h"
#include "resource.h"
namespace DB {
class Pool : public std::enable_shared_from_this<Pool> {
struct Private {};
friend class Resource;
void free(std::unique_ptr<Interface> interface);
public:
Pool(Private);
Pool(const Pool&) = delete;
Pool(Pool&&) = delete;
~Pool();
Pool& operator = (const Pool&) = delete;
Pool& operator = (Pool&&) = delete;
static std::shared_ptr<Pool> create();
Resource request();
void addInterfaces(
Interface::Type type,
std::size_t amount,
const std::string& login,
const std::string& password,
const std::string& database,
const std::string& path
);
private:
std::mutex mutex;
std::condition_variable conditional;
std::queue<std::unique_ptr<Interface>> interfaces;
};
}

38
database/resource.cpp Normal file
View File

@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "resource.h"
#include "pool.h"
DB::Resource::Resource (
std::unique_ptr<Interface> interface,
std::weak_ptr<Pool> parent
):
parent(parent),
interface(std::move(interface))
{}
DB::Resource::Resource(Resource&& other):
parent(other.parent),
interface(std::move(other.interface))
{}
DB::Resource::~Resource() {
if (!interface)
return;
if (std::shared_ptr<Pool> p = parent.lock())
p->free(std::move(interface));
}
DB::Resource& DB::Resource::operator = (Resource&& other) {
parent = other.parent;
interface = std::move(other.interface);
return *this;
}
DB::Interface* DB::Resource::operator -> () {
return interface.get();
}

31
database/resource.h Normal file
View File

@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <memory>
#include "interface.h"
namespace DB {
class Pool;
class Resource {
friend class Pool;
Resource(std::unique_ptr<Interface> interface, std::weak_ptr<Pool> parent);
public:
Resource(const Resource&) = delete;
Resource(Resource&& other);
~Resource();
Resource& operator = (const Resource&) = delete;
Resource& operator = (Resource&& other);
Interface* operator -> ();
private:
std::weak_ptr<Pool> parent;
std::unique_ptr<Interface> interface;
};
}

View File

@ -32,7 +32,7 @@ void Handler::Login::handle(Request& request) {
bool success = false; bool success = false;
try { try {
success = server->validatePassword(login, password); success = server->validatePassword(login, password);
} catch (const DBInterface::NoLogin& e) { } catch (const DB::NoLogin& e) {
std::cerr << "Exception on logging in:\n\t" << e.what() << std::endl; std::cerr << "Exception on logging in:\n\t" << e.what() << std::endl;
return error(request, Result::wrongCredentials, Response::Status::badRequest); return error(request, Result::wrongCredentials, Response::Status::badRequest);
} catch (const std::exception& e) { } catch (const std::exception& e) {

View File

@ -35,7 +35,7 @@ void Handler::Register::handle(Request& request) {
try { try {
server->registerAccount(login, password); server->registerAccount(login, password);
} catch (const DBInterface::DuplicateLogin& e) { } catch (const DB::DuplicateLogin& e) {
std::cerr << "Exception on registration:\n\t" << e.what() << std::endl; std::cerr << "Exception on registration:\n\t" << e.what() << std::endl;
return error(request, Result::loginExists, Response::Status::conflict); return error(request, Result::loginExists, Response::Status::conflict);
} catch (const std::exception& e) { } catch (const std::exception& e) {

View File

@ -1,10 +1,13 @@
set(HEADERS set(HEADERS
request.h request.h
redirect.h
redirectable.h redirectable.h
) )
set(SOURCES set(SOURCES
request.cpp request.cpp
redirect.cpp
) )
target_sources(pica PRIVATE ${SOURCES}) target_sources(pica PRIVATE ${SOURCES})

View File

@ -9,5 +9,6 @@
class Accepting { class Accepting {
public: public:
virtual ~Accepting() {};
virtual void accept(std::unique_ptr<Request> request) = 0; virtual void accept(std::unique_ptr<Request> request) = 0;
}; };

View File

@ -13,6 +13,11 @@
#include "handler/login.h" #include "handler/login.h"
constexpr const char* pepper = "well, not much of a secret, huh?"; constexpr const char* pepper = "well, not much of a secret, huh?";
constexpr const char* dbLogin = "pica";
constexpr const char* dbPassword = "pica";
constexpr const char* dbName = "pica";
constexpr const char* dbPath = "/run/mysqld/mysqld.sock";
constexpr uint8_t dbConnectionsCount = 4;
constexpr const char* randomChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; constexpr const char* randomChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
constexpr uint8_t saltSize = 16; constexpr uint8_t saltSize = 16;
@ -28,18 +33,22 @@ Server::Server():
requestCount(0), requestCount(0),
serverName(std::nullopt), serverName(std::nullopt),
router(), router(),
db(), pool(DB::Pool::create()),
sessions() sessions()
{ {
std::cout << "Startig pica..." << std::endl; std::cout << "Startig pica..." << std::endl;
db = DBInterface::create(DBInterface::Type::mysql);
std::cout << "Database type: MySQL" << std::endl; std::cout << "Database type: MySQL" << std::endl;
pool->addInterfaces(
DB::Interface::Type::mysql,
dbConnectionsCount,
dbLogin,
dbPassword,
dbName,
dbPath
);
db->setCredentials("pica", "pica"); DB::Resource db = pool->request();
db->setDatabase("pica");
db->connect("/run/mysqld/mysqld.sock");
db->migrate(currentDbVesion); db->migrate(currentDbVesion);
router.addRoute(std::make_unique<Handler::Info>()); router.addRoute(std::make_unique<Handler::Info>());
@ -112,10 +121,12 @@ unsigned int Server::registerAccount(const std::string& login, const std::string
if (result != ARGON2_OK) if (result != ARGON2_OK)
throw std::runtime_error(std::string("Hashing failed: ") + argon2_error_message(result)); throw std::runtime_error(std::string("Hashing failed: ") + argon2_error_message(result));
DB::Resource db = pool->request();
return db->registerAccount(login, hash); return db->registerAccount(login, hash);
} }
bool Server::validatePassword(const std::string& login, const std::string& password) { bool Server::validatePassword(const std::string& login, const std::string& password) {
DB::Resource db = pool->request();
std::string hash = db->getAccountHash(login); std::string hash = db->getAccountHash(login);
std::string spiced = password + pepper; std::string spiced = password + pepper;
@ -139,9 +150,10 @@ Session& Server::openSession(const std::string& login) {
try { try {
accessToken = generateRandomString(32); accessToken = generateRandomString(32);
renewToken = generateRandomString(32); renewToken = generateRandomString(32);
DB::Resource db = pool->request();
sessionId = db->createSession(login, accessToken, renewToken); sessionId = db->createSession(login, accessToken, renewToken);
break; break;
} catch (const DBInterface::Duplicate& e) { } catch (const DB::Duplicate& e) {
std::cout << "Duplicate on creating session, trying again with different tokens"; std::cout << "Duplicate on creating session, trying again with different tokens";
} }
} while (--counter != 0); } while (--counter != 0);

View File

@ -22,7 +22,7 @@
#include "response/response.h" #include "response/response.h"
#include "router.h" #include "router.h"
#include "session.h" #include "session.h"
#include "database/dbinterface.h" #include "database/pool.h"
#include "utils/helpers.h" #include "utils/helpers.h"
#include "config.h" #include "config.h"
@ -49,6 +49,6 @@ private:
uint64_t requestCount; uint64_t requestCount;
std::optional<std::string> serverName; std::optional<std::string> serverName;
Router router; Router router;
std::unique_ptr<DBInterface> db; std::shared_ptr<DB::Pool> pool;
Sessions sessions; Sessions sessions;
}; };

View File

@ -10,6 +10,10 @@
class Session : public Accepting { class Session : public Accepting {
public: public:
Session(unsigned int id, const std::string& access, const std::string& renew); Session(unsigned int id, const std::string& access, const std::string& renew);
Session(const Session&) = delete;
Session(Session&& other);
Session& operator = (const Session&) = delete;
Session& operator = (Session&& other);
std::string getAccessToken() const; std::string getAccessToken() const;
std::string getRenewToken() const; std::string getRenewToken() const;