Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add communication of player accounts between frontend and backend #32

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
[submodule "3rdparty/soci"]
path = 3rdparty/soci
url = https://github.com/SOCI/soci.git
[submodule "3rdparty/openssl"]
path = 3rdparty/openssl
url = https://github.com/openssl/openssl
15 changes: 15 additions & 0 deletions 3rdparty/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# CMake settings and includes
include(ExternalProject)

# Disable clang-tidy for 3rdparty directories
set(CMAKE_CXX_CLANG_TIDY "")

Expand All @@ -6,3 +9,15 @@ add_subdirectory(${THIRDPARTY_DIR}/SDL)
add_subdirectory(${THIRDPARTY_DIR}/libconfig)
add_subdirectory(${THIRDPARTY_DIR}/spdlog)
add_subdirectory(${THIRDPARTY_DIR}/soci)

# OpenSSL
find_program(MAKE_EXECUTABLE NAMES gmake make mingw32-make REQUIRED)
set(openssl_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}openssl${CMAKE_STATIC_LIBRARY_SUFFIX})

ExternalProject_Add(openssl
SOURCE_DIR ${THIRDPARTY_DIR}/openssl
UPDATE_DISCONNECTED true
CONFIGURE_COMMAND "${THIRDPARTY_DIR}/openssl/Configure"
BUILD_COMMAND ${MAKE_EXECUTABLE} -j
INSTALL_COMMAND ${MAKE_EXECUTABLE} -j DESTDIR="${CMAKE_BINARY_DIR}/openssl-build" install
BUILD_BYPRODUCTS ${openssl_LIBRARY})
1 change: 1 addition & 0 deletions 3rdparty/openssl
Submodule openssl added at 1d1537
12 changes: 8 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ set(THIRDPARTY_DIR ${PROJECT_SOURCE_DIR}/3rdparty)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

# clang settings
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-fuchsia-default-arguments-calls,-fuchsia-statically-constructed-objects")
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-fuchsia-default-arguments-calls,-fuchsia-statically-constructed-objects,-cert-err58-cpp")

# Project subdirectories
add_subdirectory("docs")
Expand Down Expand Up @@ -57,10 +57,12 @@ include_directories(
${THIRDPARTY_DIR}/spdlog/include
${THIRDPARTY_DIR}/soci/include
${CMAKE_BINARY_DIR}/3rdparty/soci/include
${CMAKE_BINARY_DIR}/include)
${CMAKE_BINARY_DIR}/include
${CMAKE_BINARY_DIR}/openssl-build/usr/local/include)

link_directories(
${CMAKE_BINARY_DIR}/lib)
${CMAKE_BINARY_DIR}/lib
${CMAKE_BINARY_DIR}/openssl-build/usr/local/lib64)

