bettola/common/src/db/database_manager.cpp

113 lines
3.8 KiB
C++

#include "database_manager.h"
#include "vfs.h"
DatabaseManager::DatabaseManager(const std::string& db_path) : _db(db_path) {
/* db is opened in the construtor's init list. */
}
DatabaseManager::~DatabaseManager(void) {
/* db is auto closed when _db goes out of scope. */
}
void DatabaseManager::init(void) {
_db << "CREATE TABLE IF NOT EXISTS players("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"username TEXT NOT NULL UNIQUE,"
"password TEXT NOT NULL,"
"hostname TEXT NOT NULL,"
"home_machine_id INTEGER"
");";
_db << "CREATE TABLE IF NOT EXISTS machines ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"owner_id INTEGER,"
"hostname TEXT NOT NULL,"
"ip_address TEXT NOT NULL UNIQUE"
");";
_db << "CREATE TABLE IF NOT EXISTS vfs_nodes ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"machine_id INTEGER NOT NULL,"
"parent_id INTEGER,"
"name TEXT NOT NULL,"
"type INTEGER NOT NULL,"
"content TEXT"
");";
}
bool DatabaseManager::create_player(const std::string& username, const std::string& password,
const std::string& hostname, vfs_node* vfs_template) {
long long player_id = 0;
long long machine_id = 0;
try {
_db << "BEGIN;";
/* Create the player. */
_db << "INSERT INTO players (username, password, hostname) VALUES (?, ?, ?);"
<< username
<< password
<< hostname;
player_id = _db.last_insert_rowid();
/* Create the home machine. */
/* TODO: Implement real IP allication. */
std::string ip_address = "192.168.1." + std::to_string(player_id);
_db << "INSERT INTO machines (owner_id, hostname, ip_address) VALUES (?, ?, ?);"
<< player_id << hostname << ip_address;
machine_id = _db.last_insert_rowid();
/* Link player to their new machine. */
_db << "UPDATE players SET home_machine_id = ? WHERE id = ?;"
<< machine_id << player_id;
/* Create the root dir for the new machine's VFS. */
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES(?, NULL, ?, 1);"
<< machine_id << "/";
long long root_id = _db.last_insert_rowid();
/* Create default subdirs. */
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);"
<< machine_id << root_id << "home";
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);"
<< machine_id << root_id << "etc";
/* Create /bing and get it's ID */
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES(?, ?, ?, 1);"
<< machine_id << root_id << "bin";
long long bin_id = _db.last_insert_rowid();
/* Copy scripts from template into new machine's /bin */
vfs_node* template_bin = vfs_template->children["bin"];
for(auto const& [name, node] : template_bin->children) {
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type, content) "
"VALUES (?, ?, ?, ?, ?);"
<< machine_id << bin_id << name << FILE_NODE <<node->content;
}
_db << "COMMIT";
} catch(const std::exception& e) {
_db << "ROLLBACK;"; /* Ensure atomicity. */
return false;
}
return true;
}
bool DatabaseManager::auth_player(const std::string& username, const std::string& password) {
bool authed = false;
_db << "SELECT id FROM players WHERE username = ? AND password = ?;"
<< username
<< password
>> [&](long long id) { authed = true; };
return authed;
}
long long DatabaseManager::get_player_home_machine_id(const std::string& username) {
long long machine_id = -1; /* Return -1 if not found. */
_db << "SELECT home_machine_id FROM players WHERE username = ?;"
<< username
>> machine_id;
return machine_id;
}