From 0c8ab4f082b2d8220954fd596b1e0a6fff571f8d Mon Sep 17 00:00:00 2001 From: Brett Date: Tue, 29 Aug 2023 11:48:55 -0400 Subject: [PATCH] reorder some of the main files --- CMakeLists.txt | 6 +- include/crowsite/config.h | 6 +- include/crowsite/crow_includes.h | 2 +- include/crowsite/crow_pch.h | 42 ++++ include/crowsite/crow_utility.h | 19 -- include/crowsite/site/cache.h | 9 +- include/crowsite/site/home.h | 77 +++++++ include/crowsite/site/posts.h | 17 +- include/crowsite/site/web.h | 19 +- include/crowsite/util/crow_conversion.h | 29 +++ include/crowsite/util/crow_fix.h | 45 ++++ include/crowsite/util/crow_log.h | 20 ++ include/crowsite/util/crow_session_util.h | 40 ++++ include/crowsite/util/crow_typedef.h | 20 ++ libs/crow/include/crow/query_string.h | 5 + src/crowsite/site/auth.cpp | 3 +- src/crowsite/site/cache.cpp | 18 +- src/crowsite/site/home.cpp | 11 + src/crowsite/site/posts.cpp | 16 +- src/crowsite/util/crow_fix.cpp | 22 ++ src/crowsite/util/crow_misc.cpp | 50 +++++ src/crowsite/util/crow_session_util.cpp | 88 ++++++++ src/crowsite/util/md_to_html.cpp | 2 +- src/crowsite/utility.cpp | 6 +- src/main.cpp | 242 ++++------------------ 25 files changed, 532 insertions(+), 282 deletions(-) create mode 100644 include/crowsite/crow_pch.h delete mode 100644 include/crowsite/crow_utility.h create mode 100644 include/crowsite/site/home.h create mode 100644 include/crowsite/util/crow_conversion.h create mode 100644 include/crowsite/util/crow_fix.h create mode 100644 include/crowsite/util/crow_log.h create mode 100644 include/crowsite/util/crow_session_util.h create mode 100644 include/crowsite/util/crow_typedef.h create mode 100644 src/crowsite/site/home.cpp create mode 100644 src/crowsite/util/crow_fix.cpp create mode 100644 src/crowsite/util/crow_misc.cpp create mode 100644 src/crowsite/util/crow_session_util.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e5a629d..8fcd23d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,8 @@ set(CROW_FEATURES compression) cmake_policy(SET CMP0057 NEW) #find_package(Crow) +set(PRECOMPILED_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/crowsite/crow_pch.h") + set(CROW_BUILD_TESTS OFF) set(CROW_BUILD_EXAMPLES OFF) set(CROW_INSTALL OFF) @@ -43,7 +45,7 @@ include_directories(${OPENSSL_INCLUDE_DIR}) file(GLOB_RECURSE source_files src/*.cpp) -add_executable(crowsite ${source_files}) +add_executable(crowsite ${source_files} ${PRECOMPILED_HEADER}) target_compile_definitions(crowsite PUBLIC CROW_ENABLE_COMPRESSION) @@ -70,3 +72,5 @@ if (${ENABLE_TSAN} MATCHES ON) target_compile_options(crowsite PRIVATE -fsanitize=thread) target_link_options(crowsite PRIVATE -fsanitize=thread) endif () + +target_precompile_headers(crowsite PRIVATE ${PRECOMPILED_HEADER}) diff --git a/include/crowsite/config.h b/include/crowsite/config.h index 9a31853..85aeec2 100644 --- a/include/crowsite/config.h +++ b/include/crowsite/config.h @@ -9,10 +9,10 @@ #include //#define CROW_STATIC_DIRECTORY "/home/brett/projects/cpp/crowsite/crow_test/static/" -#define CROW_STATIC_DIRECTORY "/home/brett/Documents/code/c++/crowsite/crow_test/static/" +#define CROWSITE_STATIC_DIRECTORY "/home/brett/Documents/code/c++/crowsite/crow_test/static/" //#define SITE_FILES_PATH "/home/brett/projects/cpp/crowsite/crow_test" -#define SITE_FILES_PATH "/home/brett/Documents/code/c++/crowsite/crow_test" -#define CROW_STATIC_ENDPOINT "/static/" +#define CROWSITE_FILES_PATH "/home/brett/Documents/code/c++/crowsite/crow_test" +#define CROWSITE_STATIC_ENDPOINT "/static/" #define MILES_SITE #undef MILES_SITE diff --git a/include/crowsite/crow_includes.h b/include/crowsite/crow_includes.h index 8a0af87..e5c61e8 100644 --- a/include/crowsite/crow_includes.h +++ b/include/crowsite/crow_includes.h @@ -6,6 +6,6 @@ #define CROWSITE_CROW_INCLUDES_H #include -#include "crow.h" +#include #endif //CROWSITE_CROW_INCLUDES_H diff --git a/include/crowsite/crow_pch.h b/include/crowsite/crow_pch.h new file mode 100644 index 0000000..1f8aa86 --- /dev/null +++ b/include/crowsite/crow_pch.h @@ -0,0 +1,42 @@ +#pragma once +/* + * Created by Brett on 29/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_CROW_PCH_H +#define CROWSITE_CROW_PCH_H + +#include "crow/query_string.h" +#include "crow/http_parser_merged.h" +#include "crow/ci_map.h" +#include "crow/TinySHA1.hpp" +#include "crow/settings.h" +#include "crow/socket_adaptors.h" +#include "crow/json.h" +#include "crow/mustache.h" +#include "crow/logging.h" +#include "crow/task_timer.h" +#include "crow/utility.h" +#include "crow/common.h" +#include "crow/http_request.h" +#include "crow/websocket.h" +#include "crow/parser.h" +#include "crow/http_response.h" +#include "crow/multipart.h" +#include "crow/routing.h" +#include "crow/middleware.h" +#include "crow/middleware_context.h" +#include "crow/compression.h" +#include "crow/http_connection.h" +#include "crow/http_server.h" +#include "crow/app.h" +#include "crow/middlewares/session.h" +#include "crow/middlewares/cookie_parser.h" + +using Session = crow::SessionMiddleware; +using CrowApp = crow::App; + + +#endif //CROWSITE_CROW_PCH_H diff --git a/include/crowsite/crow_utility.h b/include/crowsite/crow_utility.h deleted file mode 100644 index 5277154..0000000 --- a/include/crowsite/crow_utility.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by brett on 21/08/23. -// - -#ifndef CROWSITE_CROW_UTILITY_H -#define CROWSITE_CROW_UTILITY_H - -#include - -namespace cs { - inline crow::response redirect(const std::string& loc = "/", int code = 303) - { - crow::response res(code); - res.set_header("Location", loc); - return res; - } -} - -#endif //CROWSITE_CROW_UTILITY_H diff --git a/include/crowsite/site/cache.h b/include/crowsite/site/cache.h index 5bd4943..cff67e9 100644 --- a/include/crowsite/site/cache.h +++ b/include/crowsite/site/cache.h @@ -6,14 +6,13 @@ #define CROWSITE_CACHE_H #include +#include #include #include namespace cs { - using RuntimeContext = HASHMAP; - class LexerSyntaxError : public std::runtime_error { public: @@ -54,7 +53,7 @@ namespace cs std::string renderedPage; }; - StaticContext& m_Context; + context& m_Context; CacheSettings m_Settings; HASHMAP m_Pages; @@ -75,11 +74,11 @@ namespace cs void prune(uint64_t amount); public: - explicit CacheEngine(StaticContext& context, const CacheSettings& settings = {}); + explicit CacheEngine(context& context, const CacheSettings& settings = {}); const std::string& fetch(const std::string& path); - std::string fetch(const std::string& path, const RuntimeContext& context); + std::string fetch(const std::string& path, const context& context); }; } diff --git a/include/crowsite/site/home.h b/include/crowsite/site/home.h new file mode 100644 index 0000000..90e0881 --- /dev/null +++ b/include/crowsite/site/home.h @@ -0,0 +1,77 @@ +#pragma once +/* + * Created by Brett on 27/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_HOME_H +#define CROWSITE_HOME_H + +#include +#include +#include + +namespace cs +{ + + inline crow::response handle_root_page(const site_params& params) + { + //auto page = crow::mustache::load("index.html"); // + //return "Hello There

