precompiled headers
parent
0c8ab4f082
commit
7c4c4ee28f
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/static/css/index.css">
|
||||
<style>
|
||||
{{@../static/css/menu_bar.css}}
|
||||
{{@../static/css/body.css}}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="description" content="">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="author" content="Brett">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{$SITE_TITLE}}</title>
|
||||
</head>
|
||||
{{@body_begin.part}}
|
||||
<div class="body">
|
||||
<div class="center">
|
||||
{{CURRENT_POST}}
|
||||
</div>
|
||||
</div>
|
||||
{{@body_end.part}}
|
||||
</html>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/static/css/index.css">
|
||||
<style>
|
||||
{{@../static/css/menu_bar.css}}
|
||||
{{@../static/css/body.css}}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="description" content="">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="author" content="Brett">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{$SITE_TITLE}}</title>
|
||||
</head>
|
||||
{{@body_begin.part}}
|
||||
<div class="body">
|
||||
<div class="center">
|
||||
{{CURRENT_POST}}
|
||||
</div>
|
||||
</div>
|
||||
{{@body_end.part}}
|
||||
</html>
|
|
@ -9,7 +9,8 @@
|
|||
#include <blt/std/hashmap.h>
|
||||
|
||||
//#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/<path>"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#ifndef CROWSITE_CROW_PCH_H
|
||||
#define CROWSITE_CROW_PCH_H
|
||||
|
||||
#include <crowsite/config.h>
|
||||
#include "crow/query_string.h"
|
||||
#include "crow/http_parser_merged.h"
|
||||
#include "crow/ci_map.h"
|
||||
|
|
|
@ -8,69 +8,16 @@
|
|||
#ifndef CROWSITE_HOME_H
|
||||
#define CROWSITE_HOME_H
|
||||
|
||||
#include <crowsite/site/cache.h>
|
||||
#include <crowsite/util/crow_session_util.h>
|
||||
#include <crowsite/util/crow_conversion.h>
|
||||
|
||||
namespace cs
|
||||
{
|
||||
|
||||
inline crow::response handle_root_page(const site_params& params)
|
||||
{
|
||||
//auto page = crow::mustache::load("index.html"); //
|
||||
//return "<html><head><title>Hello There</title></head><body><h1>Suck it " + name + "</h1></body></html>";
|
||||
// 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<Session>(params.req);
|
||||
auto s_clientID = session.get("clientID", "");
|
||||
auto s_clientToken = session.get("clientToken", "");
|
||||
auto user_perms = cs::getUserPermissions(cs::getUserFromID(s_clientID));
|
||||
crow::response handle_login_request(const crow::request& req, CrowApp& app);
|
||||
|
||||
crow::mustache::context ctx;
|
||||
cs::context context;
|
||||
crow::response handle_root_page(const site_params& params);
|
||||
|
||||
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);
|
||||
}
|
||||
crow::response handle_auth_page(const site_params& params);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <crowsite/crow_pch.h>
|
||||
#include "crowsite/site/cache.h"
|
||||
|
||||
namespace cs
|
||||
{
|
||||
void establishHomeRoutes(CrowApp& app, CacheEngine& engine);
|
||||
void establishProjectRoutes(CrowApp& app, CacheEngine& engine);
|
||||
}
|
||||
|
||||
#endif //CROWSITE_ROUTING_H
|
|
@ -7,28 +7,109 @@
|
|||
|
||||
#include <sqlite3.h>
|
||||
#include <type_traits>
|
||||
#include <filesystem>
|
||||
#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<int>(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
|
||||
|
|
|
@ -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<Session>(req); \
|
||||
auto s_clientID = session.get("clientID", ""); \
|
||||
auto s_clientToken = session.get("clientToken", ""); \
|
||||
|
||||
#endif //CROWSITE_CROW_SESSION_UTIL_H
|
||||
|
|
2
libs/BLT
2
libs/BLT
|
@ -1 +1 @@
|
|||
Subproject commit d3ed46686eb0667c9824fbba5f90519efd2a50c3
|
||||
Subproject commit 215220f98b0ac4a87fe4a233de16650cf6d0b968
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
@ -298,11 +300,6 @@ namespace cs
|
|||
return str[index] == '{' && str[index + 1] == '{' && str[index + 2] == c;
|
||||
}
|
||||
|
||||
static std::string consumeToEndTemplate(const std::string& tokenName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void getTagLocations(std::vector<size_t>& tagLocations, const std::string& tag, const std::string& data)
|
||||
{
|
||||
RuntimeLexer lexer(data);
|
||||
|
|
|
@ -4,8 +4,103 @@
|
|||
* See LICENSE file for license detail
|
||||
*/
|
||||
#include <crowsite/site/home.h>
|
||||
#include <crowsite/util/crow_conversion.h>
|
||||
#include <blt/std/logging.h>
|
||||
|
||||
namespace cs
|
||||
{
|
||||
|
||||
crow::response handle_root_page(const site_params& params)
|
||||
{
|
||||
//auto page = crow::mustache::load("index.html"); //
|
||||
//return "<html><head><title>Hello There</title></head><body><h1>Suck it " + name + "</h1></body></html>";
|
||||
// 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<Session>(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<Session>(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<crow::CookieParser>(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");
|
||||
}
|
||||
}
|
|
@ -8,29 +8,57 @@
|
|||
#include <crowsite/utility.h>
|
||||
#include <crowsite/util/md_to_html.h>
|
||||
#include <blt/std/logging.h>
|
||||
#include <crowsite/sql_helper.h>
|
||||
#include <blt/std/time.h>
|
||||
|
||||
namespace cs
|
||||
{
|
||||
sql::database* posts_database;
|
||||
|
||||
response_info handleProjectPage(const request_info& req)
|
||||
{
|
||||
std::string buffer;
|
||||
buffer += "<html><head></head><body>";
|
||||
auto htmlData = loadMarkdownAsHTML(cs::fs::createDataFilePath("Billionaire Propaganda.md"));
|
||||
buffer += htmlData;
|
||||
buffer += "</body>";
|
||||
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<std::string>(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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 <crowsite/site/routing.h>
|
||||
#include <blt/std/logging.h>
|
||||
#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, "/<string>")(
|
||||
[&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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
106
src/main.cpp
106
src/main.cpp
|
@ -11,11 +11,7 @@
|
|||
#include <crowsite/site/posts.h>
|
||||
#include <crowsite/util/crow_log.h>
|
||||
#include <crowsite/util/crow_conversion.h>
|
||||
|
||||
#define CS_SESSION cs::checkAndUpdateUserSession(app, req); \
|
||||
auto& session = app.get_context<Session>(req); \
|
||||
auto s_clientID = session.get("clientID", ""); \
|
||||
auto s_clientToken = session.get("clientToken", ""); \
|
||||
#include <crowsite/site/routing.h>
|
||||
|
||||
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, "/<string>")(
|
||||
[&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<Session>(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<crow::CookieParser>(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/<path>")(
|
||||
[&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,8 +109,26 @@ 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<int32_t>(args["port"]);
|
||||
BLT_INFO("Starting Crow website on port %d", port);
|
||||
|
||||
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();
|
||||
|
|
Loading…
Reference in New Issue