Skip to content

Commit

Permalink
Set up SQLite
Browse files Browse the repository at this point in the history
  • Loading branch information
LunarWatcher committed Sep 2, 2024
1 parent 4a47ec3 commit 82f54df
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 42 deletions.
35 changes: 15 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,12 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(SPDLOG_FMT_EXTERNAL ON CACHE STRING "" FORCE)
# TODO: Disable this and use system curl. WE're already using system openssl
set(CURL_ZLIB ON CACHE STRING "" FORCE)
set(SQLITECPP_RUN_CPPLINT OFF CACHE STRING "" FORCE)

set(CROW_FEATURES ssl compression CACHE STRING "" FORCE)
set(CROW_INSTALL OFF CACHE STRING "" FORCE)

include (FetchContent)

# This has to be sourced from github because the apt version is grossly out of date,
# and doesn't support std::optional out of the box :facedesk:
FetchContent_Declare(pqxx
GIT_REPOSITORY https://github.com/jtv/libpqxx
GIT_TAG 7.9.2
EXCLUDE_FROM_ALL
)
FetchContent_Declare(crowcpp
GIT_REPOSITORY https://github.com/CrowCpp/Crow
GIT_TAG v1.2.0
Expand Down Expand Up @@ -67,19 +60,21 @@ FetchContent_Declare(cli11
GIT_REPOSITORY https://github.com/CLIUtils/CLI11
GIT_TAG v2.4.2
)
FetchContent_Declare(sqlitecpp
GIT_REPOSITORY https://github.com/SRombauts/SQLiteCpp
GIT_TAG 3.3.2
)

# Must be included before asio [not currently applicable, as asio is an external system dependency now]

# This is overkill, but I'm copying all of this in from a now dead project also based around crowcpp,
# so I'll deal with this when I'm awake
FetchContent_MakeAvailable(crowcpp)
FetchContent_MakeAvailable(pqxx)
FetchContent_MakeAvailable(nlohmann)
FetchContent_MakeAvailable(fmt)
FetchContent_MakeAvailable(spdlog)
FetchContent_MakeAvailable(cpr)
FetchContent_MakeAvailable(stc)
FetchContent_MakeAvailable(cli11)
FetchContent_MakeAvailable(
crowcpp
sqlitecpp
nlohmann
fmt
spdlog
cpr
stc
cli11
)

if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAZEL_DEBUG")
Expand Down
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
# hazel


Internal metaserver for my homelab. It's going to be a while before it's generally usable by anyone else, so the docs are going to be thin for the near foreseeable future.
Internal metaserver for my homelab. It's going to be a while before it's generally usable by anyone else, so the docs are going to be thin for the near foreseeable future, and stuff will be ugly, broken, or both.

The entire theme is scope creep, so Hazel is designed for a lot of random shit I need, but don't feel like making an entire dedicated project for. Some planned ideas include:

* The obligatory link dashboard
* Status monitoring
* The obligatory real-time (ish) overview
* Practical monitoring of stuff like miniflux unreads
* System information
* Service information
* Long-running job tracking (with NTFY integration for failure or completion)
* Automation with scripting for easier expansion

The overall goal of the project is primarily to join together other self-hosted services, and to implement a few things from scratch. But for the most part, where possible, main functionality is deferred to other (primarily self-hosted) services, with Hazel serving as an aggregator.

## Requirements

* A Linux-based server
* C++20 compiler
* CMake 3.28 (Pro tip: [CMake is available via pip](https://pypi.org/project/cmake/))
* libpq-dev, uuid-dev, libasio-dev (Debian-based names; look up your distro's package manager for the applicable packages). Additional dependencies are sourced automagically during the build process
* Postgresql
* uuid-dev, libasio-dev (Debian-based names; look up your distro's package manager for the applicable packages). Additional dependencies are sourced automagically during the build process

Docker is not supported, because it's annoying to work with and in this case, there's absolutely 0 advantages to supporting it.
6 changes: 5 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ set (SOURCE_FILES
hazel/data/DashboardDataProvider.cpp
hazel/data/dashboard/DashboardUpdaters.cpp

# Database shit
hazel/data/Database.cpp
hazel/data/db/Migration.cpp

# Server (just the core shit)
hazel/server/Hazel.cpp
)
Expand All @@ -40,7 +44,7 @@ target_link_libraries(hazelsrc
Crow::Crow
${UUID_LIB}
OpenSSL::Crypto
pqxx
SQLiteCpp
)
target_link_libraries(hazel hazelsrc)

Expand Down
38 changes: 38 additions & 0 deletions src/hazel/data/Database.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "Database.hpp"
#include "SQLiteCpp/Database.h"

#include "db/Migration.hpp"

namespace hazel {

Database::Database(const std::filesystem::path& dbPath)
: db(
SQLite::Database(
dbPath.string().c_str(),
SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE
)
)
{

}

void Database::initDatabase() {

this->db.write([](auto& sdb) {
Migration::prepMetatables(sdb);

Migration m;
m.pushVersion(R"(
CREATE TABLE Users (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Username TEXT,
Password TEXT,
IsAdmin BOOLEAN
);
)")
.exec(sdb);

});
}

}
25 changes: 25 additions & 0 deletions src/hazel/data/Database.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "SQLiteCpp/Database.h"
#include "hazel/sync/RWContainer.hpp"
#include <SQLiteCpp/SQLiteCpp.h>
#include <filesystem>
#include <shared_mutex>

namespace hazel {

class Database {
private:
RWContainer<SQLite::Database> db;

public:
Database(const std::filesystem::path& dbPath);
void initDatabase();

RWContainer<SQLite::Database>* operator->() {
return &db;
}

};

}
42 changes: 42 additions & 0 deletions src/hazel/data/config/Admin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <string>
#include <map>

namespace hazel {

namespace Modules {

#define E2S(en) {#en, en}
#define S2E(en) {en, #en}
enum Modules {
AUTOMATION,
LINKS
};


const static std::map<std::string, Modules> stringModuleMap {
E2S(AUTOMATION),
E2S(LINKS)
};

const static std::map<Modules, std::string> moduleStringMap {
S2E(AUTOMATION),
S2E(LINKS)
};

#undef E2S
#undef S2E
}

struct EnabledModules {
Modules::Modules moduleIdentifier;
bool enabled;
};

struct GlobalAdminConfig {
bool allowAccountCreation;

};

}
17 changes: 17 additions & 0 deletions src/hazel/data/config/User.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <string>

namespace hazel {

struct User {
long long userId;

std::string username;
std::string password;

bool isAdmin;

};

}
84 changes: 84 additions & 0 deletions src/hazel/data/db/Migration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "Migration.hpp"
#include "SQLiteCpp/Statement.h"
#include "SQLiteCpp/Transaction.h"

#include <hazel/data/Database.hpp>

#include <spdlog/spdlog.h>
#include <stdexcept>

namespace hazel {

Migration& Migration::pushVersion(const std::string &query) {
this->queries.push_back(query);

return *this;
}

void Migration::exec(SQLite::Database& db) {
SQLite::Transaction tx(db);

SQLite::Statement stmt(db, R"(
SELECT Version FROM Migrations WHERE Name = 'Version'
)");

int64_t headVersion = 0;
if (stmt.executeStep()) {
headVersion = stmt.getColumn(0).getInt64();
}

if (headVersion < 0) {
spdlog::error(
"The Migrations table has been tampered with. Cannot resolve the current database state. "
"If you've fucked around with the Migrations table, first, why? Second, this is not a bug. "
"You have to purge your entire database. If you haven't, please open a bug report. This should not normally "
"happen, unless you've done something weird to the database."
);
tx.rollback();
throw std::runtime_error("Database fucked");
}

if (headVersion < (int64_t) this->queries.size() + versionOffset) {
spdlog::info("Database out of date (current version: {}, new version: {})", headVersion, queries.size());
for (size_t i = headVersion - versionOffset; i < queries.size(); ++i) {
spdlog::info("Updating to v{}", i + 1 + versionOffset);
db.exec(queries.at(i + versionOffset));
}

SQLite::Statement stmt(db, R"(
INSERT OR REPLACE INTO Migrations (Name, Version)
VALUES
('Version', ?)
)");
stmt.bind(1, int64_t(queries.size()) + versionOffset);

if (stmt.exec() == 0) {
tx.rollback();
spdlog::error("Failed to upgrade database");
throw std::runtime_error("Migration error");
}

spdlog::info("Update successful.");

} else {
spdlog::info("Database up-to-date (version: {})", headVersion);
}



tx.commit();
}

void Migration::prepMetatables(SQLite::Database& db) {
spdlog::info("Initialising migration table...");
SQLite::Transaction tx(db);
db.exec(R"(
CREATE TABLE IF NOT EXISTS Migrations (
Name TEXT PRIMARY KEY,
Version INTEGER NOT NULL
);
)");
tx.commit();
}

}
36 changes: 36 additions & 0 deletions src/hazel/data/db/Migration.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "SQLiteCpp/Database.h"
#include <string>
#include <vector>

namespace hazel {

/**
* Note: this is just a version control wrapper. The queries and migration controls are still
* manually managed. This is so I don't have to spend an eterity writng this clusterfuck,
* because there are an extreme number of edge-cases in migrations. There's defaults to consider when
* rows are added to an existing table, different col types, etc. It's far easier to build
* it for just query versioning.
*/
class Migration {
private:
std::vector<std::string> queries;

/**
* Used to provide an offset to the versions
*
* This is currently not possible to set anywhere,
* and is kept purely for a hypothetical future
* scenario, because why the fuck not? Let's
* overengineer this class :D
*/
constexpr static int64_t versionOffset = 0;
public:
Migration() {}

Migration& pushVersion(const std::string& query);
void exec(SQLite::Database& db);

static void prepMetatables(SQLite::Database& db);

};
}
17 changes: 17 additions & 0 deletions src/hazel/features/webcore/DashboardModule.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "crow/mustache.h"
namespace hazel {

class DashboardModule {
public:
virtual ~DashboardModule() = default;
virtual void makeEndpoints() = 0;

virtual void render(crow::mustache::context& ctx) = 0;

virtual bool isConfigAdminOnly() = 0;
virtual bool isModulePublic() = 0;
};

}
Loading

0 comments on commit 82f54df

Please sign in to comment.