#include "DatabaseService.h" #include "../services/RedisHelper.h" #include #include #include #include using namespace drogon; using namespace drogon::orm; namespace { void storeKeyInRedis(const std::string& streamKey) { // Store the stream key in Redis for validation (24 hour TTL) bool stored = RedisHelper::storeKey("stream_key:" + streamKey, "1", 86400); if (stored) { LOG_INFO << "Stored stream key in Redis: " << streamKey; } else { LOG_ERROR << "Failed to store key in Redis: " << streamKey; } } std::string generateStreamKey() { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(0, 255); std::stringstream ss; for (int i = 0; i < 16; ++i) { ss << std::hex << std::setw(2) << std::setfill('0') << dis(gen); } return ss.str(); } } void DatabaseService::initialize() { LOG_INFO << "Initializing Database Service..."; } void DatabaseService::getUserStreamKey(int64_t userId, std::function callback) { auto dbClient = drogon::app().getDbClient(); *dbClient << "SELECT key FROM stream_keys WHERE user_id = $1 AND is_active = true" << userId >> [callback, userId, dbClient](const Result &r) { if (!r.empty()) { std::string key = r[0]["key"].as(); // Also store in Redis when retrieved storeKeyInRedis(key); callback(true, key); } else { // Generate new key for user std::string newKey = generateStreamKey(); *dbClient << "INSERT INTO stream_keys (user_id, key, is_active) VALUES ($1, $2, true)" << userId << newKey >> [callback, newKey](const Result &) { storeKeyInRedis(newKey); callback(true, newKey); } >> [callback](const DrogonDbException &e) { LOG_ERROR << "Failed to create stream key: " << e.base().what(); callback(false, ""); }; } } >> [callback](const DrogonDbException &e) { LOG_ERROR << "Database error: " << e.base().what(); callback(false, ""); }; } void DatabaseService::updateUserStreamKey(int64_t userId, const std::string& newKey, std::function callback) { auto dbClient = drogon::app().getDbClient(); // Execute as separate queries instead of transaction for simplicity *dbClient << "UPDATE stream_keys SET is_active = false WHERE user_id = $1" << userId >> [dbClient, userId, newKey, callback](const Result &) { // Insert new key *dbClient << "INSERT INTO stream_keys (user_id, key, is_active) VALUES ($1, $2, true)" << userId << newKey >> [callback, newKey](const Result &) { // Store new key in Redis storeKeyInRedis(newKey); callback(true); } >> [callback](const DrogonDbException &e) { LOG_ERROR << "Failed to insert new key: " << e.base().what(); callback(false); }; } >> [callback](const DrogonDbException &e) { LOG_ERROR << "Failed to deactivate old keys: " << e.base().what(); callback(false); }; } void DatabaseService::validateStreamKey(const std::string& key, std::function callback) { auto dbClient = drogon::app().getDbClient(); *dbClient << "SELECT 1 FROM stream_keys WHERE key = $1 AND is_active = true" << key >> [callback, key](const Result &r) { bool valid = !r.empty(); if (valid) { // Also store in Redis when validated storeKeyInRedis(key); } callback(valid); } >> [callback](const DrogonDbException &e) { LOG_ERROR << "Database error: " << e.base().what(); callback(false); }; }