#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 <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; }