diff --git a/src/core/chat_room.cpp b/src/core/chat_room.cpp index 936a8ad..22dd4c3 100755 --- a/src/core/chat_room.cpp +++ b/src/core/chat_room.cpp @@ -113,7 +113,14 @@ namespace Yc { return false; } - auto newUser = std::make_shared(shared_from_this(), _userName, color, socket); + std::shared_ptr newUser; + if (_database) { + // Verwende den neuen Konstruktor mit Datenbank + newUser = std::make_shared(shared_from_this(), _userName, color, socket, _database); + } else { + // Fallback auf den alten Konstruktor + newUser = std::make_shared(shared_from_this(), _userName, color, socket); + } _users.push_back(newUser); newUser->start(); if (_parent) { @@ -631,5 +638,10 @@ namespace Yc addMessage(ChatUser::system, msg, "", ""); } + void ChatRoom::setDatabase(std::shared_ptr database) + { + _database = database; + } + } // namespace Lib } // namespace Yc diff --git a/src/core/chat_room.h b/src/core/chat_room.h index 7125550..e6d7c79 100755 --- a/src/core/chat_room.h +++ b/src/core/chat_room.h @@ -15,6 +15,7 @@ #include "lib/base.h" #include "chat_user.h" #include "object/room.h" +#include "lib/database.h" namespace Yc { @@ -50,6 +51,7 @@ namespace Yc void addMessage(ChatUser::MsgType type, const char *messageText, std::string userName = "", std::string color = ""); void addMessage(ChatUser::MsgType type, std::string messageText, std::string userName = "", std::string color = ""); void addMessage(ChatUser::MsgType type, Json::Value messageText, std::string userName = "", std::string color = ""); + void setDatabase(std::shared_ptr database); RoomType type(); bool isType(RoomType type); bool canDice(); @@ -91,6 +93,7 @@ namespace Yc }; std::shared_ptr _parent; + std::shared_ptr _database; std::string _name; std::string _password; std::vector _allowedUsers; diff --git a/src/core/chat_user.cpp b/src/core/chat_user.cpp index adfc326..4fc5ca6 100644 --- a/src/core/chat_user.cpp +++ b/src/core/chat_user.cpp @@ -45,6 +45,13 @@ namespace Yc return; } auto server = _parent->getServer(); + if (!server) { + // Fallback wenn Server nicht verfügbar + _user = Yc::Object::User(Json::Value()); + _token = Yc::Lib::Tools::generateRandomString(32); + sendMsg(token, _token, _name, _color); + return; + } auto db = server->_database; // Suche Community-User std::string query = "SELECT * FROM community.\"user\" WHERE username = '" + name + "' LIMIT 1;"; @@ -107,6 +114,83 @@ namespace Yc // Thread-Start erfolgt jetzt explizit per start(), nicht im Konstruktor } + ChatUser::ChatUser(std::shared_ptr parent, std::string name, std::string color, int socket, std::shared_ptr database) + : _parent(std::move(parent)), + _name(name), + _color(color), + _socket(socket), + _stop(false) + { + // Verwende die direkt übergebene Datenbank + if (!database) { + // Fallback wenn keine Datenbank verfügbar + _user = Yc::Object::User(Json::Value()); + _token = Yc::Lib::Tools::generateRandomString(32); + sendMsg(token, _token, _name, _color); + return; + } + auto db = database; + // Suche Community-User + std::string query = "SELECT * FROM community.\"user\" WHERE username = '" + name + "' LIMIT 1;"; + auto result = db->exec(query); + Json::Value userJson; + if (result.empty()) { + // Kein Community-User, lege Dummy an + userJson["display_name"] = name; + userJson["color"] = "#000000"; + } else { + const auto& row = result[0]; + int falukant_user_id = row["id"].as(); + // Suche Chat-User + std::string chatUserQuery = "SELECT * FROM chat.\"user\" WHERE falukant_user_id = " + std::to_string(falukant_user_id) + " LIMIT 1;"; + auto chatUserResult = db->exec(chatUserQuery); + if (chatUserResult.empty()) { + // Chat-User anlegen + std::string insert = "INSERT INTO chat.\"user\" (falukant_user_id, display_name, color, show_gender, show_age, created_at, updated_at) VALUES (" + + std::to_string(falukant_user_id) + ", '" + name + "', '#000000', true, true, NOW(), NOW()) RETURNING *;"; + auto newUser = db->exec(insert); + if (!newUser.empty()) { + const auto& u = newUser[0]; + userJson["id"] = u["id"].as(); + userJson["falukant_user_id"] = u["falukant_user_id"].as(); + userJson["display_name"] = u["display_name"].c_str(); + userJson["color"] = u["color"].c_str(); + userJson["show_gender"] = u["show_gender"].as(); + userJson["show_age"] = u["show_age"].as(); + userJson["created_at"] = u["created_at"].c_str(); + userJson["updated_at"] = u["updated_at"].c_str(); + } + } else { + const auto& u = chatUserResult[0]; + userJson["id"] = u["id"].as(); + userJson["falukant_user_id"] = u["falukant_user_id"].as(); + userJson["display_name"] = u["display_name"].c_str(); + userJson["color"] = u["color"].c_str(); + userJson["show_gender"] = u["show_gender"].as(); + userJson["show_age"] = u["show_age"].as(); + userJson["created_at"] = u["created_at"].c_str(); + userJson["updated_at"] = u["updated_at"].c_str(); + } + // Rechte laden + std::string rightsQuery = "SELECT r.tr FROM chat.user_rights ur JOIN chat.rights r ON ur.chat_right_id = r.id WHERE ur.chat_user_id = " + std::to_string(userJson["id"].asInt()) + ";"; + auto rightsResult = db->exec(rightsQuery); + Json::Value rights(Json::arrayValue); + for (const auto& r : rightsResult) { + rights.append(r["tr"].c_str()); + } + userJson["rights"] = rights; + } + _user = Yc::Object::User(userJson); + // Prefer DB color if available + if (_user.id() != 0 && !_user.color().empty()) { + _color = _user.color(); + } + _token = Yc::Lib::Tools::generateRandomString(32); + // Beim Initial-Token direkt Name und aktuelle Farbe mitsenden, damit der Client "ich" korrekt färben kann + sendMsg(token, _token, _name, _color); + // Thread-Start erfolgt jetzt explizit per start(), nicht im Konstruktor + } + ChatUser::~ChatUser() { // Hinweis: Thread wird nicht im Destruktor gejoint, um Deadlocks zu vermeiden! diff --git a/src/core/chat_user.h b/src/core/chat_user.h index b7b816d..f765829 100644 --- a/src/core/chat_user.h +++ b/src/core/chat_user.h @@ -8,6 +8,7 @@ #include #include "lib/base.h" #include "object/user.h" +#include "lib/database.h" namespace Yc { @@ -33,7 +34,8 @@ namespace Yc result = 9 }; - ChatUser(std::shared_ptr parent, std::string name, std::string color, int socket); + ChatUser(std::shared_ptr parent, std::string name, std::string color, int socket); + ChatUser(std::shared_ptr parent, std::string name, std::string color, int socket, std::shared_ptr database); ~ChatUser(); std::string name() const; std::string getToken() const; diff --git a/src/core/server.cpp b/src/core/server.cpp index c2d6119..3e4a18d 100755 --- a/src/core/server.cpp +++ b/src/core/server.cpp @@ -359,6 +359,7 @@ namespace Yc { room["allowed"] = Json::arrayValue; // ggf. später befüllen room["roundlength"] = 60; // Default-Wert auto newRoom = std::make_shared(self, room); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); created = true; #ifdef YC_DEBUG @@ -389,6 +390,7 @@ namespace Yc { std::cout << "[Debug] Creating fallback room: " << room["name"].asString() << std::endl; #endif auto newRoom = std::make_shared(self, room); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); created = true; } @@ -404,6 +406,7 @@ namespace Yc { room["type"] = 0; room["roundlength"] = 0; auto newRoom = std::make_shared(self, room); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); created = true; } diff --git a/src/core/ssl_server.cpp b/src/core/ssl_server.cpp index 042a374..31971a8 100644 --- a/src/core/ssl_server.cpp +++ b/src/core/ssl_server.cpp @@ -437,6 +437,7 @@ void SSLServer::createRooms() { for (const auto& room : dbRooms) { std::cout << "[YourChat] Database room: " << room << std::endl; auto newRoom = std::make_shared(nullptr, room); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); } std::cout << "[YourChat] Loaded " << _rooms.size() << " rooms from database" << std::endl; @@ -462,6 +463,7 @@ void SSLServer::createRooms() { std::cout << "[YourChat] Config room: " << room << std::endl; // Create room objects using the same logic as the main server auto newRoom = std::make_shared(nullptr, room); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); } } else { @@ -474,6 +476,7 @@ void SSLServer::createRooms() { defaultRoom["type"] = 0; defaultRoom["roundlength"] = 0; auto newRoom = std::make_shared(nullptr, defaultRoom); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); std::cout << "[YourChat] Created default room 'Halle'" << std::endl; } @@ -499,6 +502,7 @@ void SSLServer::reloadRooms() { for (const auto& room : dbRooms) { std::cout << "[YourChat] Database room: " << room << std::endl; auto newRoom = std::make_shared(nullptr, room); + newRoom->setDatabase(_database); _rooms.push_back(newRoom); } std::cout << "[YourChat] Loaded " << _rooms.size() << " rooms from database" << std::endl;