diff --git a/crow_test/data/session/.expirations b/crow_test/data/session/.expirations new file mode 100644 index 0000000..55171af --- /dev/null +++ b/crow_test/data/session/.expirations @@ -0,0 +1 @@ +jlbpNSZuchBeVInZ 1692336738 diff --git a/crow_test/data/session/jlbpNSZuchBeVInZ.json b/crow_test/data/session/jlbpNSZuchBeVInZ.json new file mode 100644 index 0000000..9650cf7 --- /dev/null +++ b/crow_test/data/session/jlbpNSZuchBeVInZ.json @@ -0,0 +1 @@ +{"clientID":"2e68464b-a37c-58a2-a970-97fedf56e8f9","clientToken":"00000000-0000-0000-0000-000000000000"} \ No newline at end of file diff --git a/crow_test/webcontent/login.html b/crow_test/webcontent/login.html index 1154fbf..7aaedc3 100644 --- a/crow_test/webcontent/login.html +++ b/crow_test/webcontent/login.html @@ -17,7 +17,9 @@


- +
+
+
diff --git a/include/crowsite/site/auth.h b/include/crowsite/site/auth.h index e6801a0..4e45b5e 100644 --- a/include/crowsite/site/auth.h +++ b/include/crowsite/site/auth.h @@ -6,10 +6,16 @@ #define CROWSITE_AUTH_H #include "crowsite/utility.h" +#include namespace cs { + + struct cookie_data { + std::string clientID; + std::string clientToken; + }; - bool handleLoginPost(cs::parser::Post& postData); + bool handleLoginPost(cs::parser::Post& postData, cookie_data& cookieOut); } diff --git a/src/crowsite/site/auth.cpp b/src/crowsite/site/auth.cpp index 838b412..d55d8b0 100644 --- a/src/crowsite/site/auth.cpp +++ b/src/crowsite/site/auth.cpp @@ -4,10 +4,13 @@ #include #include #include "blt/std/logging.h" +#include "blt/std/uuid.h" + +using namespace blt; namespace cs { - bool handleLoginPost(parser::Post& postData) + bool handleLoginPost(parser::Post& postData, cookie_data& cookieOut) { // javascript should make sure we don't send post requests without information // this way it can be interactive @@ -15,6 +18,9 @@ namespace cs { return false; auto auth = jellyfin::authenticateUser(postData["username"], postData["password"]); + cookieOut.clientID = uuid::toString(uuid::genV5("ClientID?")); + cookieOut.clientToken = uuid::toString(uuid::genV4()); + return auth == jellyfin::auth_response::AUTHORIZED; } } \ No newline at end of file diff --git a/src/crowsite/utility.cpp b/src/crowsite/utility.cpp index 3a23707..6446123 100644 --- a/src/crowsite/utility.cpp +++ b/src/crowsite/utility.cpp @@ -17,6 +17,8 @@ namespace cs { auto stripped_key = curl_easy_unescape(nullptr, key.c_str(), 0, nullptr); auto stripped_value = curl_easy_unescape(nullptr, value.c_str(), 0, nullptr); m_Values[stripped_key] = stripped_value; + curl_free(stripped_key); + curl_free(stripped_value); } } diff --git a/src/main.cpp b/src/main.cpp index 311a5dc..293ec4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include class BLT_CrowLogger : public crow::ILogHandler { @@ -40,6 +42,11 @@ class BLT_CrowLogger : public crow::ILogHandler } }; +inline crow::response redirect(const std::string& loc){ + crow::response res; + res.redirect(loc); + return res; +} int main(int argc, const char** argv) { @@ -57,16 +64,24 @@ int main(int argc, const char** argv) cs::jellyfin::setToken(blt::arg_parse::get(args["token"])); cs::jellyfin::processUserData(); - auto res = cs::jellyfin::authenticateUser(blt::arg_parse::get(args["user"]), blt::arg_parse::get(args["pass"])); - BLT_INFO("Has true: %b", res == cs::jellyfin::auth_response::AUTHORIZED); - BLT_INFO("Starting site %s.", SITE_NAME); crow::mustache::set_global_base(SITE_FILES_PATH); static BLT_CrowLogger bltCrowLogger{}; crow::logger::setHandler(&bltCrowLogger); + using Session = crow::SessionMiddleware; + + const auto session_age = 24 * 60 * 60; + const auto cookie_age = 180 * 24 * 60 * 60; + BLT_INFO("Init Crow with compression and logging enabled!"); - crow::SimpleApp app; + crow::App app {Session{ + // customize cookies + crow::CookieParser::Cookie("session").max_age(session_age).path("/"), + // 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}}}; app.use_compression(crow::compression::GZIP); app.loglevel(crow::LogLevel::WARNING); @@ -126,15 +141,30 @@ int main(int argc, const char** argv) ); CROW_ROUTE(app, "/res/login").methods(crow::HTTPMethod::POST)( - [](const crow::request& req) { + [&app](const crow::request& req) { cs::parser::Post pp(req.body); + auto& session = app.get_context(req); crow::response res(303); + cs::cookie_data data; + // either redirect to clear the form if failed or pass user to index - if (cs::handleLoginPost(pp)) + if (cs::handleLoginPost(pp, data)) + { + session.set("clientID", data.clientID); + session.set("clientToken", data.clientToken); + if (pp.hasKey("remember_me")){ + auto value = pp["remember_me"]; + auto& cookie_context = app.get_context(req); + if (value[0] == 'T') + { + cookie_context.set_cookie("clientID", data.clientID).path("/").max_age(cookie_age); + cookie_context.set_cookie("clientToken", data.clientToken).path("/").max_age(cookie_age); + } + } res.set_header("Location", pp.hasKey("referer") ? pp["referer"] : "/"); - else + } else res.set_header("Location", "/login.html"); return res;