Maurice Grönwoldt
5bb68a7d02
We have no make install support... so we don't need to have everything as a single-header and lib file.
123 lines
3.3 KiB
C++
123 lines
3.3 KiB
C++
#include "Includes/PreMiddleWare.h"
|
|
#include "StringUtils.h"
|
|
|
|
#include <random>
|
|
#include <sstream>
|
|
|
|
namespace VWeb {
|
|
#pragma region AUTH
|
|
PreMiddleWareReturn AuthWare::PreHandle(Request &request) {
|
|
if (m_AuthFunction)
|
|
return m_AuthFunction(request);
|
|
return {};
|
|
}
|
|
|
|
#pragma endregion AUTH
|
|
|
|
#pragma region SESSION
|
|
|
|
static std::string GenerateSID() {
|
|
static std::random_device dev;
|
|
static std::mt19937 rng(dev());
|
|
|
|
std::uniform_int_distribution<int> dist(0, 15);
|
|
|
|
const char *v = "0123456789abcdef";
|
|
const bool dashArray[] = {false, false, false, false, true, false,
|
|
true, false, true, false, true, false,
|
|
false, false, false, false};
|
|
|
|
std::stringstream res;
|
|
for (bool dash : dashArray) {
|
|
if (dash)
|
|
res << "-";
|
|
res << v[dist(rng)];
|
|
res << v[dist(rng)];
|
|
}
|
|
return res.str();
|
|
}
|
|
|
|
SessionManager::SessionManager() {
|
|
m_GCThread = CreateRef<std::thread>([this]() {
|
|
while (m_IsRunning) {
|
|
if (m_Counter == 59) {
|
|
GC();
|
|
m_Counter = -1;
|
|
}
|
|
m_Counter++;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
|
}
|
|
});
|
|
}
|
|
SessionManager::~SessionManager() {
|
|
m_IsRunning = false;
|
|
m_GCThread->join();
|
|
}
|
|
|
|
PreMiddleWareReturn SessionManager::PreHandle(Request &request) {
|
|
auto &cookies = request.CookieData;
|
|
if (!cookies->Has("sid"))
|
|
return {};
|
|
auto &cookie = cookies->Get("sid");
|
|
std::lock_guard<std::mutex> lck(m_Mutex);
|
|
if (!m_Sessions.contains(cookie.Value))
|
|
return {};
|
|
auto &session = m_Sessions[cookie.Value];
|
|
session->Update();
|
|
request.SessionData = session;
|
|
return {};
|
|
}
|
|
|
|
bool SessionManager::PostHandle(Request &request, Response &response) {
|
|
if (response.SessionData->Id.empty() &&
|
|
response.SessionData->ContainsData()) {
|
|
response.SessionData->Update();
|
|
{
|
|
std::lock_guard<std::mutex> lck(m_Mutex);
|
|
response.SessionData->Id = GenerateSID();
|
|
while (m_Sessions.contains(response.SessionData->Id))
|
|
response.SessionData->Id = GenerateSID();
|
|
}
|
|
m_Sessions[response.SessionData->Id] = response.SessionData;
|
|
auto &sidCookie = response.CookieData->Get("sid");
|
|
sidCookie.Name = "sid";
|
|
sidCookie.HttpOnly = true;
|
|
sidCookie.SameSite = CookieSameSite::Strict;
|
|
sidCookie.Value = response.SessionData->Id;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SessionManager::GC() {
|
|
std::lock_guard<std::mutex> lck(m_Mutex);
|
|
std::vector<std::string_view> mark_as_delete;
|
|
for (auto &itemToCollect : m_Sessions) {
|
|
if (!itemToCollect.second->IsValid())
|
|
mark_as_delete.push_back(itemToCollect.first);
|
|
}
|
|
|
|
for (auto &i : mark_as_delete)
|
|
m_Sessions.erase(i.data());
|
|
}
|
|
#pragma endregion SESSION
|
|
#pragma region COOKIES
|
|
PreMiddleWareReturn CookieManager::PreHandle(Request &request) {
|
|
auto &cookieHeaders = request.Header("cookie");
|
|
auto &cookies = request.CookieData;
|
|
if (cookieHeaders.Size() > 0) {
|
|
auto &values = cookieHeaders.Values();
|
|
for (auto &rawCookie : values) {
|
|
auto splitCookies = String::Split(rawCookie, ";");
|
|
for (auto &cookie : splitCookies) {
|
|
auto split = String::Split(cookie, "=");
|
|
String::Trim(split[0]);
|
|
String::Trim(split[1]);
|
|
cookies->CreateOld(split[0], split[1]);
|
|
}
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
#pragma endregion COOKIES
|
|
} // namespace VWeb
|