Reworked HTTPSession, now it uses Variants instead of multiple classes. Also it's inherited from Reference now. Also smaller cleanups to the SessionManager.

This commit is contained in:
Relintai 2022-01-09 14:32:09 +01:00
parent bede579bf6
commit a119251e09
8 changed files with 102 additions and 115 deletions

View File

@ -1,58 +1,48 @@
#include "http_session.h" #include "http_session.h"
void HTTPSession::add_object(const String &key, Object *obj) { void HTTPSession::add(const String &key, const Variant &value) {
std::lock_guard<std::mutex> lock(_mutex); _mutex.lock();
_data[key] = obj; _data[key] = value;
_mutex.unlock();
} }
void HTTPSession::remove_object(const String &key) { void HTTPSession::remove(const String &key) {
std::lock_guard<std::mutex> lock(_mutex); _mutex.lock();
_data.erase(key); _data[key] = Variant();
_mutex.unlock();
}
bool HTTPSession::has(const String &key) {
return _data[key].is_null();
} }
Object *HTTPSession::get_object(const String &key) {
//don't lock here
Variant HTTPSession::get(const String &key) {
return _data[key]; return _data[key];
} }
void HTTPSession::add_reference(const String &key, const Ref<Reference> &ref) { Object *HTTPSession::get_object(const String &key) {
std::lock_guard<std::mutex> lock(_mutex); // don't lock here
_reference_data[key] = ref; return _data[key].to_object();
} }
void HTTPSession::remove_reference(const String &key) {
std::lock_guard<std::mutex> lock(_mutex);
_reference_data.erase(key);
}
Ref<Reference> HTTPSession::get_reference(const String &key) { Ref<Reference> HTTPSession::get_reference(const String &key) {
// don't lock here // don't lock here
return _reference_data[key]; return _data[key].to_reference();
} }
void HTTPSession::add_int(const String &key, const int val) {
std::lock_guard<std::mutex> lock(_mutex);
_int_data[key] = val;
}
void HTTPSession::remove_int(const String &key) {
std::lock_guard<std::mutex> lock(_mutex);
_int_data.erase(key);
}
int HTTPSession::get_int(const String &key) { int HTTPSession::get_int(const String &key) {
// don't lock here // don't lock here
return _int_data[key]; return _data[key].to_int();
} }
void HTTPSession::clear() { void HTTPSession::clear() {
_data.clear(); _data.clear();
_int_data.clear();
_reference_data.clear();
} }
void HTTPSession::reset() { void HTTPSession::reset() {
@ -60,8 +50,8 @@ void HTTPSession::reset() {
session_id = ""; session_id = "";
} }
std::map<String, int> HTTPSession::get_int_data() { std::map<String, Variant> *HTTPSession::get_data() {
return _int_data; return &_data;
} }
HTTPSession::HTTPSession() { HTTPSession::HTTPSession() {

View File

@ -1,27 +1,26 @@
#ifndef HTTP_SESSION_H #ifndef HTTP_SESSION_H
#define HTTP_SESSION_H #define HTTP_SESSION_H
#include "core/string.h"
#include "core/object.h"
#include "core/reference.h"
#include <map> #include <map>
#include <mutex>
class HTTPSession : public Object { #include "core/reference.h"
RCPP_OBJECT(HTTPSession, Object);
#include "core/string.h"
#include "core/variant.h"
#include "core/threading/mutex.h"
class HTTPSession : public Reference {
RCPP_OBJECT(HTTPSession, Reference);
public: public:
void add_object(const String &key, Object *obj); void add(const String &key, const Variant &value);
void remove_object(const String &key); void remove(const String &key);
bool has(const String &key);
Variant get(const String &key);
Object *get_object(const String &key); Object *get_object(const String &key);
void add_reference(const String &key, const Ref<Reference> &ref);
void remove_reference(const String &key);
Ref<Reference> get_reference(const String &key); Ref<Reference> get_reference(const String &key);
void add_int(const String &key, const int val);
void remove_int(const String &key);
int get_int(const String &key); int get_int(const String &key);
String session_id; String session_id;
@ -30,18 +29,15 @@ public:
void clear(); void clear();
void reset(); void reset();
std::map<String, int> get_int_data(); std::map<String, Variant> *get_data();
HTTPSession(); HTTPSession();
~HTTPSession(); ~HTTPSession();
protected: protected:
std::mutex _mutex; Mutex _mutex;
//todo make something similar to godot's variant. (Or get godot's variant lol) std::map<String, Variant> _data;
std::map<String, Object *> _data;
std::map<String, Ref<Reference> > _reference_data;
std::map<String, int> _int_data;
}; };
#endif #endif

View File

@ -8,8 +8,8 @@
#include "core/http/web_root.h" #include "core/http/web_root.h"
#include "session_manager.h" #include "session_manager.h"
HTTPSession *Request::get_or_create_session() { Ref<HTTPSession> Request::get_or_create_session() {
if (session) { if (session.is_valid()) {
return session; return session;
} }

View File

@ -34,11 +34,11 @@ public:
bool connection_closed; bool connection_closed;
HTTPSession *session; Ref<HTTPSession> session;
std::map<String, Object *> data; std::map<String, Object *> data;
std::map<String, Ref<Reference> > reference_data; std::map<String, Ref<Reference> > reference_data;
HTTPSession *get_or_create_session(); Ref<HTTPSession> get_or_create_session();
virtual const String get_cookie(const String &key); virtual const String get_cookie(const String &key);
virtual void add_cookie(const ::Cookie &cookie); virtual void add_cookie(const ::Cookie &cookie);

View File

@ -15,25 +15,27 @@
#include "cookie.h" #include "cookie.h"
void SessionManager::add_session(HTTPSession *session) { void SessionManager::add_session(Ref<HTTPSession> &session) {
if (!session) { if (!session.is_valid()) {
printf("SessionManager::add_session: ERROR, session is null!\n"); printf("SessionManager::add_session: ERROR, session is null!\n");
return; return;
} }
std::lock_guard<std::mutex> lock(_mutex); _mutex.lock();
_sessions_vec.push_back(session); _sessions_vec.push_back(session);
_sessions[session->session_id] = session; _sessions[session->session_id] = session;
_mutex.unlock();
} }
void SessionManager::remove_session(HTTPSession *session) { void SessionManager::remove_session(Ref<HTTPSession> &session) {
if (!session) { if (!session.is_valid()) {
printf("SessionManager::remove_session: ERROR, session is null!\n"); printf("SessionManager::remove_session: ERROR, session is null!\n");
return; return;
} }
std::lock_guard<std::mutex> lock(_mutex); _mutex.lock();
_sessions.erase(session->session_id); _sessions.erase(session->session_id);
@ -41,20 +43,23 @@ void SessionManager::remove_session(HTTPSession *session) {
if (_sessions_vec[i] == session) { if (_sessions_vec[i] == session) {
_sessions_vec[i] = _sessions_vec[_sessions_vec.size() - 1]; _sessions_vec[i] = _sessions_vec[_sessions_vec.size() - 1];
_sessions_vec.pop_back(); _sessions_vec.pop_back();
_mutex.unlock();
return; return;
} }
} }
_mutex.unlock();
} }
void SessionManager::delete_session(const String &session_id) { void SessionManager::delete_session(const String &session_id) {
_mutex.lock(); _mutex.lock();
HTTPSession *s = _sessions[session_id]; Ref<HTTPSession> s = _sessions[session_id];
_sessions.erase(session_id); _sessions.erase(session_id);
for (int i = 0; i < _sessions_vec.size(); ++i) { for (int i = 0; i < _sessions_vec.size(); ++i) {
HTTPSession *sess = _sessions_vec[i]; Ref<HTTPSession> sess = _sessions_vec[i];
if (sess->session_id == session_id) { if (sess->session_id == session_id) {
@ -67,13 +72,11 @@ void SessionManager::delete_session(const String &session_id) {
_mutex.unlock(); _mutex.unlock();
if (!s) { if (!s.is_valid()) {
return; return;
} }
if (!s->id) { if (!s->id) {
delete s;
return; return;
} }
@ -82,11 +85,9 @@ void SessionManager::delete_session(const String &session_id) {
b->del(_data_table_name)->where()->wp("session_db_id", s->id)->end_command(); b->del(_data_table_name)->where()->wp("session_db_id", s->id)->end_command();
b->del(_table_name)->where()->wp("id", s->id)->end_command(); b->del(_table_name)->where()->wp("id", s->id)->end_command();
b->run_query(); b->run_query();
delete s;
} }
void SessionManager::save_session(HTTPSession *session) { void SessionManager::save_session(Ref<HTTPSession> &session) {
Ref<QueryBuilder> b = DatabaseManager::get_singleton()->ddb->get_query_builder(); Ref<QueryBuilder> b = DatabaseManager::get_singleton()->ddb->get_query_builder();
if (!session->id) { if (!session->id) {
@ -105,39 +106,41 @@ void SessionManager::save_session(HTTPSession *session) {
b->del(_data_table_name)->where()->wp("session_db_id", session->id)->end_command(); b->del(_data_table_name)->where()->wp("session_db_id", session->id)->end_command();
int id = session->id; int id = session->id;
std::map<String, int> m = session->get_int_data(); std::map<String, Variant> *m = session->get_data();
for (std::map<String, int>::iterator it = m.begin(); it != m.end(); it++) { for (std::map<String, Variant>::iterator it = m->begin(); it != m->end(); it++) {
b->insert(_data_table_name, "session_db_id, key, value")->values()->val(id)->val(it->first)->val(it->second)->cvalues()->end_command(); const Variant &val = it->second;
if (val.is_simple_type()) {
b->insert(_data_table_name, "session_db_id,key,value")->values()->val(id)->val(it->first)->val(val.to_string())->cvalues()->end_command();
}
} }
b->run_query(); b->run_query();
} }
HTTPSession *SessionManager::get_session(const String &session_id) { Ref<HTTPSession> SessionManager::get_session(const String &session_id) {
return _sessions[session_id]; return _sessions[session_id];
} }
HTTPSession *SessionManager::create_session() { Ref<HTTPSession> SessionManager::create_session() {
HTTPSession *session = new HTTPSession(); Ref<HTTPSession> session = new HTTPSession();
std::unique_lock<std::mutex> lock(_mutex, std::defer_lock);
while (true) { while (true) {
session->session_id = generate_session_id(session->session_id); session->session_id = generate_session_id(session->session_id);
lock.lock(); _mutex.lock();
if (_sessions[session->session_id] == nullptr) { if (_sessions[session->session_id] == nullptr) {
_sessions_vec.push_back(session); _sessions_vec.push_back(session);
_sessions[session->session_id] = session; _sessions[session->session_id] = session;
lock.unlock(); _mutex.unlock();
return session; return session;
} }
lock.unlock(); _mutex.unlock();
} }
save_session(session); save_session(session);
@ -159,7 +162,7 @@ void SessionManager::load_sessions() {
int id = r->get_cell_int(0); int id = r->get_cell_int(0);
String session_id = r->get_cell(1); String session_id = r->get_cell(1);
HTTPSession *s = new HTTPSession(); Ref<HTTPSession> s = new HTTPSession();
s->id = id; s->id = id;
s->session_id = session_id; s->session_id = session_id;
@ -177,39 +180,37 @@ void SessionManager::load_sessions() {
while (r->next_row()) { while (r->next_row()) {
int session_db_id = r->get_cell_int(0); int session_db_id = r->get_cell_int(0);
HTTPSession *s = nullptr; Ref<HTTPSession> s;
for (int i = 0; i < _sessions_vec.size(); ++i) { for (int i = 0; i < _sessions_vec.size(); ++i) {
HTTPSession *ss = _sessions_vec[i]; Ref<HTTPSession> ss = _sessions_vec[i];
if (ss && session_db_id == ss->id) { if (ss.is_valid() && session_db_id == ss->id) {
s = ss; s = ss;
break; break;
} }
} }
if (!s) { if (!s.is_valid()) {
printf("Error: SessionManager::load_sessions(): %d sid doesn't exists!\n", session_db_id); printf("Error: SessionManager::load_sessions(): %d sid doesn't exists!\n", session_db_id);
continue; continue;
} }
String key = r->get_cell(1); String key = r->get_cell(1);
int value = r->get_cell_int(2); String value = r->get_cell(2);
s->add_int(key, value); s->add(key, Variant::parse_string(value));
} }
} }
void SessionManager::clear() { void SessionManager::clear() {
std::lock_guard<std::mutex> lock(_mutex); _mutex.lock();
for (int i = 0; i < _sessions_vec.size(); ++i) {
delete _sessions_vec[i];
}
_sessions.clear(); _sessions.clear();
_sessions_vec.clear(); _sessions_vec.clear();
_mutex.unlock();
} }
String SessionManager::generate_session_id(const String &base) { String SessionManager::generate_session_id(const String &base) {
@ -250,7 +251,7 @@ void SessionManager::create_table() {
tb->create_table(_data_table_name); tb->create_table(_data_table_name);
tb->integer("session_db_id")->not_null()->next_row(); tb->integer("session_db_id")->not_null()->next_row();
tb->varchar("key", 100)->next_row(); tb->varchar("key", 100)->next_row();
tb->integer("value")->not_null()->next_row(); tb->text("value")->not_null()->next_row();
tb->foreign_key("session_db_id"); tb->foreign_key("session_db_id");
tb->references(_table_name, "id"); tb->references(_table_name, "id");
tb->ccreate_table(); tb->ccreate_table();

View File

@ -3,7 +3,7 @@
#include "core/string.h" #include "core/string.h"
#include "core/containers/vector.h" #include "core/containers/vector.h"
#include <mutex> #include "core/threading/mutex.h"
#include <map> #include <map>
#include "core/object.h" #include "core/object.h"
@ -17,12 +17,12 @@ class SessionManager : public Object {
RCPP_OBJECT(SessionManager, Object); RCPP_OBJECT(SessionManager, Object);
public: public:
void add_session(HTTPSession *session); void add_session(Ref<HTTPSession> &session);
void remove_session(HTTPSession *session); void remove_session(Ref<HTTPSession> &session);
void delete_session(const String &session_id); void delete_session(const String &session_id);
void save_session(HTTPSession *session); void save_session(Ref<HTTPSession> &session);
HTTPSession *get_session(const String &session_id); Ref<HTTPSession> get_session(const String &session_id);
HTTPSession *create_session(); Ref<HTTPSession> create_session();
void load_sessions(); void load_sessions();
@ -39,9 +39,9 @@ public:
SessionManager(); SessionManager();
~SessionManager(); ~SessionManager();
std::map<String, HTTPSession *> _sessions; std::map<String, Ref<HTTPSession>> _sessions;
Vector<HTTPSession *> _sessions_vec; Vector<Ref<HTTPSession>> _sessions_vec;
std::mutex _mutex; Mutex _mutex;
protected: protected:
static SessionManager *_self; static SessionManager *_self;

View File

@ -59,7 +59,7 @@ RBACUserController::~RBACUserController() {
// returnring true means handled, false means continue // returnring true means handled, false means continue
bool RBACUserSessionSetupMiddleware::on_before_handle_request_main(Request *request) { bool RBACUserSessionSetupMiddleware::on_before_handle_request_main(Request *request) {
if (request->session) { if (request->session.is_valid()) {
int user_id = request->session->get_int("user_id"); int user_id = request->session->get_int("user_id");
if (user_id != 0) { if (user_id != 0) {
@ -70,7 +70,7 @@ bool RBACUserSessionSetupMiddleware::on_before_handle_request_main(Request *requ
request->reference_data["user"] = u; request->reference_data["user"] = u;
} else { } else {
// log // log
request->session->remove_int("user_id"); request->session->remove("user_id");
} }
} }
} }
@ -89,7 +89,7 @@ bool RBACDefaultUserSessionSetupMiddleware::on_before_handle_request_main(Reques
Ref<RBACRank> rank; Ref<RBACRank> rank;
if (request->session) { if (request->session.is_valid()) {
int user_id = request->session->get_int("user_id"); int user_id = request->session->get_int("user_id");
if (user_id != 0) { if (user_id != 0) {
@ -102,7 +102,7 @@ bool RBACDefaultUserSessionSetupMiddleware::on_before_handle_request_main(Reques
request->reference_data["user"] = u; request->reference_data["user"] = u;
} else { } else {
// log // log
request->session->remove_int("user_id"); request->session->remove("user_id");
} }
} }
} }

View File

@ -16,7 +16,7 @@
#include "core/hash/sha256.h" #include "core/hash/sha256.h"
void UserController::handle_request_main(Request *request) { void UserController::handle_request_main(Request *request) {
if (request->session) { if (request->session.is_valid()) {
Ref<User> u = request->reference_data["user"]; Ref<User> u = request->reference_data["user"];
if (u.is_valid()) { if (u.is_valid()) {
@ -68,9 +68,9 @@ void UserController::handle_login_request_default(Request *request) {
if (!check_password(user, data.pass_val)) { if (!check_password(user, data.pass_val)) {
data.error_str += "Invalid username or password!"; data.error_str += "Invalid username or password!";
} else { } else {
HTTPSession *session = request->get_or_create_session(); Ref<HTTPSession> session = request->get_or_create_session();
session->add_int("user_id", user->id); session->add("user_id", user->id);
SessionManager::get_singleton()->save_session(session); SessionManager::get_singleton()->save_session(session);
::Cookie c = ::Cookie("session_id", session->session_id); ::Cookie c = ::Cookie("session_id", session->session_id);
@ -794,7 +794,7 @@ String UserController::_table_name = "users";
// returnring true means handled, false means continue // returnring true means handled, false means continue
bool UserSessionSetupMiddleware::on_before_handle_request_main(Request *request) { bool UserSessionSetupMiddleware::on_before_handle_request_main(Request *request) {
if (request->session) { if (request->session.is_valid()) {
int user_id = request->session->get_int("user_id"); int user_id = request->session->get_int("user_id");
if (user_id != 0) { if (user_id != 0) {
@ -805,7 +805,7 @@ bool UserSessionSetupMiddleware::on_before_handle_request_main(Request *request)
request->reference_data["user"] = u; request->reference_data["user"] = u;
} else { } else {
// log // log
request->session->remove_int("user_id"); request->session->remove("user_id");
} }
} }
} }