Suck it " + name + "

"; +// BLT_TRACE(req.body); +// for (const auto& h : req.headers) +// BLT_TRACE("Header: %s = %s", h.first.c_str(), h.second.c_str()); +// BLT_TRACE(req.raw_url); +// BLT_TRACE(req.url); +// BLT_TRACE(req.remote_ip_address); +// for (const auto& v : req.url_params.keys()) +// BLT_TRACE("URL: %s = %s", v.c_str(), req.url_params.get(v)); + if (params.name.ends_with(".html")) + { + checkAndUpdateUserSession(params.app, params.req); + auto& session = params.app.get_context(params.req); + auto s_clientID = session.get("clientID", ""); + auto s_clientToken = session.get("clientToken", ""); + auto user_perms = cs::getUserPermissions(cs::getUserFromID(s_clientID)); + + crow::mustache::context ctx; + cs::context context; + + generateRuntimeContext(params, context); + + // pass perms in + if (user_perms & cs::PERM_ADMIN) + ctx["_admin"] = true; + + if (cs::isUserLoggedIn(s_clientID, s_clientToken)) + { + ctx["_logged_in"] = true; + } else + { + ctx["_not_logged_in"] = true; + } + + // we don't want to pass all get parameters to the context to prevent leaking information + auto referer = params.req.url_params.get("referer"); + if (referer) + ctx["referer"] = referer; + auto page = crow::mustache::compile(params.engine.fetch(params.name, context)); + return page.render(ctx); + } + + return params.engine.fetch("default.html"); + } + + inline crow::response handle_auth_page(const site_params& params) + { + if (isUserAdmin(params.app, params.req)) + return redirect("/login.html"); + + + return handle_root_page(params); + } + +} + +#endif //CROWSITE_HOME_H diff --git a/include/crowsite/site/posts.h b/include/crowsite/site/posts.h index ab84dc9..8cc6a87 100644 --- a/include/crowsite/site/posts.h +++ b/include/crowsite/site/posts.h @@ -9,21 +9,14 @@ #define CROWSITE_POSTS_H #include -#include -#include +#include namespace cs { - struct request_info { - CacheEngine& engine; - const crow::request& req; - std::string clientID; - std::string tokenID; - std::string path; - }; - - crow::response handleProjectPage(const request_info& req); - + void posts_init(); + void posts_cleanup(); + + response_info handleProjectPage(const request_info& req); } #endif //CROWSITE_POSTS_H diff --git a/include/crowsite/site/web.h b/include/crowsite/site/web.h index a47d914..6dc1098 100644 --- a/include/crowsite/site/web.h +++ b/include/crowsite/site/web.h @@ -8,28 +8,11 @@ #include #include #include +#include #include namespace cs { - class StaticContext { - private: - HASHMAP replacements; - public: - inline auto begin() { - return replacements.begin(); - } - inline auto end() { - return replacements.end(); - } - inline std::string& operator[](const std::string& key){ - return replacements[key]; - } - inline void add(const std::string& key, const std::string& value){ - replacements[key] = value; - } - }; - class HTMLPage { private: std::string m_SiteData; diff --git a/include/crowsite/util/crow_conversion.h b/include/crowsite/util/crow_conversion.h new file mode 100644 index 0000000..48041e8 --- /dev/null +++ b/include/crowsite/util/crow_conversion.h @@ -0,0 +1,29 @@ +#pragma once +/* + * Created by Brett on 29/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_CROW_CONVERSION_H +#define CROWSITE_CROW_CONVERSION_H + +#include "crow/http_response.h" +#include + +namespace cs +{ + + crow::response toResponse(cs::response_info res); + + inline crow::response redirect(const std::string& loc, int code = 303) + { + crow::response res(code); + res.set_header("Location", loc); + return res; + } + +} + + +#endif //CROWSITE_CROW_CONVERSION_H diff --git a/include/crowsite/util/crow_fix.h b/include/crowsite/util/crow_fix.h new file mode 100644 index 0000000..fc86e79 --- /dev/null +++ b/include/crowsite/util/crow_fix.h @@ -0,0 +1,45 @@ +#pragma once +/* + * Created by Brett on 27/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_CROW_FIX_H +#define CROWSITE_CROW_FIX_H + +/** + * Basically waste a bunch of time to both a. reduce the compile time of using crow + * and b. reduce the runtime overhead of crow, by increasing runtime in some respects + * TODO: explain why this is better later, maybe test as well. + */ + +#include +#include +#include +#include "crowsite/site/cache.h" +#include "crowsite/util/crow_typedef.h" + +namespace cs +{ + query_string toQueryString(const std::vector& kv); + + struct request_info + { + std::string raw_url; ///< The full URL containing the `?` and URL parameters. + std::string clientID; + std::string tokenID; + std::string path; + query_string url_params; ///< The parameters associated with the request. (everything after the `?` in the URL) + CacheEngine& engine; + std::optional headers{}; + }; + + struct response_info + { + std::string body; + std::optional ctx{}; + }; +} + +#endif //CROWSITE_CROW_FIX_H diff --git a/include/crowsite/util/crow_log.h b/include/crowsite/util/crow_log.h new file mode 100644 index 0000000..b17beb8 --- /dev/null +++ b/include/crowsite/util/crow_log.h @@ -0,0 +1,20 @@ +#pragma once +/* + * Created by Brett on 29/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_CROW_LOG_H +#define CROWSITE_CROW_LOG_H + +#include +#include + +class BLT_CrowLogger : public crow::ILogHandler +{ + public: + void log(std::string message, crow::LogLevel crow_level) final; +}; + +#endif //CROWSITE_CROW_LOG_H diff --git a/include/crowsite/util/crow_session_util.h b/include/crowsite/util/crow_session_util.h new file mode 100644 index 0000000..6a66e59 --- /dev/null +++ b/include/crowsite/util/crow_session_util.h @@ -0,0 +1,40 @@ +#pragma once +/* + * Created by Brett on 29/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_CROW_SESSION_UTIL_H +#define CROWSITE_CROW_SESSION_UTIL_H + +#include "crowsite/site/auth.h" +#include "crow_typedef.h" +#include "crowsite/site/cache.h" + +namespace cs +{ + + struct site_params + { + CrowApp& app; + cs::CacheEngine& engine; + const crow::request& req; + const std::string& name; + }; + + /** + * Note this function destroys the user's session and any login related cookies! + */ + void destroyUserSession(CrowApp& app, const crow::request& req); + + bool checkAndUpdateUserSession(CrowApp& app, const crow::request& req); + + bool isUserLoggedIn(CrowApp& app, const crow::request& req); + + bool isUserAdmin(CrowApp& app, const crow::request& req); + + void generateRuntimeContext(const site_params& params, cs::context& context); +} + +#endif //CROWSITE_CROW_SESSION_UTIL_H diff --git a/include/crowsite/util/crow_typedef.h b/include/crowsite/util/crow_typedef.h new file mode 100644 index 0000000..5e3c851 --- /dev/null +++ b/include/crowsite/util/crow_typedef.h @@ -0,0 +1,20 @@ +#pragma once +/* + * Created by Brett on 28/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ + +#ifndef CROWSITE_CROW_TYPEDEF_H +#define CROWSITE_CROW_TYPEDEF_H + +#include + +namespace cs +{ + typedef HASHMAP header_map; + typedef HASHMAP query_string; + typedef HASHMAP context; +} + +#endif //CROWSITE_CROW_TYPEDEF_H diff --git a/libs/crow/include/crow/query_string.h b/libs/crow/include/crow/query_string.h index 66d380f..f14de29 100644 --- a/libs/crow/include/crow/query_string.h +++ b/libs/crow/include/crow/query_string.h @@ -469,6 +469,11 @@ namespace crow } return ret; } + + inline const std::vector& getValues() const + { + return key_value_pairs_; + } std::vector keys() const { diff --git a/src/crowsite/site/auth.cpp b/src/crowsite/site/auth.cpp index 297fe2c..298504b 100644 --- a/src/crowsite/site/auth.cpp +++ b/src/crowsite/site/auth.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "blt/std/logging.h" #include "blt/std/uuid.h" #include @@ -190,7 +191,7 @@ namespace cs void auth::init() { // TODO: proper multithreading - auto path = (std::string(SITE_FILES_PATH) + "/data/db/"); + auto path = cs::fs::createDataFilePath("db/"); auto dbname = "users.sqlite"; auto full_path = path + dbname; BLT_TRACE("Using %s for users database", full_path.c_str()); diff --git a/src/crowsite/site/cache.cpp b/src/crowsite/site/cache.cpp index ab793e9..a3aea5d 100644 --- a/src/crowsite/site/cache.cpp +++ b/src/crowsite/site/cache.cpp @@ -224,14 +224,14 @@ namespace cs } } - static inline bool isTrue(const RuntimeContext& context, const std::string& token) + static inline bool isTrue(const context& context, const std::string& token) { //BLT_DEBUG("isTrue for token '%s' contains? %s", token.c_str(), context.contains(token) ? "True" : "False"); return context.contains(token) && !context.at(token).empty(); } // http://www.cs.unb.ca/~wdu/cs4613/a2ans.htm - bool factor(const RuntimeContext& context) + bool factor(const context& context) { if (!hasNextToken()) blt_throw(LexerSyntaxError("Processing boolean factor but no token was found!")); @@ -256,7 +256,7 @@ namespace cs } } - bool expr(const RuntimeContext& context) + bool expr(const context& context) { auto fac = factor(context); if (!hasNextToken()) @@ -281,7 +281,7 @@ namespace cs processString(); } - bool eval(const RuntimeContext& context) + bool eval(const context& context) { return expr(context); } @@ -335,7 +335,7 @@ namespace cs return tagLocations[0]; } - static std::string searchAndReplace(const std::string& data, const RuntimeContext& context) + static std::string searchAndReplace(const std::string& data, const context& context) { RuntimeLexer lexer(data); std::string results; @@ -373,7 +373,7 @@ namespace cs if (lexer.hasTemplatePrefix('/')) lexer.consumeToken(); else - blt_throw(LexerSyntaxError("Ending token not found!")); + blt_throw(LexerSyntaxError("Ending token not found!")); } else results += lexer.consume(); @@ -389,8 +389,8 @@ namespace cs return (double) (v) / 1000000000.0; } - CacheEngine::CacheEngine(StaticContext& context, const CacheSettings& settings): m_Context(context), - m_Settings((settings)) + CacheEngine::CacheEngine(context& ctx, const CacheSettings& settings): m_Context(ctx), + m_Settings((settings)) {} uint64_t CacheEngine::calculateMemoryUsage(const std::string& path, const CacheEngine::CacheValue& value) @@ -571,7 +571,7 @@ namespace cs page.getRawSite() = resolvedSite; } - std::string CacheEngine::fetch(const std::string& path, const RuntimeContext& context) + std::string CacheEngine::fetch(const std::string& path, const context& context) { auto fetched = fetch(path); return RuntimeLexer::searchAndReplace(fetched, context); diff --git a/src/crowsite/site/home.cpp b/src/crowsite/site/home.cpp new file mode 100644 index 0000000..194269b --- /dev/null +++ b/src/crowsite/site/home.cpp @@ -0,0 +1,11 @@ +/* + * Created by Brett on 27/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ +#include + +namespace cs +{ + +} \ No newline at end of file diff --git a/src/crowsite/site/posts.cpp b/src/crowsite/site/posts.cpp index 534ede9..133f86a 100644 --- a/src/crowsite/site/posts.cpp +++ b/src/crowsite/site/posts.cpp @@ -4,6 +4,7 @@ * See LICENSE file for license detail */ #include +#include #include #include #include @@ -11,7 +12,7 @@ namespace cs { - crow::response handleProjectPage(const request_info& req) + response_info handleProjectPage(const request_info& req) { std::string buffer; buffer += ""; @@ -19,9 +20,18 @@ namespace cs buffer += htmlData; buffer += ""; - return buffer; + return {buffer}; + } + + void posts_init() + { + + } + + void posts_cleanup() + { + } - } \ No newline at end of file diff --git a/src/crowsite/util/crow_fix.cpp b/src/crowsite/util/crow_fix.cpp new file mode 100644 index 0000000..2b5b7d3 --- /dev/null +++ b/src/crowsite/util/crow_fix.cpp @@ -0,0 +1,22 @@ +/* + * Created by Brett on 27/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ +#include + +namespace cs +{ + + query_string toQueryString(const std::vector& key_values) + { + query_string query_kv; + for (const auto& kv : key_values) + { + std::string str(kv); + auto equ_loc = str.find('='); + query_kv[str.substr(0, equ_loc)] = str.substr(equ_loc+1, str.size()); + } + return query_kv; + } +} \ No newline at end of file diff --git a/src/crowsite/util/crow_misc.cpp b/src/crowsite/util/crow_misc.cpp new file mode 100644 index 0000000..f5ec78b --- /dev/null +++ b/src/crowsite/util/crow_misc.cpp @@ -0,0 +1,50 @@ +/* + * Created by Brett on 29/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ +#include +#include +#include + +void BLT_CrowLogger::log(std::string message, crow::LogLevel crow_level) +{ + blt::logging::log_level blt_level = blt::logging::log_level::NONE; + switch (crow_level) + { + case crow::LogLevel::DEBUG: + blt_level = blt::logging::log_level::DEBUG; + break; + case crow::LogLevel::INFO: + blt_level = blt::logging::log_level::INFO; + break; + case crow::LogLevel::WARNING: + blt_level = blt::logging::log_level::WARN; + break; + case crow::LogLevel::ERROR: + blt_level = blt::logging::log_level::ERROR; + break; + case crow::LogLevel::CRITICAL: + blt_level = blt::logging::log_level::FATAL; + break; + } + BLT_LOG("Crow: %s", blt_level, message.c_str()); +} + +namespace cs +{ + + crow::response toResponse(cs::response_info res) + { + if (res.ctx.has_value()) + { + auto v = crow::mustache::compile(res.body); + crow::mustache::context ctx; + for (const auto& c : res.ctx.value()) + ctx[c.first] = c.second; + return v.render(ctx); + } + return res.body; + } + +} \ No newline at end of file diff --git a/src/crowsite/util/crow_session_util.cpp b/src/crowsite/util/crow_session_util.cpp new file mode 100644 index 0000000..7948409 --- /dev/null +++ b/src/crowsite/util/crow_session_util.cpp @@ -0,0 +1,88 @@ +/* + * Created by Brett on 29/08/23. + * Licensed under GNU General Public License V3.0 + * See LICENSE file for license detail + */ +#include +#include + +namespace cs +{ + + void destroyUserSession(CrowApp& app, const crow::request& req) + { + auto& session = app.get_context(req); + auto& cookie_context = app.get_context(req); + + session.set("clientID", ""); + session.set("clientToken", ""); + cookie_context.set_cookie("clientID", ""); + cookie_context.set_cookie("clientToken", ""); + } + + bool checkAndUpdateUserSession(CrowApp& app, const crow::request& req) + { + auto& session = app.get_context(req); + auto& cookie_context = app.get_context(req); + + auto s_clientID = session.get("clientID", ""); + auto s_clientToken = session.get("clientToken", ""); + + auto c_clientID = cookie_context.get_cookie("clientID"); + auto c_clientToken = cookie_context.get_cookie("clientToken"); + + if ((!c_clientID.empty() && !c_clientToken.empty()) && (s_clientID != c_clientID || s_clientToken != c_clientToken)) + { + session.set("clientID", c_clientID); + session.set("clientToken", c_clientToken); + return true; + } + return false; + } + + bool isUserLoggedIn(CrowApp& app, const crow::request& req) + { + auto& session = app.get_context(req); + auto s_clientID = session.get("clientID", ""); + auto s_clientToken = session.get("clientToken", ""); + return cs::isUserLoggedIn(s_clientID, s_clientToken); + } + + bool isUserAdmin(CrowApp& app, const crow::request& req) + { + auto& session = app.get_context(req); + auto s_clientID = session.get("clientID", ""); + return cs::isUserAdmin(cs::getUserFromID(s_clientID)); + } + + void generateRuntimeContext(const site_params& params, cs::context& context) + { + auto& session = params.app.get_context(params.req); + auto s_clientID = session.get("clientID", ""); + auto s_clientToken = session.get("clientToken", ""); + if (cs::isUserLoggedIn(s_clientID, s_clientToken)) + { + auto username = cs::getUserFromID(s_clientID); + auto perms = cs::getUserPermissions(username); + auto isAdmin = cs::isUserAdmin(username); + context["_logged_in"] = "True"; + context["_username"] = username; + if (isAdmin) + context["_admin"] = "True"; + if (perms & cs::PERM_READ_FILES) + context["_read_files"] = "True"; + if (perms & cs::PERM_WRITE_FILES) + context["_write_files"] = "True"; + if (perms & cs::PERM_CREATE_POSTS) + context["_create_posts"] = "True"; + if (perms & cs::PERM_CREATE_COMMENTS) + context["_create_comments"] = "True"; + if (perms & cs::PERM_CREATE_SHARES) + context["_create_shares"] = "True"; + if (perms & cs::PERM_EDIT_POSTS) + context["_edit_posts"] = "True"; + if (perms & cs::PERM_EDIT_COMMENTS) + context["_edit_comments"] = "True"; + } + } +} diff --git a/src/crowsite/util/md_to_html.cpp b/src/crowsite/util/md_to_html.cpp index e6ba9df..f270470 100644 --- a/src/crowsite/util/md_to_html.cpp +++ b/src/crowsite/util/md_to_html.cpp @@ -47,7 +47,7 @@ namespace cs { std::string str() { - std::string out (buffer, buffer + used_size); + std::string out (buffer, used_size); return out; } }; diff --git a/src/crowsite/utility.cpp b/src/crowsite/utility.cpp index 3550732..2c57374 100644 --- a/src/crowsite/utility.cpp +++ b/src/crowsite/utility.cpp @@ -55,7 +55,7 @@ namespace cs { std::string createStaticFilePath(const std::string& file) { - auto path = std::string(CROW_STATIC_DIRECTORY); + auto path = std::string(CROWSITE_STATIC_DIRECTORY); if (!path.ends_with('/')) path += '/'; path += file; @@ -67,7 +67,7 @@ namespace cs std::string createWebFilePath(const std::string& file) { - auto path = std::string(SITE_FILES_PATH); + auto path = std::string(CROWSITE_FILES_PATH); if (!path.ends_with('/')) path += '/'; path += "webcontent/"; @@ -79,7 +79,7 @@ namespace cs std::string createDataFilePath(const std::string& file) { - auto path = std::string(SITE_FILES_PATH); + auto path = std::string(CROWSITE_FILES_PATH); if (!path.ends_with('/')) path += '/'; path += "data/"; diff --git a/src/main.cpp b/src/main.cpp index a11691f..2849805 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,191 +3,19 @@ #include #include #include -#include #include #include #include #include -#include -#include +#include #include -#include +#include +#include -using Session = crow::SessionMiddleware; -using CrowApp = crow::App; - -class BLT_CrowLogger : public crow::ILogHandler -{ - public: - void log(std::string message, crow::LogLevel crow_level) final - { - blt::logging::log_level blt_level = blt::logging::log_level::NONE; - switch (crow_level) - { - case crow::LogLevel::DEBUG: - blt_level = blt::logging::log_level::DEBUG; - break; - case crow::LogLevel::INFO: - blt_level = blt::logging::log_level::INFO; - break; - case crow::LogLevel::WARNING: - blt_level = blt::logging::log_level::WARN; - break; - case crow::LogLevel::ERROR: - blt_level = blt::logging::log_level::ERROR; - break; - case crow::LogLevel::CRITICAL: - blt_level = blt::logging::log_level::FATAL; - break; - } - BLT_LOG("Crow: %s", blt_level, message.c_str()); - } -}; - -struct site_params -{ - CrowApp& app; - cs::CacheEngine& engine; - const crow::request& req; - const std::string& name; -}; - -/** - * Note this function destroys the user's session and any login related cookies! - */ -void destroyUserSession(CrowApp& app, const crow::request& req) -{ - auto& session = app.get_context(req); - auto& cookie_context = app.get_context(req); - - session.set("clientID", ""); - session.set("clientToken", ""); - cookie_context.set_cookie("clientID", ""); - cookie_context.set_cookie("clientToken", ""); -} - -bool checkAndUpdateUserSession(CrowApp& app, const crow::request& req) -{ - auto& session = app.get_context(req); - auto& cookie_context = app.get_context(req); - - auto s_clientID = session.get("clientID", ""); - auto s_clientToken = session.get("clientToken", ""); - - auto c_clientID = cookie_context.get_cookie("clientID"); - auto c_clientToken = cookie_context.get_cookie("clientToken"); - - if ((!c_clientID.empty() && !c_clientToken.empty()) && (s_clientID != c_clientID || s_clientToken != c_clientToken)) - { - session.set("clientID", c_clientID); - session.set("clientToken", c_clientToken); - return true; - } - return false; -} - -bool isUserLoggedIn(CrowApp& app, const crow::request& req) -{ - auto& session = app.get_context(req); - auto s_clientID = session.get("clientID", ""); - auto s_clientToken = session.get("clientToken", ""); - return cs::isUserLoggedIn(s_clientID, s_clientToken); -} - -bool isUserAdmin(CrowApp& app, const crow::request& req) -{ - auto& session = app.get_context(req); - auto s_clientID = session.get("clientID", ""); - return cs::isUserAdmin(cs::getUserFromID(s_clientID)); -} - -void generateRuntimeContext(const site_params& params, cs::RuntimeContext& context) -{ - auto& session = params.app.get_context(params.req); - auto s_clientID = session.get("clientID", ""); - auto s_clientToken = session.get("clientToken", ""); - if (cs::isUserLoggedIn(s_clientID, s_clientToken)) - { - auto username = cs::getUserFromID(s_clientID); - auto perms = cs::getUserPermissions(username); - auto isAdmin = cs::isUserAdmin(username); - context["_logged_in"] = "True"; - context["_username"] = username; - if (isAdmin) - context["_admin"] = "True"; - if (perms & cs::PERM_READ_FILES) - context["_read_files"] = "True"; - if (perms & cs::PERM_WRITE_FILES) - context["_write_files"] = "True"; - if (perms & cs::PERM_CREATE_POSTS) - context["_create_posts"] = "True"; - if (perms & cs::PERM_CREATE_COMMENTS) - context["_create_comments"] = "True"; - if (perms & cs::PERM_CREATE_SHARES) - context["_create_shares"] = "True"; - if (perms & cs::PERM_EDIT_POSTS) - context["_edit_posts"] = "True"; - if (perms & cs::PERM_EDIT_COMMENTS) - context["_edit_comments"] = "True"; - } -} - -crow::response handle_root_page(const site_params& params) -{ - //auto page = crow::mustache::load("index.html"); // - //return "Hello There

