diff --git a/core/http/http_session.cpp b/core/http/http_session.cpp index a454f44..b0624ef 100644 --- a/core/http/http_session.cpp +++ b/core/http/http_session.cpp @@ -60,7 +60,12 @@ void HTTPSession::reset() { session_id = ""; } +std::map HTTPSession::get_int_data() { + return _int_data; +} + HTTPSession::HTTPSession() { + id = 0; } HTTPSession::~HTTPSession() { diff --git a/core/http/http_session.h b/core/http/http_session.h index 5cdb79e..e3a9a3e 100644 --- a/core/http/http_session.h +++ b/core/http/http_session.h @@ -22,10 +22,13 @@ public: int get_int(const std::string &key); std::string session_id; + int id; void clear(); void reset(); + std::map get_int_data(); + HTTPSession(); ~HTTPSession(); diff --git a/core/http/session_manager.cpp b/core/http/session_manager.cpp index f35f4c0..221249b 100644 --- a/core/http/session_manager.cpp +++ b/core/http/session_manager.cpp @@ -4,6 +4,11 @@ #include #include +#include "core/database/database_manager.h" +#include "core/database/query_builder.h" +#include "core/database/query_result.h" +#include "core/database/table_builder.h" + #include "core/hash/sha256.h" #include "request.h" @@ -42,7 +47,9 @@ void SessionManager::remove_session(HTTPSession *session) { } void SessionManager::delete_session(const std::string &session_id) { - std::lock_guard lock(_mutex); + _mutex.lock(); + + HTTPSession *s = _sessions[session_id]; _sessions.erase(session_id); @@ -54,11 +61,56 @@ void SessionManager::delete_session(const std::string &session_id) { _sessions_vec[i] = _sessions_vec[_sessions_vec.size() - 1]; _sessions_vec.pop_back(); - delete sess; - - return; + break; } } + + _mutex.unlock(); + + if (!s) { + return; + } + + if (!s->id) { + delete s; + + return; + } + + Ref b = DatabaseManager::get_singleton()->ddb->get_query_builder(); + + 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->run_query(); + + delete s; +} + +void SessionManager::save_session(HTTPSession *session) { + Ref b = DatabaseManager::get_singleton()->ddb->get_query_builder(); + + if (!session->id) { + b->insert(_table_name, "session_id"); + b->values(); + b->val(session->session_id); + b->cvalues(); + b->end_command(); + b->select_last_insert_id(); + + session->id = b->run()->get_last_insert_rowid(); + + b->reset(); + } + + b->del(_data_table_name)->where()->wp("session_db_id", session->id)->end_command(); + int id = session->id; + + std::map m = session->get_int_data(); + for (std::map::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(); + } + + b->run_query(); } HTTPSession *SessionManager::get_session(const std::string &session_id) { @@ -88,9 +140,67 @@ HTTPSession *SessionManager::create_session() { lock.unlock(); } + save_session(session); + return session; } +void SessionManager::load_sessions() { + clear(); + + Ref b = DatabaseManager::get_singleton()->ddb->get_query_builder(); + + b->select("id, session_id"); + b->from(_table_name); + b->print(); + Ref r = b->run(); + + while (r->next_row()) { + int id = r->get_cell_int(0); + std::string session_id = r->get_cell(1); + + HTTPSession *s = new HTTPSession(); + s->id = id; + + s->session_id = session_id; + + add_session(s); + } + + b->reset(); + + b->select("session_db_id, key, value"); + b->from(_data_table_name); + b->print(); + r = b->run(); + + while (r->next_row()) { + int session_db_id = r->get_cell_int(0); + + HTTPSession *s = nullptr; + + for (int i = 0; i < _sessions_vec.size(); ++i) { + HTTPSession *ss = _sessions_vec[i]; + + if (ss && session_db_id == ss->id) { + s = ss; + break; + } + } + + if (!s) { + printf("Error: SessionManager::load_sessions(): %d sid doesn't exists!\n", session_db_id); + + continue; + } + + std::string key = r->get_cell(1); + int value = r->get_cell_int(2); + + s->add_int(key, value); + } +} + void SessionManager::clear() { std::lock_guard lock(_mutex); @@ -139,6 +249,41 @@ void SessionManager::session_setup_middleware(Object *instance, Request *request request->next_stage(); } +void SessionManager::migrate() { + drop_table(); + create_table(); +} + +void SessionManager::create_table() { + Ref tb = DatabaseManager::get_singleton()->ddb->get_table_builder(); + + tb->create_table(_table_name); + tb->integer("id")->auto_increment()->next_row(); + tb->varchar("session_id", 100)->next_row(); + tb->primary_key("id"); + tb->ccreate_table(); + //tb->print(); + tb->run_query(); + + tb->result = ""; + + tb->create_table(_data_table_name); + tb->integer("session_db_id")->not_null()->next_row(); + tb->varchar("key", 100)->next_row(); + tb->integer("value")->not_null()->next_row(); + tb->foreign_key("session_db_id"); + tb->references(_table_name, "id"); + tb->ccreate_table(); + //tb->print(); + tb->run_query(); +} +void SessionManager::drop_table() { + Ref tb = DatabaseManager::get_singleton()->ddb->get_table_builder(); + + tb->drop_table_if_exists(_table_name)->run_query(); + tb->drop_table_if_exists(_data_table_name)->run_query(); +} + SessionManager *SessionManager::get_singleton() { return _self; } @@ -163,4 +308,6 @@ SessionManager::~SessionManager() { } } -SessionManager *SessionManager::_self = nullptr; \ No newline at end of file +SessionManager *SessionManager::_self = nullptr; +std::string SessionManager::_table_name = "sessions"; +std::string SessionManager::_data_table_name = "session_data"; \ No newline at end of file diff --git a/core/http/session_manager.h b/core/http/session_manager.h index 92e813e..62c73eb 100644 --- a/core/http/session_manager.h +++ b/core/http/session_manager.h @@ -16,15 +16,22 @@ public: void add_session(HTTPSession *session); void remove_session(HTTPSession *session); void delete_session(const std::string &session_id); + void save_session(HTTPSession *session); HTTPSession *get_session(const std::string &session_id); HTTPSession *create_session(); + void load_sessions(); + void clear(); virtual std::string generate_session_id(const std::string &base = ""); static void session_setup_middleware(Object *instance, Request *request); + virtual void migrate(); + virtual void create_table(); + virtual void drop_table(); + static SessionManager *get_singleton(); SessionManager(); @@ -36,6 +43,9 @@ public: protected: static SessionManager *_self; + + static std::string _table_name; + static std::string _data_table_name; }; #endif \ No newline at end of file diff --git a/modules/users/user_controller.cpp b/modules/users/user_controller.cpp index 0d7476d..4d7f3f5 100644 --- a/modules/users/user_controller.cpp +++ b/modules/users/user_controller.cpp @@ -67,7 +67,7 @@ void UserController::handle_login_request_default(Request *request) { HTTPSession *session = request->get_or_create_session(); session->add_int("user_id", user->id); - //session->save(); + SessionManager::get_singleton()->save_session(session); request->add_cookie(::Cookie("session_id", session->session_id));