121 lines
3.2 KiB
C++
121 lines
3.2 KiB
C++
|
#include "StringUtils.h"
|
||
|
#include "VWeb.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(const 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.HttpOnly = true;
|
||
|
sidCookie.Secure = true;
|
||
|
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 : cookieHeaders.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
|