Suck it " + name + "

"; -// BLT_TRACE(req.body); -// for (const auto& h : req.headers) -// BLT_TRACE("Header: %s = %s", h.first.c_str(), h.second.c_str()); -// BLT_TRACE(req.raw_url); -// BLT_TRACE(req.url); -// BLT_TRACE(req.remote_ip_address); -// for (const auto& v : req.url_params.keys()) -// BLT_TRACE("URL: %s = %s", v.c_str(), req.url_params.get(v)); - if (params.name.ends_with(".html")) - { - checkAndUpdateUserSession(params.app, params.req); - auto& session = params.app.get_context(params.req); - auto s_clientID = session.get("clientID", ""); - auto s_clientToken = session.get("clientToken", ""); - auto user_perms = cs::getUserPermissions(cs::getUserFromID(s_clientID)); - - crow::mustache::context ctx; - cs::RuntimeContext context; - - generateRuntimeContext(params, context); - - // pass perms in - if (user_perms & cs::PERM_ADMIN) - ctx["_admin"] = true; - - if (cs::isUserLoggedIn(s_clientID, s_clientToken)) - { - ctx["_logged_in"] = true; - } else - { - ctx["_not_logged_in"] = true; - } - - // we don't want to pass all get parameters to the context to prevent leaking information - auto referer = params.req.url_params.get("referer"); - if (referer) - ctx["referer"] = referer; - auto page = crow::mustache::compile(params.engine.fetch(params.name, context)); - return page.render(ctx); - } - - return params.engine.fetch("default.html"); -} - -crow::response handle_auth_page(const site_params& params) -{ - if (isUserAdmin(params.app, params.req)) - return cs::redirect("/login.html"); - - - return handle_root_page(params); -} +#define CS_SESSION cs::checkAndUpdateUserSession(app, req); \ + auto& session = app.get_context(req); \ + auto s_clientID = session.get("clientID", ""); \ + auto s_clientToken = session.get("clientToken", ""); \ int main(int argc, const char** argv) { @@ -207,7 +35,7 @@ int main(int argc, const char** argv) cs::auth::init(); BLT_INFO("Starting site %s.", SITE_NAME); - crow::mustache::set_global_base(SITE_FILES_PATH); + crow::mustache::set_global_base(CROWSITE_FILES_PATH); static BLT_CrowLogger bltCrowLogger{}; crow::logger::setHandler(&bltCrowLogger); @@ -221,26 +49,28 @@ int main(int argc, const char** argv) // set session id length (small value only for demonstration purposes) 16, // init the store - crow::FileStore{std::string(SITE_FILES_PATH) + "/data/session", session_age}}}; + crow::FileStore{std::string(CROWSITE_FILES_PATH) + "/data/session", session_age}}}; app.use_compression(crow::compression::GZIP); app.loglevel(crow::LogLevel::WARNING); BLT_INFO("Creating static context"); - cs::StaticContext context; - context["SITE_TITLE"] = SITE_TITLE; - context["SITE_NAME"] = SITE_NAME; - context["SITE_VERSION"] = SITE_VERSION; - context["BEE_MOVIE"] = beemovie_script; - context["SITE_BACKGROUND"] = "/static/images/backgrounds/2023-05-26_23.18.23.png"; - context["MENU_BAR_COLOR"] = "#335"; - context["MENU_BAR_HOVER"] = "#223"; - context["MENU_BAR_ACTIVE"] = "#7821be"; + cs::context static_context; + static_context["SITE_TITLE"] = SITE_TITLE; + static_context["SITE_NAME"] = SITE_NAME; + static_context["SITE_VERSION"] = SITE_VERSION; + static_context["BEE_MOVIE"] = beemovie_script; + static_context["SITE_BACKGROUND"] = "/static/images/backgrounds/2023-05-26_23.18.23.png"; + static_context["MENU_BAR_COLOR"] = "#335"; + static_context["MENU_BAR_HOVER"] = "#223"; + static_context["MENU_BAR_ACTIVE"] = "#7821be"; BLT_INFO("Starting cache engine"); cs::CacheSettings settings; - cs::CacheEngine engine(context, settings); + cs::CacheEngine engine(static_context, settings); + + cs::posts_init(); BLT_INFO("Creating routes"); @@ -255,22 +85,22 @@ int main(int argc, const char** argv) CROW_ROUTE(app, "/login.html")( [&app, &engine](const crow::request& req) -> crow::response { - if (isUserLoggedIn(app, req)) + if (cs::isUserLoggedIn(app, req)) return cs::redirect("/"); - return handle_root_page({app, engine, req, "login.html"}); + return cs::handle_root_page({app, engine, req, "login.html"}); } ); CROW_ROUTE(app, "/logout.html")( [&app](const crow::request& req) -> crow::response { - destroyUserSession(app, req); + cs::destroyUserSession(app, req); return cs::redirect("/"); } ); CROW_ROUTE(app, "/")( [&app, &engine](const crow::request& req, const std::string& name) -> crow::response { - return handle_root_page({app, engine, req, name}); + return cs::handle_root_page({app, engine, req, name}); } ); @@ -314,29 +144,27 @@ int main(int argc, const char** argv) CROW_ROUTE(app, "/projects/")( [&engine, &app](const crow::request& req, const std::string& path) { - checkAndUpdateUserSession(app, req); - auto& session = app.get_context(req); - auto s_clientID = session.get("clientID", ""); - auto s_clientToken = session.get("clientToken", ""); + CS_SESSION; - return cs::handleProjectPage({engine, req, s_clientID, s_clientToken, path}); + return toResponse( + cs::handleProjectPage({req.raw_url, s_clientID, s_clientToken, path, cs::toQueryString(req.url_params.getValues()), engine})); } ); CROW_ROUTE(app, "/projects/")( [&engine, &app](const crow::request& req) { - checkAndUpdateUserSession(app, req); - auto& session = app.get_context(req); - auto s_clientID = session.get("clientID", ""); - auto s_clientToken = session.get("clientToken", ""); + CS_SESSION; - return cs::handleProjectPage({engine, req, s_clientID, s_clientToken, "index.html"}); + return toResponse( + cs::handleProjectPage( + {req.raw_url, s_clientID, s_clientToken, "index.html", cs::toQueryString(req.url_params.getValues()), engine} + )); } ); CROW_ROUTE(app, "/")( [&engine, &app](const crow::request& req) { - return handle_root_page({app, engine, req, "index.html"}); + return cs::handle_root_page({app, engine, req, "index.html"}); } ); @@ -363,6 +191,8 @@ int main(int argc, const char** argv) BLT_INFO("Starting Crow website on port %d", port); app.port(port).multithreaded().run(); + cs::posts_cleanup(); + cs::requests::cleanup(); cs::auth::cleanup();