first what so ever registration

This commit is contained in:
Blue 2023-12-20 19:42:13 -03:00
parent 0c50cfa639
commit 99a9fd507e
Signed by: blue
GPG key ID: 9B203B252A63EE38
17 changed files with 285 additions and 25 deletions

View file

@ -1,11 +1,13 @@
set(HEADERS
mysql.h
statement.h
transaction.h
)
set(SOURCES
mysql.cpp
statement.cpp
transaction.cpp
)
find_package(MariaDB REQUIRED)

View file

@ -9,8 +9,13 @@
#include "mysqld_error.h"
#include "statement.h"
#include "transaction.h"
constexpr const char* versionQuery = "SELECT value FROM system WHERE `key` = 'version'";
constexpr const char* updateQuery = "UPDATE system SET `value` = ? WHERE `key` = 'version'";
constexpr const char* registerQuery = "INSERT INTO accounts (`login`, `type`, `password`) VALUES (?, 1, ?)";
constexpr const char* lastIdQuery = "SELECT LAST_INSERT_ID() AS id";
constexpr const char* assignRoleQuery = "INSERT INTO roleBindings (`account`, `role`) SELECT ?, roles.id FROM roles WHERE roles.name = ?";
static const std::filesystem::path buildSQLPath = "database";
@ -34,7 +39,6 @@ MySQL::~MySQL() {
mysql_close(&connection);
}
void MySQL::connect(const std::string& path) {
if (state != State::disconnected)
return;
@ -138,7 +142,7 @@ void MySQL::executeFile(const std::filesystem::path& relativePath) {
uint8_t MySQL::getVersion() {
MYSQL* con = &connection;
int result = mysql_query(con, "SELECT value FROM system WHERE `key` = 'version'");
int result = mysql_query(con, versionQuery);
if (result != 0) {
unsigned int errcode = mysql_errno(con);
@ -216,3 +220,48 @@ std::optional<std::string> MySQL::getComment(std::string& string) {
return std::nullopt;
}
unsigned int MySQL::registerAccount(const std::string& login, const std::string& hash) {
//TODO validate filed lengths!
MYSQL* con = &connection;
MySQL::Transaction txn(con);
Statement addAcc(con, registerQuery);
std::string l = login; //I hate copying just to please this horible API
std::string h = hash;
addAcc.bind(l.data(), MYSQL_TYPE_STRING);
addAcc.bind(h.data(), MYSQL_TYPE_STRING);
addAcc.execute();
unsigned int id = lastInsertedId();
static std::string defaultRole("default");
Statement addRole(con, assignRoleQuery);
addRole.bind(&id, MYSQL_TYPE_LONG, true);
addRole.bind(defaultRole.data(), MYSQL_TYPE_STRING);
addRole.execute();
txn.commit();
return id;
}
unsigned int MySQL::lastInsertedId() {
MYSQL* con = &connection;
int result = mysql_query(con, lastIdQuery);
if (result != 0)
throw std::runtime_error(std::string("Error executing last inserted id: ") + mysql_error(con));
std::unique_ptr<MYSQL_RES, ResDeleter> res(mysql_store_result(con));
if (!res)
throw std::runtime_error(std::string("Querying last inserted id returned no result: ") + mysql_error(con));
MYSQL_ROW row = mysql_fetch_row(res.get());
if (row)
return std::stoi(row[0]);
else
throw std::runtime_error(std::string("Querying last inserted id returned no rows"));
}

View file

@ -14,6 +14,7 @@
class MySQL : public DBInterface {
class Statement;
class Transaction;
public:
MySQL();
~MySQL() override;
@ -27,9 +28,12 @@ public:
uint8_t getVersion() override;
void setVersion(uint8_t version) override;
unsigned int registerAccount(const std::string& login, const std::string& hash) override;
private:
void executeFile(const std::filesystem::path& relativePath);
static std::optional<std::string> getComment(std::string& string);
unsigned int lastInsertedId();
protected:
MYSQL connection;

View file

@ -9,15 +9,14 @@ static uint64_t TIME_LENGTH = sizeof(MYSQL_TIME);
MySQL::Statement::Statement(MYSQL* connection, const char* statement):
stmt(mysql_stmt_init(connection)),
param(),
lengths()
param()
{
int result = mysql_stmt_prepare(stmt.get(), statement, strlen(statement));
if (result != 0)
throw std::runtime_error(std::string("Error preparing statement: ") + mysql_stmt_error(stmt.get()));
}
void MySQL::Statement::bind(void* value, enum_field_types type) {
void MySQL::Statement::bind(void* value, enum_field_types type, bool usigned) {
MYSQL_BIND& result = param.emplace_back();
std::memset(&result, 0, sizeof(result));
@ -27,13 +26,18 @@ void MySQL::Statement::bind(void* value, enum_field_types type) {
switch (type) {
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
result.length = &lengths.emplace_back(strlen(static_cast<char*>(value)));
result.buffer_length = strlen(static_cast<char*>(value));
break;
case MYSQL_TYPE_DATE:
result.length = &TIME_LENGTH;
result.buffer_length = TIME_LENGTH;
break;
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_TINY:
result.is_unsigned = usigned;
break;
default:
lengths.pop_back();
throw std::runtime_error("Type: " + std::to_string(type) + " is not yet supported in bind");
break;
}

View file

@ -7,7 +7,6 @@
#include "mysql.h"
class MySQL::Statement {
struct STMTDeleter {
void operator () (MYSQL_STMT* stmt) {
@ -17,11 +16,10 @@ class MySQL::Statement {
public:
Statement(MYSQL* connection, const char* statement);
void bind(void* value, enum_field_types type);
void bind(void* value, enum_field_types type, bool usigned = false);
void execute();
private:
std::unique_ptr<MYSQL_STMT, STMTDeleter> stmt;
std::vector<MYSQL_BIND> param;
std::vector<uint64_t> lengths;
};

View file

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

View file

@ -0,0 +1,16 @@
#pragma once
#include "mysql.h"
class MySQL::Transaction {
public:
Transaction(MYSQL* connection);
~Transaction();
void commit();
void abort();
private:
MYSQL* con;
bool opened;
};