mirror of
https://github.com/kunkundi/crossdesk-server.git
synced 2026-03-22 07:45:07 +08:00
[fix] fix device presence status dispatch on login/logout
This commit is contained in:
@@ -60,12 +60,6 @@ void DeviceDBManager::InitDB() {
|
||||
"online INTEGER NOT NULL,"
|
||||
"updated_at INTEGER NOT NULL"
|
||||
");";
|
||||
const char* sql_user_devices =
|
||||
"CREATE TABLE IF NOT EXISTS user_devices ("
|
||||
"user_id TEXT NOT NULL,"
|
||||
"device_id TEXT NOT NULL,"
|
||||
"PRIMARY KEY(user_id, device_id)"
|
||||
");";
|
||||
|
||||
char* err_msg = nullptr;
|
||||
|
||||
@@ -94,12 +88,6 @@ void DeviceDBManager::InitDB() {
|
||||
sqlite3_free(err_msg);
|
||||
return;
|
||||
}
|
||||
if (sqlite3_exec(db_, sql_user_devices, nullptr, nullptr, &err_msg) !=
|
||||
SQLITE_OK) {
|
||||
LOG_ERROR("Failed to create user_devices table: {}", err_msg);
|
||||
sqlite3_free(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string DeviceDBManager::Sha256(const std::string& str) {
|
||||
@@ -410,70 +398,6 @@ bool DeviceDBManager::UpdatePassword(const std::string& device_id,
|
||||
return success;
|
||||
}
|
||||
|
||||
bool DeviceDBManager::SetUserDevices(
|
||||
const std::string& user_id, const std::vector<std::string>& device_ids) {
|
||||
if (db_ == nullptr) {
|
||||
LOG_ERROR("Database is not initialized in SetUserDevices.");
|
||||
return false;
|
||||
}
|
||||
sqlite3_exec(db_, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr);
|
||||
const char* del_sql = "DELETE FROM user_devices WHERE user_id = ?;";
|
||||
sqlite3_stmt* del_stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db_, del_sql, -1, &del_stmt, nullptr) != SQLITE_OK) {
|
||||
sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, nullptr);
|
||||
return false;
|
||||
}
|
||||
sqlite3_bind_text(del_stmt, 1, user_id.c_str(), -1, SQLITE_TRANSIENT);
|
||||
if (sqlite3_step(del_stmt) != SQLITE_DONE) {
|
||||
sqlite3_finalize(del_stmt);
|
||||
sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, nullptr);
|
||||
return false;
|
||||
}
|
||||
sqlite3_finalize(del_stmt);
|
||||
|
||||
const char* ins_sql =
|
||||
"INSERT INTO user_devices (user_id, device_id) VALUES (?, ?);";
|
||||
sqlite3_stmt* ins_stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db_, ins_sql, -1, &ins_stmt, nullptr) != SQLITE_OK) {
|
||||
sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, nullptr);
|
||||
return false;
|
||||
}
|
||||
for (const auto& id : device_ids) {
|
||||
sqlite3_bind_text(ins_stmt, 1, user_id.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(ins_stmt, 2, id.c_str(), -1, SQLITE_TRANSIENT);
|
||||
if (sqlite3_step(ins_stmt) != SQLITE_DONE) {
|
||||
sqlite3_finalize(ins_stmt);
|
||||
sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, nullptr);
|
||||
return false;
|
||||
}
|
||||
sqlite3_reset(ins_stmt);
|
||||
sqlite3_clear_bindings(ins_stmt);
|
||||
}
|
||||
sqlite3_finalize(ins_stmt);
|
||||
sqlite3_exec(db_, "COMMIT;", nullptr, nullptr, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> DeviceDBManager::GetUserDevices(
|
||||
const std::string& user_id) {
|
||||
std::vector<std::string> devices;
|
||||
if (db_ == nullptr) {
|
||||
LOG_ERROR("Database is not initialized in GetUserDevices.");
|
||||
return devices;
|
||||
}
|
||||
const char* sql = "SELECT device_id FROM user_devices WHERE user_id = ?;";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
return devices;
|
||||
}
|
||||
sqlite3_bind_text(stmt, 1, user_id.c_str(), -1, SQLITE_TRANSIENT);
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
devices.emplace_back(
|
||||
reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return devices;
|
||||
}
|
||||
bool DeviceDBManager::RemoveDevice(const std::string& device_id) {
|
||||
if (db_ == nullptr) {
|
||||
LOG_ERROR("Database is not initialized in RemoveDevice.");
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
void PresenceManager::OnLogin(const std::string& user_id,
|
||||
const std::string& device_id,
|
||||
websocketpp::connection_hdl hdl) {
|
||||
@@ -12,8 +14,7 @@ void PresenceManager::OnLogin(const std::string& user_id,
|
||||
}
|
||||
|
||||
void PresenceManager::OnLogout(const std::string& device_id) {
|
||||
std::string user_id;
|
||||
user_id = device_id;
|
||||
std::string user_id = device_id;
|
||||
if (db_) {
|
||||
db_->SetDeviceOnline(device_id, false);
|
||||
}
|
||||
@@ -40,15 +41,30 @@ std::vector<std::pair<std::string, bool>> PresenceManager::BatchQuery(
|
||||
void PresenceManager::NotifyUserDevices(const std::string& user_id,
|
||||
const std::string& changed_device_id,
|
||||
bool online) {
|
||||
if (!db_ || !send_msg_) return;
|
||||
auto devices = db_->GetUserDevices(user_id);
|
||||
if (devices.empty()) return;
|
||||
auto statuses = db_->BatchQueryOnline(devices);
|
||||
std::vector<std::string> targets;
|
||||
for (const auto& p : statuses) {
|
||||
if (p.first == changed_device_id) continue;
|
||||
if (p.second) {
|
||||
targets.push_back(p.first);
|
||||
if (!send_msg_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> watchers;
|
||||
for (const auto& kv : associations_) {
|
||||
const auto& watcher = kv.first;
|
||||
const auto& watched_set = kv.second;
|
||||
if (watched_set.find(changed_device_id) != watched_set.end()) {
|
||||
watchers.push_back(watcher);
|
||||
}
|
||||
}
|
||||
if (watchers.empty()) {
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> targets = watchers;
|
||||
if (db_) {
|
||||
auto statuses = db_->BatchQueryOnline(watchers);
|
||||
targets.clear();
|
||||
for (const auto& p : statuses) {
|
||||
if (p.first == changed_device_id) {
|
||||
continue;
|
||||
}
|
||||
if (p.second) targets.push_back(p.first);
|
||||
}
|
||||
}
|
||||
nlohmann::json j = {
|
||||
@@ -56,7 +72,7 @@ void PresenceManager::NotifyUserDevices(const std::string& user_id,
|
||||
{"id", changed_device_id},
|
||||
{"online", online},
|
||||
};
|
||||
for (auto& id : targets) {
|
||||
for (const auto& id : targets) {
|
||||
if (send_to_device_) {
|
||||
send_to_device_(id, j);
|
||||
}
|
||||
@@ -65,6 +81,9 @@ void PresenceManager::NotifyUserDevices(const std::string& user_id,
|
||||
|
||||
void PresenceManager::UpdateUserDevices(
|
||||
const std::string& user_id, const std::vector<std::string>& device_ids) {
|
||||
if (!db_) return;
|
||||
db_->SetUserDevices(user_id, device_ids);
|
||||
auto& setref = associations_[user_id];
|
||||
setref.clear();
|
||||
for (const auto& id : device_ids) {
|
||||
setref.insert(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
@@ -50,6 +52,8 @@ class PresenceManager {
|
||||
std::function<void(websocketpp::connection_hdl, json)> send_msg_;
|
||||
DeviceDBManager* db_ = nullptr;
|
||||
std::function<void(const std::string&, json)> send_to_device_;
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>>
|
||||
associations_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user