Füge Unterstützung für Token in der Benutzeranmeldung im ChatRoom hinzu
- Implementiere eine neue Methode `addUser`, die einen Token als Parameter akzeptiert, um die Benutzeranmeldung über WebSockets zu verbessern. - Aktualisiere den Konstruktor von `ChatUser`, um den Token zu verarbeiten und sicherzustellen, dass Benutzer korrekt initialisiert werden. - Ergänze Debug-Ausgaben, um den Ablauf beim Hinzufügen von Benutzern und beim Senden von Nachrichten zu protokollieren, um die Nachverfolgbarkeit zu erhöhen.
This commit is contained in:
@@ -243,6 +243,74 @@ namespace Yc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatRoom::addUser(std::string _userName, std::string color, std::string _password, void* wsi, std::string token)
|
||||||
|
{
|
||||||
|
if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::shared_ptr<ChatUser> newUser;
|
||||||
|
if (_database) {
|
||||||
|
// Verwende den neuen WebSocket-Konstruktor mit Token
|
||||||
|
newUser = std::make_shared<ChatUser>(shared_from_this(), _userName, color, wsi, _database, token);
|
||||||
|
} else {
|
||||||
|
// Fallback: WebSocket ohne Datenbank nicht unterstützt
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_users.push_back(newUser);
|
||||||
|
|
||||||
|
// Sende zuerst alle wichtigen Nachrichten, bevor der checkerTask Thread startet
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Starting message sequence for user: " << newUser->name() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_parent) {
|
||||||
|
Json::Value roomList = _parent->jsonRoomList();
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Sending roomList to user: " << newUser->name() << std::endl;
|
||||||
|
#endif
|
||||||
|
newUser->sendMsg(ChatUser::roomList, roomList, "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kurze Pause, damit der WebSocket-Handshake vollständig abgeschlossen ist
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Waiting 100ms for WebSocket handshake..." << std::endl;
|
||||||
|
#endif
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
|
// Sende aktuelle Userliste an den neuen User
|
||||||
|
Json::Value currentUserList = userList();
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Sending userListe to user: " << newUser->name() << std::endl;
|
||||||
|
#endif
|
||||||
|
newUser->sendMsg(ChatUser::userListe, currentUserList, "", "");
|
||||||
|
|
||||||
|
// Sende aktualisierte Userliste an alle anderen User im Raum
|
||||||
|
for (auto &existingUser : _users) {
|
||||||
|
if (existingUser != newUser) {
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Sending userListe to existing user: " << existingUser->name() << std::endl;
|
||||||
|
#endif
|
||||||
|
existingUser->sendMsg(ChatUser::userListe, currentUserList, "", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast an andere Nutzer: Benutzer X hat den Chat betreten (mit Farbinfo)
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Sending 'user_entered_chat' message for user: " << newUser->name() << std::endl;
|
||||||
|
#endif
|
||||||
|
addMessage(ChatUser::system, "user_entered_chat", newUser->name(), newUser->color());
|
||||||
|
|
||||||
|
// Starte den checkerTask Thread erst nach dem Senden aller wichtigen Nachrichten
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] addUser(WebSocket with token): Starting checkerTask thread for user: " << newUser->name() << std::endl;
|
||||||
|
#endif
|
||||||
|
newUser->start();
|
||||||
|
|
||||||
|
_initRound();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ChatRoom::addUser(std::shared_ptr<ChatUser> user, std::string password)
|
bool ChatRoom::addUser(std::shared_ptr<ChatUser> user, std::string password)
|
||||||
{
|
{
|
||||||
if (password == _password)
|
if (password == _password)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ namespace Yc
|
|||||||
std::string name();
|
std::string name();
|
||||||
bool addUser(std::string userName, std::string color, std::string password, int socket);
|
bool addUser(std::string userName, std::string color, std::string password, int socket);
|
||||||
bool addUser(std::string userName, std::string color, std::string password, void* wsi);
|
bool addUser(std::string userName, std::string color, std::string password, void* wsi);
|
||||||
|
bool addUser(std::string userName, std::string color, std::string password, void* wsi, std::string token);
|
||||||
bool addUser(std::shared_ptr<ChatUser> user, std::string password);
|
bool addUser(std::shared_ptr<ChatUser> user, std::string password);
|
||||||
bool userNameExists(std::string userName);
|
bool userNameExists(std::string userName);
|
||||||
void removeUser(std::string _token, bool silent = false);
|
void removeUser(std::string _token, bool silent = false);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace Yc
|
|||||||
// Fallback für SSL-Server ohne Parent
|
// Fallback für SSL-Server ohne Parent
|
||||||
_user = Yc::Object::User(Json::Value());
|
_user = Yc::Object::User(Json::Value());
|
||||||
_token = Yc::Lib::Tools::generateRandomString(32);
|
_token = Yc::Lib::Tools::generateRandomString(32);
|
||||||
sendMsg(token, _token, _name, _color);
|
sendMsg(ChatUser::token, _token, _name, _color);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto server = _parent->getServer();
|
auto server = _parent->getServer();
|
||||||
@@ -50,7 +50,7 @@ namespace Yc
|
|||||||
// Fallback wenn Server nicht verfügbar
|
// Fallback wenn Server nicht verfügbar
|
||||||
_user = Yc::Object::User(Json::Value());
|
_user = Yc::Object::User(Json::Value());
|
||||||
_token = Yc::Lib::Tools::generateRandomString(32);
|
_token = Yc::Lib::Tools::generateRandomString(32);
|
||||||
sendMsg(token, _token, _name, _color);
|
sendMsg(ChatUser::token, _token, _name, _color);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto db = server->_database;
|
auto db = server->_database;
|
||||||
@@ -131,7 +131,7 @@ namespace Yc
|
|||||||
// Fallback wenn keine Datenbank verfügbar
|
// Fallback wenn keine Datenbank verfügbar
|
||||||
_user = Yc::Object::User(Json::Value());
|
_user = Yc::Object::User(Json::Value());
|
||||||
_token = Yc::Lib::Tools::generateRandomString(32);
|
_token = Yc::Lib::Tools::generateRandomString(32);
|
||||||
sendMsg(token, _token, _name, _color);
|
sendMsg(ChatUser::token, _token, _name, _color);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto db = database;
|
auto db = database;
|
||||||
@@ -279,6 +279,86 @@ namespace Yc
|
|||||||
// Thread-Start erfolgt jetzt explizit per start(), nicht im Konstruktor
|
// Thread-Start erfolgt jetzt explizit per start(), nicht im Konstruktor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatUser::ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, void* wsi, std::shared_ptr<Database> database, std::string token)
|
||||||
|
: _parent(std::move(parent)),
|
||||||
|
_name(name),
|
||||||
|
_color(color),
|
||||||
|
_socket(-1),
|
||||||
|
_wsi(wsi),
|
||||||
|
_token(token),
|
||||||
|
_stop(false)
|
||||||
|
{
|
||||||
|
#ifdef YC_DEBUG
|
||||||
|
std::cout << "[Debug] ChatUser constructor with token: name=" << _name << ", token=" << _token << std::endl;
|
||||||
|
#endif
|
||||||
|
// Verwende die direkt übergebene Datenbank
|
||||||
|
if (!database) {
|
||||||
|
// Fallback wenn keine Datenbank verfügbar
|
||||||
|
_user = Yc::Object::User(Json::Value());
|
||||||
|
sendMsg(ChatUser::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<int>();
|
||||||
|
// 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<int>();
|
||||||
|
userJson["falukant_user_id"] = u["falukant_user_id"].as<int>();
|
||||||
|
userJson["display_name"] = u["display_name"].c_str();
|
||||||
|
userJson["color"] = u["color"].c_str();
|
||||||
|
userJson["show_gender"] = u["show_gender"].as<bool>();
|
||||||
|
userJson["show_age"] = u["show_age"].as<bool>();
|
||||||
|
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<int>();
|
||||||
|
userJson["falukant_user_id"] = u["falukant_user_id"].as<int>();
|
||||||
|
userJson["display_name"] = u["display_name"].c_str();
|
||||||
|
userJson["color"] = u["color"].c_str();
|
||||||
|
userJson["show_gender"] = u["show_gender"].as<bool>();
|
||||||
|
userJson["show_age"] = u["show_age"].as<bool>();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
// Beim Initial-Token direkt Name und aktuelle Farbe mitsenden, damit der Client "ich" korrekt färben kann
|
||||||
|
sendMsg(ChatUser::token, _token, _name, _color);
|
||||||
|
// Thread-Start erfolgt jetzt explizit per start(), nicht im Konstruktor
|
||||||
|
}
|
||||||
|
|
||||||
ChatUser::~ChatUser()
|
ChatUser::~ChatUser()
|
||||||
{
|
{
|
||||||
// Hinweis: Thread wird nicht im Destruktor gejoint, um Deadlocks zu vermeiden!
|
// Hinweis: Thread wird nicht im Destruktor gejoint, um Deadlocks zu vermeiden!
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ namespace Yc
|
|||||||
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket);
|
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket);
|
||||||
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket, std::shared_ptr<Database> database);
|
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket, std::shared_ptr<Database> database);
|
||||||
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, void* wsi, std::shared_ptr<Database> database);
|
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, void* wsi, std::shared_ptr<Database> database);
|
||||||
|
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, void* wsi, std::shared_ptr<Database> database, std::string token);
|
||||||
~ChatUser();
|
~ChatUser();
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
std::string getToken() const;
|
std::string getToken() const;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "ssl_server.h"
|
#include "ssl_server.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "lib/database.h"
|
#include "lib/database.h"
|
||||||
|
#include "lib/tools.h"
|
||||||
#include "chat_room.h"
|
#include "chat_room.h"
|
||||||
#include "chat_user.h"
|
#include "chat_user.h"
|
||||||
#include "lib/base.h"
|
#include "lib/base.h"
|
||||||
@@ -265,7 +266,7 @@ void SSLServer::handleWebSocketMessage(struct lws *wsi, const std::string& messa
|
|||||||
|
|
||||||
// Generate token if not provided
|
// Generate token if not provided
|
||||||
if (token.empty()) {
|
if (token.empty()) {
|
||||||
token = Base::generateToken();
|
token = Yc::Lib::Tools::generateRandomString(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store user data in connections map instead
|
// Store user data in connections map instead
|
||||||
@@ -300,7 +301,7 @@ void SSLServer::handleWebSocketMessage(struct lws *wsi, const std::string& messa
|
|||||||
std::cout << "[Debug] Attempting to add user '" << name << "' to room '" << room << "' with WebSocket wsi pointer" << std::endl;
|
std::cout << "[Debug] Attempting to add user '" << name << "' to room '" << room << "' with WebSocket wsi pointer" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (roomObj->addUser(name, color, password, wsi)) {
|
if (roomObj->addUser(name, color, password, wsi, token)) {
|
||||||
std::cout << "[YourChat] Successfully added user '" << name << "' to room '" << room << "'" << std::endl;
|
std::cout << "[YourChat] Successfully added user '" << name << "' to room '" << room << "'" << std::endl;
|
||||||
// Find the created ChatUser
|
// Find the created ChatUser
|
||||||
auto chatUser = roomObj->findUserByName(name);
|
auto chatUser = roomObj->findUserByName(name);
|
||||||
|
|||||||
Reference in New Issue
Block a user