diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index fd03663..721f701 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -2,59 +2,57 @@ -
+

Login

+ + {#if error}

{error}

{/if} -
diff --git a/src/login/login.cpp b/src/login/login.cpp index 5d1cc70..852bf08 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -29,20 +29,21 @@ bool isLoggedIn(const crow::request& req) { std::optional loginUser(const std::string& username, const std::string& password) { auto user = getVerifiedUser(username, password); - if (user.has_value()) { - return sessionHandler.createSession(user.value().id); + if (user) { + return sessionHandler.createSession(user->id); } return {}; } void initLogin(crow::SimpleApp& app) { - // createUser("lukas", "Trollar4928"); + + //createUser("lukas", "Trollar4928"); CROW_ROUTE(app, "/login").methods("POST"_method) ([](const crow::request& req) { nlohmann::json body = nlohmann::json::parse(req.body); // parse JSON from HTTP body - if (!body.empty()) + if (body.empty()) return crow::response(400, "Invalid JSON"); auto usenameIt = body.find("username"); diff --git a/src/login/login.hpp b/src/login/login.hpp index ad245b4..8127a4b 100644 --- a/src/login/login.hpp +++ b/src/login/login.hpp @@ -11,15 +11,27 @@ void initLogin(crow::SimpleApp& app); bool isLoggedIn(const crow::request& req); -// lambda to be used by endpoint that requiere login +// login_required lambda that works for any handler with arbitrary args inline auto login_required = [](auto handler){ - return [handler](const crow::request& req){ + return [handler](auto&&... args) -> crow::response { + // the first argument is always crow::request + const crow::request& req = std::get<0>(std::forward_as_tuple(args...)); if (!isLoggedIn(req)) { - return crow::response(401, "Login required"); + return crow::response(401, "Login required"); + } + + // call original handler with all arguments + auto result = handler(std::forward(args)...); + + // ensure crow::response return type + if constexpr (std::is_same_v) { + return result; + } else { + return crow::response(result); } - return handler(req); }; }; + } #endif // __LOGIN_H__ \ No newline at end of file diff --git a/src/login/loginDb.cpp b/src/login/loginDb.cpp index fc939f4..48bbf29 100644 --- a/src/login/loginDb.cpp +++ b/src/login/loginDb.cpp @@ -1,8 +1,11 @@ #include "loginDb.hpp" #include "databasepool.h" +#include #include #include #include +#include + extern "C" { #include "monocypher.h" } @@ -59,8 +62,14 @@ int createUser(const std::string& username, const std::string& password){ int64_t id; auto db = dbpool.acquire(); - auto user = db->get_optional( - where(c(&User::username) == username) + for (auto &u : db->get_all()) { + if (u.username == username){ + std::cout << "WTF" << std::endl; + }; + } + + auto user = db->get_optional( + where(c(&login::User::username) == username) ); if (user.has_value()) { @@ -76,11 +85,16 @@ int createUser(const std::string& username, const std::string& password){ std::optional getUser(const std::string& username){ auto db = dbpool.acquire(); - auto user = db->get_optional( - where(c(&User::username) == username) + auto user = db->get_all( + where(c(&login::User::username) == username) ); dbpool.release(db); - return user; + + if(user.size() > 0){ + return user[0]; + } + + return {}; } std::optional getVerifiedUser(const std::string& username, const std::string& password){ @@ -88,7 +102,7 @@ std::optional getVerifiedUser(const std::string& username, const std::stri if (!user.has_value()) return {}; - if (verifyUser(user.value(), password)){ + if (verifyUser(*user, password)){ return user; } return {}; diff --git a/src/login/loginDb.hpp b/src/login/loginDb.hpp index 4719bd4..9b71980 100644 --- a/src/login/loginDb.hpp +++ b/src/login/loginDb.hpp @@ -3,7 +3,6 @@ #include #include -#include #include "json.hpp" #include "utils.hpp" namespace login diff --git a/src/main.cpp b/src/main.cpp index ea013b4..56b7cee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,38 +7,12 @@ using namespace std; -std::string read_file(const std::string& path) { - std::ifstream file(path, std::ios::binary); - if (!file) { - throw std::runtime_error("Cannot open file: " + path); - } - std::ostringstream ss; - ss << file.rdbuf(); - return ss.str(); -} - -// Simple MIME type detection -std::string get_mime_type(const std::string& path) { - if (path.ends_with(".html")) return "text/html"; - if (path.ends_with(".js")) return "text/javascript"; - if (path.ends_with(".css")) return "text/css"; - if (path.ends_with(".json")) return "application/json"; - if (path.ends_with(".svg")) return "image/svg+xml"; - if (path.ends_with(".png")) return "image/png"; - if (path.ends_with(".jpg") || path.ends_with(".jpeg")) return "image/jpeg"; - if (path.ends_with(".woff")) return "font/woff"; - if (path.ends_with(".woff2")) return "font/woff2"; - if (path.ends_with(".pdf")) return "application/pdf"; - return "application/octet-stream"; -} - int main() { crow::SimpleApp app; - const filesystem::path build_dir = "frontend/build/"; // <-- set your build folder // Root route CROW_ROUTE(app, "/")([&]() { - auto data = read_file(build_dir / "index.html"); + auto data = utils::read_file(utils::build_dir / "index.html"); return crow::response(200, "text/html", data); }); @@ -63,40 +37,19 @@ int main() { ([&](const std::string& p) { const filesystem::path assets_dir = "assets/"; // <-- set your build folder filesystem::path file_path = assets_dir / p; - - // If file exists, serve it - if (filesystem::exists(file_path)) { - auto data = read_file(file_path); - auto mime = get_mime_type(file_path.string()); - return crow::response(200, mime.c_str(), data); - } - - // SPA fallback: serve root index.html for unknown routes - filesystem::path fallback = build_dir / "index.html"; - auto data = read_file(fallback); - return crow::response(404, "text/html", data); + return utils::getFile(file_path); }); // Catch-all route for static files and SPA fallback CROW_ROUTE(app, "/") ([&](const std::string& p) { - filesystem::path file_path = build_dir / p; + filesystem::path file_path = utils::build_dir / p; // If path is a directory, serve index.html inside it if (filesystem::is_directory(file_path)) file_path /= "index.html"; - // If file exists, serve it - if (filesystem::exists(file_path)) { - auto data = read_file(file_path); - auto mime = get_mime_type(file_path.string()); - return crow::response(200, mime.c_str(), data); - } - - // SPA fallback: serve root index.html for unknown routes - filesystem::path fallback = build_dir / "index.html"; - auto data = read_file(fallback); - return crow::response(404, "text/html", data); + return utils::getFile(file_path); }); app.loglevel(crow::LogLevel::INFO); diff --git a/src/shadowrun/ShadowrunApi.cpp b/src/shadowrun/ShadowrunApi.cpp index 7f8fce6..598bdd8 100644 --- a/src/shadowrun/ShadowrunApi.cpp +++ b/src/shadowrun/ShadowrunApi.cpp @@ -26,16 +26,26 @@ static std::unordered_map parse_query_string(const std return params; } -static crow::response rsp(const std::string& msg){ - auto str = format("
" - "{}
", msg); - return crow::response{str}; -} +void initApi(crow::SimpleApp& app){ + + CROW_ROUTE(app, "/assets/shadowrun/") + ([&](const crow::request& req, const std::string& p) { + if (!login::isLoggedIn(req)) { + return crow::response(401, "Login required"); + } + + const filesystem::path assets_dir = "assets/shadowrun/"; + filesystem::path file_path = assets_dir / p; + return utils::getFile(file_path); + }); -void initApi(crow::SimpleApp& app) -{ CROW_ROUTE(app, "/api/shadowrun/characters") - ([&]() { + ([&](const crow::request& req) { + + if (!login::isLoggedIn(req)) { + return crow::response(401, "Login required"); + } + auto characters = getCharacters(); auto res = crow::response(200, utils::toJsonArray(characters)); @@ -45,6 +55,10 @@ void initApi(crow::SimpleApp& app) CROW_ROUTE(app, "/api/shadowrun/characters").methods("POST"_method) ([](const crow::request& req) { + if (!login::isLoggedIn(req)) { + return crow::response(401, "Login required"); + } + nlohmann::json data = nlohmann::json::parse(req.body); // parse JSON from HTTP body auto name = data["name"]; int id = createCharacter(name); @@ -60,7 +74,10 @@ void initApi(crow::SimpleApp& app) }); CROW_ROUTE(app, "/api/shadowrun/characters/") - ([&](int id) { + ([&](const crow::request& req, int id) { + if (!login::isLoggedIn(req)) { + return crow::response(401, "Login required"); + } auto optCharacter = getChracter(id); if (!optCharacter.has_value()) return crow::response(404, "Character not found"); @@ -71,7 +88,10 @@ void initApi(crow::SimpleApp& app) }); CROW_ROUTE(app, "/api/shadowrun/characters_data/") - ([&](int id) { + ([&](const crow::request& req, int id) { + if (!login::isLoggedIn(req)) { + return crow::response(401, "Login required"); + } nlohmann::json j; const auto characterData = getChracterData(id); @@ -99,6 +119,9 @@ void initApi(crow::SimpleApp& app) CROW_ROUTE(app, "/api/shadowrun/characters_data/").methods("POST"_method) ([&](const crow::request& req, int id) { + if (!login::isLoggedIn(req)) { + return crow::response(401, "Login required"); + } nlohmann::json j = nlohmann::json::parse(req.body); for (auto type : magic_enum::enum_values()) { @@ -110,7 +133,6 @@ void initApi(crow::SimpleApp& app) auto res = crow::response(200, "Saved Character data"); return res; - //return crow::response(405, ret.error()); }); } diff --git a/src/utils.cpp b/src/utils.cpp index 4b11be9..554c46c 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -6,6 +6,7 @@ #include #include #include "utils.hpp" +#include "crow/http_response.h" #include #include #include @@ -141,6 +142,45 @@ string currentTime(){ return ss.str(); } +std::string read_file(const std::string& path) { + std::ifstream file(path, std::ios::binary); + if (!file) { + throw std::runtime_error("Cannot open file: " + path); + } + std::ostringstream ss; + ss << file.rdbuf(); + return ss.str(); +} + +// Simple MIME type detection +std::string get_mime_type(const std::string& path) { + if (path.ends_with(".html")) return "text/html"; + if (path.ends_with(".js")) return "text/javascript"; + if (path.ends_with(".css")) return "text/css"; + if (path.ends_with(".json")) return "application/json"; + if (path.ends_with(".svg")) return "image/svg+xml"; + if (path.ends_with(".png")) return "image/png"; + if (path.ends_with(".jpg") || path.ends_with(".jpeg")) return "image/jpeg"; + if (path.ends_with(".woff")) return "font/woff"; + if (path.ends_with(".woff2")) return "font/woff2"; + if (path.ends_with(".pdf")) return "application/pdf"; + return "application/octet-stream"; +} + +crow::response getFile(const filesystem::path& file_path){ + // If file exists, serve it + if (filesystem::exists(file_path)) { + auto data = read_file(file_path); + auto mime = get_mime_type(file_path.string()); + return crow::response(200, mime.c_str(), data); + } + + // SPA fallback: serve root index.html for unknown routes + filesystem::path fallback = build_dir / "index.html"; + auto data = read_file(fallback); + return crow::response(404, "text/html", data); +} + std::expected parseJson(const std::string& input) { try { return nlohmann::json::parse(input); diff --git a/src/utils.hpp b/src/utils.hpp index 3fc9a4b..0b558e8 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -5,10 +5,13 @@ #include #include #include -#include #include #include "json.hpp" +#include "crow.h" + namespace utils { + const std::filesystem::path build_dir = "frontend/build/"; // <-- set your build folder + std::map parseBody(const std::string& body); std::optional getBodyName(const std::string& body); @@ -45,8 +48,10 @@ namespace utils { catch (const nlohmann::json::exception& e) { return std::unexpected(e.what()); } - } + +std::string read_file(const std::string& path); +crow::response getFile(const std::filesystem::path& file_path); } #endif