add_library(imgui
${THIRDPARTY_DIR}/imgui/imgui.cpp
Expand All @@ -76,6 +78,7 @@ add_library(${PROJECT_NAME}
add_executable(${PROJECT_NAME}-bin
src/main.cpp
src/althack/main_window.cpp
src/althack/crypto_service.cpp
src/althack/frontend.cpp
src/althack/backend.cpp
src/althack/backends/server_backend.cpp
Expand All @@ -90,7 +93,8 @@ target_link_libraries(${PROJECT_NAME}
config++
soci_core
soci_sqlite3
dl)
dl
crypto)

target_link_libraries(${PROJECT_NAME}-bin
${PROJECT_NAME})
2 changes: 2 additions & 0 deletions include/althack/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Backend {
public:
Backend(const std::string& identifier);

virtual ~Backend() = default;

const std::string& getIdentifier() const;

virtual void step() = 0;
Expand Down
1 change: 1 addition & 0 deletions include/althack/backends/server_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

// AltHack
#include <althack/backend.hpp>
#include <althack/crypto_service.hpp>
#include <althack/database.hpp>

namespace althack {
Expand Down
17 changes: 17 additions & 0 deletions include/althack/crypto_service.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef ALTHACK_CRYPTO_SERVICE_HPP_
#define ALTHACK_CRYPTO_SERVICE_HPP_

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

namespace althack {

class CryptoService {
public:
static void generateKeyPair();
};

} // namespace althack

#endif // ALTHACK_CRYPTO_SERVICE_HPP_
22 changes: 22 additions & 0 deletions include/althack/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

namespace althack {

using EntityId = long long;

//! \brief Abstract base class for persistent database classes
/*!
This base database class provides the interface for persistent data storage in server backend
Expand All @@ -18,8 +20,28 @@ class Database {
//! \brief Closes the database.
virtual bool close() = 0;

EntityId createUser(const std::string& user_name);

void deleteUser(EntityId user_id);

void setUserProperty(EntityId user_id, const std::string& key, const std::string& value);

void deleteUserProperty(EntityId user_id, const std::string& key);

protected:
static std::string getISO8601Timestamp();

virtual EntityId createEntity(const std::string& domain) = 0;

virtual void deleteEntity(EntityId entity_id) = 0;

virtual EntityId storeBlob(const std::string& value) = 0;

virtual void associateBlobProperty(
const std::string& domain, EntityId blob_id, EntityId entity_id, const std::string& key) = 0;

virtual void deleteBlobProperty(
const std::string& domain, EntityId entity_id, const std::string& key) = 0;
};

} // namespace althack
Expand Down
13 changes: 13 additions & 0 deletions include/althack/databases/soci_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ class SociDatabase : public Database {
bool close() override;

private:
EntityId createEntity(const std::string& domain) override;

void deleteEntity(EntityId entity_id) override;

EntityId storeBlob(const std::string& value) override;

void associateBlobProperty(
const std::string& domain, EntityId blob_id, EntityId entity_id,
const std::string& key) override;

void deleteBlobProperty(
const std::string& domain, EntityId entity_id, const std::string& key) override;

//! \brief The database session to use.
soci::session session_;
//! \brief The database file to use.
Expand Down
3 changes: 3 additions & 0 deletions include/althack/frontend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

// Althack
#include <althack/backend.hpp>
#include <althack/crypto_service.hpp>

namespace althack {

Expand All @@ -17,6 +18,8 @@ class Frontend {

const std::list<visuals::AccountNode> getAccounts();

bool createAccount(const std::string& username);

private:
std::shared_ptr<Backend> backend_;
};
Expand Down
8 changes: 2 additions & 6 deletions src/althack/althack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ bool AltHack::setup() {
return false;
}

// TODO: Decide how server/client backend is determined.
// TODO(fairlight1337): Decide how server/client backend is determined.
backend_ = std::make_shared<backends::ServerBackend>("database.db");
frontend_.connect(backend_);

Expand Down Expand Up @@ -79,11 +79,7 @@ void AltHack::stop() {
}

bool AltHack::teardown() {
if (!headless_ && !main_window_.teardown()) {
return false;
}

return true;
return !headless_ && !main_window_.teardown();
}

std::string AltHack::getVersion() {
Expand Down
9 changes: 9 additions & 0 deletions src/althack/crypto_service.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <althack/crypto_service.hpp>

namespace althack {

void CryptoService::generateKeyPair() {
// TODO(fairlight1337): Implement keypair generation here.
}

} // namespace althack
26 changes: 26 additions & 0 deletions src/althack/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@

namespace althack {

namespace {
//! \brief The database domain for user account related data.
const std::string DB_ENTITY_DOMAIN_USER = "user";
//! \brief The database user account property key for usernames.
const std::string DB_USER_PROPERTY_USERNAME = "name";
} // namespace

EntityId Database::createUser(const std::string& user_name) {
const EntityId user_id = createEntity(DB_ENTITY_DOMAIN_USER);
setUserProperty(user_id, DB_USER_PROPERTY_USERNAME, user_name);
return user_id;
}

void Database::deleteUser(EntityId user_id) {
deleteEntity(user_id);
}

void Database::setUserProperty(EntityId user_id, const std::string& key, const std::string& value) {
const EntityId blob_id = storeBlob(value);
associateBlobProperty(DB_ENTITY_DOMAIN_USER, blob_id, user_id, key);
}

void Database::deleteUserProperty(EntityId user_id, const std::string& key) {
deleteBlobProperty(DB_ENTITY_DOMAIN_USER, user_id, key);
}

std::string Database::getISO8601Timestamp() {
const auto now = std::chrono::system_clock::now();
const std::time_t time = std::chrono::system_clock::to_time_t(now);
Expand Down
56 changes: 50 additions & 6 deletions src/althack/databases/soci_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ bool SociDatabase::open() {
session_.open(soci::sqlite3, database_file_);

if (!exists) {
// Create users table
session_ << "CREATE TABLE users ("
<< "user_id INTEGER PRIMARY KEY AUTOINCREMENT, "
<< "password_hash VARCHAR(64) NOT NULL, "
<< "user_name VARCHAR(255) NOT NULL"
// Create entities table
session_ << "CREATE TABLE entities ("
<< "entity_id INTEGER PRIMARY KEY AUTOINCREMENT, "
<< "domain VARCHAR(255) NOT NULL"
<< ")";
// Create blob storage table
session_ << "CREATE TABLE blobs (blob_id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)";
// Create blob association table
session_ << "CREATE TABLE blobs_entities ("
<< "domain VARCHAR(255) NOT NULL, "
<< "blob_id INTEGER NOT NULL, "
<< "entity_id INTEGER NOT NULL, "
<< "key VARCHAR(255) NOT NULL"
<< ")";
// Create stats table
session_ << "CREATE TABLE stats ("
Expand All @@ -29,7 +37,7 @@ bool SociDatabase::open() {
<< ")";

// Insert initial data
session_ << "INSERT INTO users(user_name, password_hash) VALUES('admin', 'somehash')";
session_ << "INSERT INTO users(user_name) VALUES('admin', 'somehash')";
session_ << "INSERT INTO stats VALUES('created_at', '" << getISO8601Timestamp() << "')";
}

Expand All @@ -40,6 +48,42 @@ bool SociDatabase::close() {
session_.close();
return true;
}

EntityId SociDatabase::createEntity(const std::string& domain) {
session_ << "INSERT INTO entities(domain) VALUES(" << domain << ")";
EntityId id = 0;
if (!session_.get_last_insert_id("entities", id)) {
throw std::runtime_error("Failed to get entities last inserted id");
}
return id;
}

void SociDatabase::deleteEntity(EntityId entity_id) {
// Delete all blobs related to the entity to delete
session_ << "DELETE b FROM blobs b JOIN blobs_entities b_e ON b.blob_id = b_e.blob_id WHERE b_e.entity_id = " << entity_id;
// Delete all the blob/entity associations of the entity to delete
session_ << "DELETE FROM blobs_entities WHERE entity_id = " << entity_id;
// Delete the actual entity to delete
session_ << "DELETE FROM entities WHERE entity_id = " << entity_id;
}

EntityId SociDatabase::storeBlob(const std::string& value) {
session_ << "INSERT INTO blobs(value) VALUES(" << value << ")";
EntityId id = 0;
if (!session_.get_last_insert_id("blobs", id)) {
throw std::runtime_error("Failed to get blobs last inserted id");
}
return id;
}

void SociDatabase::associateBlobProperty(const std::string& domain, EntityId blob_id, EntityId entity_id, const std::string& key) {
session_ << "INSERT INTO blobs_entities(domain, blob_id, entity_id, key) VALUES(" << domain << ", " << blob_id << ", " << entity_id << ", " << key << ")";
}

void SociDatabase::deleteBlobProperty(const std::string& domain, EntityId entity_id, const std::string& key) {
session_ << "DELETE b FROM blobs b JOIN blobs_entities b_e ON b.blob_id = b_e.blob_id WHERE b_e.entity_id = " << entity_id << " AND b_e.key = " << key << " AND b_e.domain = " << domain;
session_ << "DELETE FROM blobs_entities WHERE domain = " << domain << " AND entity_id = " << entity_id << " AND key = " << key;
}

} // namespace databases
} // namespace althack
4 changes: 4 additions & 0 deletions src/althack/frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ void Frontend::step() {
// TOOD: Implement frontend cycle work.
}

bool Frontend::createAccount(const std::string& username) {
CryptoService::generateKeyPair();
}

const std::list<visuals::AccountNode> Frontend::getAccounts() {
return backend_->getAccounts();
}
Expand Down