diff --git a/crow_test/webcontent/projects/post.html b/crow_test/webcontent/projects/post.html
new file mode 100644
index 0000000..9434f82
--- /dev/null
+++ b/crow_test/webcontent/projects/post.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+ {{$SITE_TITLE}}
+
+ {{@body_begin.part}}
+
+ {{@body_end.part}}
+
diff --git a/crow_test/webcontent/projects/projects.html b/crow_test/webcontent/projects/projects.html
new file mode 100644
index 0000000..9434f82
--- /dev/null
+++ b/crow_test/webcontent/projects/projects.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+ {{$SITE_TITLE}}
+
+ {{@body_begin.part}}
+
+ {{@body_end.part}}
+
diff --git a/include/crowsite/config.h b/include/crowsite/config.h
index 85aeec2..761e324 100644
--- a/include/crowsite/config.h
+++ b/include/crowsite/config.h
@@ -9,7 +9,8 @@
#include
//#define CROW_STATIC_DIRECTORY "/home/brett/projects/cpp/crowsite/crow_test/static/"
-#define CROWSITE_STATIC_DIRECTORY "/home/brett/Documents/code/c++/crowsite/crow_test/static/"
+#undef CROW_STATIC_DIRECTORY
+#define CROW_STATIC_DIRECTORY "/home/brett/Documents/code/c++/crowsite/crow_test/static/"
//#define SITE_FILES_PATH "/home/brett/projects/cpp/crowsite/crow_test"
#define CROWSITE_FILES_PATH "/home/brett/Documents/code/c++/crowsite/crow_test"
#define CROWSITE_STATIC_ENDPOINT "/static/"
diff --git a/include/crowsite/crow_pch.h b/include/crowsite/crow_pch.h
index 1f8aa86..25b17cb 100644
--- a/include/crowsite/crow_pch.h
+++ b/include/crowsite/crow_pch.h
@@ -8,6 +8,7 @@
#ifndef CROWSITE_CROW_PCH_H
#define CROWSITE_CROW_PCH_H
+#include
#include "crow/query_string.h"
#include "crow/http_parser_merged.h"
#include "crow/ci_map.h"
diff --git a/include/crowsite/site/home.h b/include/crowsite/site/home.h
index 90e0881..7d4fddc 100644
--- a/include/crowsite/site/home.h
+++ b/include/crowsite/site/home.h
@@ -8,69 +8,16 @@
#ifndef CROWSITE_HOME_H
#define CROWSITE_HOME_H
-#include
#include
-#include
namespace cs
{
+
+ crow::response handle_login_request(const crow::request& req, CrowApp& app);
- inline crow::response handle_root_page(const site_params& params)
- {
- //auto page = crow::mustache::load("index.html"); //
- //return "Hello ThereSuck 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");
- }
+ crow::response handle_root_page(const site_params& params);
- 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);
- }
+ crow::response handle_auth_page(const site_params& params);
}
diff --git a/include/crowsite/site/routing.h b/include/crowsite/site/routing.h
new file mode 100644
index 0000000..aa17f5f
--- /dev/null
+++ b/include/crowsite/site/routing.h
@@ -0,0 +1,20 @@
+#pragma once
+/*
+ * Created by Brett on 01/09/23.
+ * Licensed under GNU General Public License V3.0
+ * See LICENSE file for license detail
+ */
+
+#ifndef CROWSITE_ROUTING_H
+#define CROWSITE_ROUTING_H
+
+#include
+#include "crowsite/site/cache.h"
+
+namespace cs
+{
+ void establishHomeRoutes(CrowApp& app, CacheEngine& engine);
+ void establishProjectRoutes(CrowApp& app, CacheEngine& engine);
+}
+
+#endif //CROWSITE_ROUTING_H
diff --git a/include/crowsite/sql_helper.h b/include/crowsite/sql_helper.h
index 396328c..5045457 100644
--- a/include/crowsite/sql_helper.h
+++ b/include/crowsite/sql_helper.h
@@ -7,29 +7,110 @@
#include
#include
+#include
+#include "blt/std/assert.h"
namespace cs::sql
{
+ class sql_error : public std::runtime_error
+ {
+ public:
+ sql_error(const std::string& error): std::runtime_error(error)
+ {}
+ };
+
static int prepareStatement(sqlite3* db, const std::string& sqlStatement, sqlite3_stmt** ppStmt)
{
return sqlite3_prepare_v2(db, sqlStatement.c_str(), static_cast(sqlStatement.size()) + 1, ppStmt, nullptr);
}
- class statement
+ class database
{
+ friend class statement_base_helper;
+
private:
- sqlite3_stmt* stmt = nullptr;
+ std::string path;
sqlite3* db;
- int err;
public:
- statement(sqlite3* db, const std::string& statement): db(db)
+ database(const std::string& dbLocation): path(dbLocation)
{
- err = prepareStatement(db, statement, &stmt);
- if (err)
- BLT_ERROR("Failed to execute statement, error code %d, error: %s.", err, sqlite3_errstr(err));
+ std::filesystem::create_directories(dbLocation.substr(0, dbLocation.find_last_of('/') + 1));
+ if (int err = sqlite3_open_v2(
+ path.c_str(), &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX,
+ nullptr
+ ) != SQLITE_OK)
+ {
+ BLT_FATAL("Unable to create database connection! err %d msg %s", err, sqlite3_errstr(err));
+ std::exit(1);
+ }
}
+ database(database&& move)
+ {
+ db = move.db;
+ path = move.path;
+ move.db = nullptr;
+ }
+
+ database& operator=(database&& move)
+ {
+ db = move.db;
+ path = move.path;
+ move.db = nullptr;
+ return *this;
+ }
+
+ database(const database& copy) = delete;
+
+ database& operator=(const database& copy) = delete;
+
+ ~database()
+ {
+ sqlite3_close_v2(db);
+ }
+ };
+
+ class statement_base_helper
+ {
+ protected:
+ sqlite3_stmt* stmt = nullptr;
+ int err;
+
+ statement_base_helper(const database& db, const std::string& statement, bool throw_errors)
+ {
+ err = prepareStatement(db.db, statement, &stmt);
+ if (err != SQLITE_OK)
+ {
+ if (throw_errors)
+ {
+ BLT_THROW(std::runtime_error(
+ "Failed to prepare statement '" + statement + "', error code " + std::to_string(err) + ", error: " +
+ sqlite3_errstr(err)));
+ } else
+ BLT_ERROR("Failed to prepare statement, error code %d, error: %s.", err, sqlite3_errstr(err));
+ }
+ }
+ };
+
+ class statement : public statement_base_helper
+ {
+ public:
+ statement(statement&& move) = delete;
+
+ statement(const statement& copy) = delete;
+
+ statement& operator=(statement&& move) = delete;
+
+ statement& operator=(const statement& copy) = delete;
+
+ statement(const database& db, const std::string& statement, bool throw_errors = true): statement_base_helper(db, statement, throw_errors)
+ {}
+
+ statement(const database* db, const std::string& statement, bool throw_errors = true): statement_base_helper(*db, statement, throw_errors)
+ {}
+
/**
* @return true if the last statement failed. Should be checked after construction!
*/
@@ -121,6 +202,12 @@ namespace cs::sql
};
+ inline void auto_statement(const database* db, const std::string& stmt, bool throw_errors = true){
+ statement s(db, stmt, throw_errors);
+ if (!s.execute() && throw_errors)
+ BLT_THROW(sql_error("Unable to execute statement '" + stmt + "'. Error: " + std::to_string(s.error()) + sqlite3_errstr(s.error())));
+ }
+
}
#endif //CROWSITE_SQL_HELPER_H
diff --git a/include/crowsite/util/crow_session_util.h b/include/crowsite/util/crow_session_util.h
index 6a66e59..e8919db 100644
--- a/include/crowsite/util/crow_session_util.h
+++ b/include/crowsite/util/crow_session_util.h
@@ -14,6 +14,8 @@
namespace cs
{
+ constexpr auto session_age = 24 * 60 * 60;
+ constexpr auto cookie_age = 180 * 24 * 60 * 60;
struct site_params
{
@@ -37,4 +39,9 @@ namespace cs
void generateRuntimeContext(const site_params& params, cs::context& context);
}
+#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", ""); \
+
#endif //CROWSITE_CROW_SESSION_UTIL_H
diff --git a/libs/BLT b/libs/BLT
index d3ed466..215220f 160000
--- a/libs/BLT
+++ b/libs/BLT
@@ -1 +1 @@
-Subproject commit d3ed46686eb0667c9824fbba5f90519efd2a50c3
+Subproject commit 215220f98b0ac4a87fe4a233de16650cf6d0b968
diff --git a/src/crowsite/site/auth.cpp b/src/crowsite/site/auth.cpp
index 298504b..b219394 100644
--- a/src/crowsite/site/auth.cpp
+++ b/src/crowsite/site/auth.cpp
@@ -17,7 +17,7 @@ using namespace blt;
namespace cs
{
- sqlite3* user_database;
+ cs::sql::database* user_database;
// https://stackoverflow.com/questions/5288076/base64-encoding-and-decoding-with-openssl
@@ -191,28 +191,15 @@ namespace cs
void auth::init()
{
// TODO: proper multithreading
- 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());
- std::filesystem::create_directories(path);
- if (int err = sqlite3_open_v2(full_path.c_str(), &user_database,
- SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX,
- nullptr
- ) != SQLITE_OK)
- {
- BLT_FATAL("Unable to create database connection! err %d msg %s", err, sqlite3_errstr(err));
- std::exit(1);
- }
+ const auto path = cs::fs::createDataFilePath("db/users.sqlite");
+ BLT_TRACE("Using %s for users database", path.c_str());
+ user_database = new sql::database(path);
sql::statement v {
user_database,
"SELECT SQLITE_VERSION()"
};
- if (v.fail())
- BLT_WARN("Failed to create statement with error code: %d msg: %s", v.error(), sqlite3_errstr(v.error()));
-
if (!v.execute())
BLT_WARN("Failed to execute statement with error code: %d msg: %s", v.error(), sqlite3_errstr(v.error()));
@@ -237,6 +224,6 @@ namespace cs
void auth::cleanup()
{
- sqlite3_close_v2(user_database);
+ delete(user_database);
}
}
\ No newline at end of file
diff --git a/src/crowsite/site/cache.cpp b/src/crowsite/site/cache.cpp
index a3aea5d..7046870 100644
--- a/src/crowsite/site/cache.cpp
+++ b/src/crowsite/site/cache.cpp
@@ -136,6 +136,7 @@ namespace cs
case TokenType::CLOSE:
return "CLOSE";
}
+ throw LexerSyntaxError("Unable to determine type of token");
}
struct Token
@@ -254,6 +255,7 @@ namespace cs
default:
blt_throw(LexerSyntaxError("Weird token found while parsing tokens, type: " + decodeName(next.type)));
}
+ return false;
}
bool expr(const context& context)
@@ -297,12 +299,7 @@ namespace cs
return false;
return str[index] == '{' && str[index + 1] == '{' && str[index + 2] == c;
}
-
- static std::string consumeToEndTemplate(const std::string& tokenName)
- {
-
- }
-
+
static void getTagLocations(std::vector& tagLocations, const std::string& tag, const std::string& data)
{
RuntimeLexer lexer(data);
diff --git a/src/crowsite/site/home.cpp b/src/crowsite/site/home.cpp
index 194269b..f10b9f0 100644
--- a/src/crowsite/site/home.cpp
+++ b/src/crowsite/site/home.cpp
@@ -4,8 +4,103 @@
* See LICENSE file for license detail
*/
#include
+#include
+#include
namespace cs
{
-
+
+ crow::response handle_root_page(const site_params& params)
+ {
+ //auto page = crow::mustache::load("index.html"); //
+ //return "Hello ThereSuck 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");
+ }
+
+ crow::response handle_auth_page(const site_params& params)
+ {
+ if (isUserAdmin(params.app, params.req))
+ return redirect("/login.html");
+
+
+ return handle_root_page(params);
+ }
+
+ crow::response handle_login_request(const crow::request& req, CrowApp& app)
+ {
+ cs::parser::Post pp(req.body);
+ auto& session = app.get_context(req);
+
+ std::string user_agent;
+
+ for (const auto& h : req.headers)
+ if (h.first == "User-Agent")
+ {
+ user_agent = h.second;
+ break;
+ }
+
+ // either cs::redirect to clear the form if failed or pass user to index
+ if (cs::checkUserAuthorization(pp))
+ {
+ cs::cookie_data data = cs::createUserAuthTokens(pp, user_agent);
+ if (!cs::storeUserData(pp["username"], user_agent, data))
+ {
+ BLT_ERROR("Failed to update user data");
+ return cs::redirect("login.html");
+ }
+
+ session.set("clientID", data.clientID);
+ session.set("clientToken", data.clientToken);
+ if (pp.hasKey("remember_me") && pp["remember_me"][0] == 'T')
+ {
+ auto& cookie_context = app.get_context(req);
+ cookie_context.set_cookie("clientID", data.clientID).path("/").max_age(cookie_age);
+ cookie_context.set_cookie("clientToken", data.clientToken).path("/").max_age(cookie_age);
+ }
+ return cs::redirect(pp.hasKey("referer") ? pp["referer"] : "/");
+ } else
+ return cs::redirect("login.html");
+ }
}
\ No newline at end of file
diff --git a/src/crowsite/site/posts.cpp b/src/crowsite/site/posts.cpp
index 133f86a..2617411 100644
--- a/src/crowsite/site/posts.cpp
+++ b/src/crowsite/site/posts.cpp
@@ -8,29 +8,57 @@
#include
#include
#include
+#include
+#include
namespace cs
{
+ sql::database* posts_database;
response_info handleProjectPage(const request_info& req)
{
- std::string buffer;
- buffer += "";
- auto htmlData = loadMarkdownAsHTML(cs::fs::createDataFilePath("Billionaire Propaganda.md"));
- buffer += htmlData;
- buffer += "";
+ if (req.url_params.contains("post"))
+ {
+ BLT_TRACE(req.url_params.at("post"));
+ sql::statement posts(posts_database, "SELECT file FROM posts WHERE postID=?;");
+ posts.set(req.url_params.at("post"), 0);
+ posts.execute();
+ return {loadMarkdownAsHTML(cs::fs::createDataFilePath(posts.get(2)))};
+ }
- return {buffer};
+ return {""};
}
void posts_init()
{
-
+
+ posts_database = new sql::database(cs::fs::createDataFilePath("db/posts.sqlite"));
+
+ sql::auto_statement(
+ posts_database,
+ "CREATE TABLE IF NOT EXISTS posts(postID INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT, title TEXT, file TEXT);"
+ );
+
+ sql::auto_statement(
+ posts_database,
+ "CREATE TABLE IF NOT EXISTS modifications(postID INTEGER, date TEXT, FOREIGN KEY(postID) REFERENCES posts(postID));"
+ );
+
+ sql::auto_statement(
+ posts_database,
+ "CREATE TABLE IF NOT EXISTS tags(postID INTEGER, tag TEXT, FOREIGN KEY(postID) REFERENCES posts(postID));"
+ );
+
+ sql::auto_statement(
+ posts_database,
+ "CREATE TABLE IF NOT EXISTS types(postID INTEGER, type INTEGER, FOREIGN KEY(postID) REFERENCES posts(postID));"
+ );
+
}
void posts_cleanup()
{
-
+ delete posts_database;
}
diff --git a/src/crowsite/site/routing.cpp b/src/crowsite/site/routing.cpp
new file mode 100644
index 0000000..305f3d6
--- /dev/null
+++ b/src/crowsite/site/routing.cpp
@@ -0,0 +1,69 @@
+/*
+ * Created by Brett on 01/09/23.
+ * Licensed under GNU General Public License V3.0
+ * See LICENSE file for license detail
+ */
+#include
+#include
+#include "crowsite/util/crow_session_util.h"
+#include "crowsite/utility.h"
+#include "crowsite/util/crow_conversion.h"
+#include "crowsite/site/home.h"
+
+namespace cs
+{
+ inline void createLoginRoutes(CrowApp& app, CacheEngine& engine)
+ {
+ CROW_ROUTE(app, "/login.html")(
+ [&app, &engine](const crow::request& req) -> crow::response {
+ if (cs::isUserLoggedIn(app, req))
+ return cs::redirect("/");
+ return cs::handle_root_page({app, engine, req, "login.html"});
+ }
+ );
+
+ CROW_ROUTE(app, "/logout.html")(
+ [&app](const crow::request& req) -> crow::response {
+ cs::destroyUserSession(app, req);
+ return cs::redirect("/");
+ }
+ );
+
+ CROW_ROUTE(app, "/res/login").methods(crow::HTTPMethod::POST)(
+ [&app](const crow::request& req) {
+ return cs::handle_login_request(req, app);
+ }
+ );
+ }
+
+ void establishHomeRoutes(CrowApp& app, CacheEngine& engine)
+ {
+ CROW_ROUTE(app, "/favicon.ico")(
+ [](crow::response& local_fav_res) {
+ local_fav_res.compressed = false;
+ local_fav_res.set_static_file_info_unsafe(cs::fs::createStaticFilePath("images/favicon.ico"));
+ local_fav_res.set_header("content-type", "image/x-icon");
+ local_fav_res.end();
+ }
+ );
+
+ createLoginRoutes(app, engine);
+
+ CROW_ROUTE(app, "/")(
+ [&app, &engine](const crow::request& req, const std::string& name) -> crow::response {
+ return cs::handle_root_page({app, engine, req, name});
+ }
+ );
+
+ CROW_ROUTE(app, "/")(
+ [&engine, &app](const crow::request& req) {
+ return cs::handle_root_page({app, engine, req, "index.html"});
+ }
+ );
+ }
+
+ void establishProjectRoutes(CrowApp& app, CacheEngine& engine)
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/crowsite/utility.cpp b/src/crowsite/utility.cpp
index 2c57374..5f59452 100644
--- a/src/crowsite/utility.cpp
+++ b/src/crowsite/utility.cpp
@@ -55,13 +55,13 @@ namespace cs
{
std::string createStaticFilePath(const std::string& file)
{
- auto path = std::string(CROWSITE_STATIC_DIRECTORY);
+ auto path = std::string(CROW_STATIC_DIRECTORY);
if (!path.ends_with('/'))
path += '/';
path += file;
// prevent crow from hanging web responses when we make a typo in the filename
- if (!std::filesystem::exists(path))
- throw std::runtime_error("Unable to create file path because file does not exist!");
+ if (!std::filesystem::exists(path.substr(0, path.find_last_of('/'))))
+ throw std::runtime_error("Unable to create file path because path does not exist!");
return path;
}
@@ -72,8 +72,8 @@ namespace cs
path += '/';
path += "webcontent/";
path += file;
- if (!std::filesystem::exists(path))
- throw std::runtime_error("Unable to create file path because file does not exist!");
+ if (!std::filesystem::exists(path.substr(0, path.find_last_of('/'))))
+ throw std::runtime_error("Unable to create file path because folder does not exist!");
return path;
}
@@ -84,8 +84,8 @@ namespace cs
path += '/';
path += "data/";
path += file;
- if (!std::filesystem::exists(path))
- throw std::runtime_error("Unable to create file path because file does not exist!");
+ if (!std::filesystem::exists(path.substr(0, path.find_last_of('/'))))
+ throw std::runtime_error("Unable to create file path because folder does not exist!");
return path;
}
}
diff --git a/src/main.cpp b/src/main.cpp
index 2849805..cfcd5f2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,11 +11,7 @@
#include
#include
#include
-
-#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", ""); \
+#include
int main(int argc, const char** argv)
{
@@ -27,6 +23,7 @@ int main(int argc, const char** argv)
blt::arg_parse parser;
parser.addArgument(blt::arg_builder("--tests").setAction(blt::arg_action_t::STORE_TRUE).build());
+ parser.addArgument(blt::arg_builder("--standalone").setAction(blt::arg_action_t::STORE_TRUE).build());
parser.addArgument(blt::arg_builder({"--port", "-p"}).setDefault(8080).build());
parser.addArgument(blt::arg_builder("token").setRequired().build());
auto args = parser.parse_args(argc, argv);
@@ -39,17 +36,14 @@ int main(int argc, const char** argv)
static BLT_CrowLogger bltCrowLogger{};
crow::logger::setHandler(&bltCrowLogger);
- const auto session_age = 24 * 60 * 60;
- const auto cookie_age = 180 * 24 * 60 * 60;
-
BLT_INFO("Init Crow with compression and logging enabled!");
CrowApp app{Session{
// customize cookies
- crow::CookieParser::Cookie("session").max_age(session_age).path("/"),
+ crow::CookieParser::Cookie("session").max_age(cs::session_age).path("/"),
// set session id length (small value only for demonstration purposes)
16,
// init the store
- crow::FileStore{std::string(CROWSITE_FILES_PATH) + "/data/session", session_age}}};
+ crow::FileStore{std::string(CROWSITE_FILES_PATH) + "/data/session", cs::session_age}}};
app.use_compression(crow::compression::GZIP);
app.loglevel(crow::LogLevel::WARNING);
@@ -74,73 +68,7 @@ int main(int argc, const char** argv)
BLT_INFO("Creating routes");
- CROW_ROUTE(app, "/favicon.ico")(
- [](crow::response& local_fav_res) {
- local_fav_res.compressed = false;
- local_fav_res.set_static_file_info_unsafe(cs::fs::createStaticFilePath("images/favicon.ico"));
- local_fav_res.set_header("content-type", "image/x-icon");
- local_fav_res.end();
- }
- );
-
- CROW_ROUTE(app, "/login.html")(
- [&app, &engine](const crow::request& req) -> crow::response {
- if (cs::isUserLoggedIn(app, req))
- return cs::redirect("/");
- return cs::handle_root_page({app, engine, req, "login.html"});
- }
- );
-
- CROW_ROUTE(app, "/logout.html")(
- [&app](const crow::request& req) -> crow::response {
- cs::destroyUserSession(app, req);
- return cs::redirect("/");
- }
- );
-
- CROW_ROUTE(app, "/")(
- [&app, &engine](const crow::request& req, const std::string& name) -> crow::response {
- return cs::handle_root_page({app, engine, req, name});
- }
- );
-
- CROW_ROUTE(app, "/res/login").methods(crow::HTTPMethod::POST)(
- [&app](const crow::request& req) {
- cs::parser::Post pp(req.body);
- auto& session = app.get_context(req);
-
- std::string user_agent;
-
- for (const auto& h : req.headers)
- if (h.first == "User-Agent")
- {
- user_agent = h.second;
- break;
- }
-
- // either cs::redirect to clear the form if failed or pass user to index
- if (cs::checkUserAuthorization(pp))
- {
- cs::cookie_data data = cs::createUserAuthTokens(pp, user_agent);
- if (!cs::storeUserData(pp["username"], user_agent, data))
- {
- BLT_ERROR("Failed to update user data");
- return cs::redirect("login.html");
- }
-
- session.set("clientID", data.clientID);
- session.set("clientToken", data.clientToken);
- if (pp.hasKey("remember_me") && pp["remember_me"][0] == 'T')
- {
- auto& cookie_context = app.get_context(req);
- cookie_context.set_cookie("clientID", data.clientID).path("/").max_age(cookie_age);
- cookie_context.set_cookie("clientToken", data.clientToken).path("/").max_age(cookie_age);
- }
- return cs::redirect(pp.hasKey("referer") ? pp["referer"] : "/");
- } else
- return cs::redirect("login.html");
- }
- );
+ cs::establishHomeRoutes(app, engine);
CROW_ROUTE(app, "/projects/")(
[&engine, &app](const crow::request& req, const std::string& path) {
@@ -162,12 +90,6 @@ int main(int argc, const char** argv)
}
);
- CROW_ROUTE(app, "/")(
- [&engine, &app](const crow::request& req) {
- return cs::handle_root_page({app, engine, req, "index.html"});
- }
- );
-
CROW_CATCHALL_ROUTE(app)(
[&engine]() {
return engine.fetch("default.html");
@@ -187,9 +109,27 @@ int main(int argc, const char** argv)
}
}
);
+
+// int flags = fcntl(0, F_GETFL, 0);
+// fcntl(0, F_SETFL, flags | O_NONBLOCK);
+
auto port = blt::arg_parse::get_cast(args["port"]);
BLT_INFO("Starting Crow website on port %d", port);
- app.port(port).multithreaded().run();
+
+ if (args.contains("standalone"))
+ {
+ auto crw = app.port(port).multithreaded().run_async();
+ std::string line;
+ while (crw.valid())
+ {
+ //std::cin.clear(std::ios::badbit | std::ios::failbit | std::ios::eofbit);
+ std::getline(std::cin, line);
+
+ if (!line.empty())
+ BLT_TRACE(line);
+ }
+ } else
+ app.port(port).multithreaded().run();
cs::posts_cleanup();