#include "AdminController.h" #include "../services/OmeClient.h" #include "../services/RedisHelper.h" using namespace drogon::orm; namespace { HttpResponsePtr jsonResp(const Json::Value& j, HttpStatusCode c = k200OK) { auto r = HttpResponse::newHttpJsonResponse(j); r->setStatusCode(c); return r; } HttpResponsePtr jsonError(const std::string& error, HttpStatusCode code = k400BadRequest) { Json::Value j; j["success"] = false; j["error"] = error; return jsonResp(j, code); } } UserInfo AdminController::getUserFromRequest(const HttpRequestPtr &req) { UserInfo user; std::string auth = req->getHeader("Authorization"); if (auth.empty() || auth.substr(0, 7) != "Bearer ") { return user; } std::string token = auth.substr(7); AuthService::getInstance().validateToken(token, user); return user; } void AdminController::getUsers(const HttpRequestPtr &req, std::function &&callback) { UserInfo user = getUserFromRequest(req); if (user.id == 0 || !user.isAdmin) { callback(jsonError("Unauthorized", k403Forbidden)); return; } auto dbClient = app().getDbClient(); *dbClient << "SELECT u.id, u.username, u.is_admin, u.is_streamer, u.created_at, " "(SELECT COUNT(*) FROM realms WHERE user_id = u.id) as realm_count " "FROM users u ORDER BY u.created_at DESC" >> [callback](const Result& r) { Json::Value resp; resp["success"] = true; Json::Value users(Json::arrayValue); for (const auto& row : r) { Json::Value user; user["id"] = static_cast(row["id"].as()); user["username"] = row["username"].as(); user["isAdmin"] = row["is_admin"].as(); user["isStreamer"] = row["is_streamer"].as(); user["createdAt"] = row["created_at"].as(); user["realmCount"] = static_cast(row["realm_count"].as()); users.append(user); } resp["users"] = users; callback(jsonResp(resp)); } >> [callback](const DrogonDbException& e) { LOG_ERROR << "Failed to get users: " << e.base().what(); callback(jsonError("Failed to get users")); }; } void AdminController::getActiveStreams(const HttpRequestPtr &req, std::function &&callback) { UserInfo user = getUserFromRequest(req); if (user.id == 0 || !user.isAdmin) { callback(jsonError("Unauthorized", k403Forbidden)); return; } // Get live realms from database auto dbClient = app().getDbClient(); *dbClient << "SELECT r.id, r.name, r.stream_key, r.viewer_count, " "u.username FROM realms r " "JOIN users u ON r.user_id = u.id " "WHERE r.is_live = true" >> [callback](const Result& r) { Json::Value resp; resp["success"] = true; Json::Value streams(Json::arrayValue); for (const auto& row : r) { Json::Value stream; stream["id"] = static_cast(row["id"].as()); stream["name"] = row["name"].as(); stream["streamKey"] = row["stream_key"].as(); stream["viewerCount"] = static_cast(row["viewer_count"].as()); stream["username"] = row["username"].as(); streams.append(stream); } resp["streams"] = streams; callback(jsonResp(resp)); } >> [callback](const DrogonDbException& e) { LOG_ERROR << "Failed to get active streams: " << e.base().what(); callback(jsonError("Failed to get active streams")); }; } void AdminController::disconnectStream(const HttpRequestPtr &req, std::function &&callback, const std::string &streamKey) { UserInfo user = getUserFromRequest(req); if (user.id == 0 || !user.isAdmin) { callback(jsonError("Unauthorized", k403Forbidden)); return; } // Add to Redis set for OpenResty to disconnect RedisHelper::addToSet("streams_to_disconnect", streamKey); // Also try direct disconnect OmeClient::getInstance().disconnectStream(streamKey, [callback](bool) { Json::Value resp; resp["success"] = true; resp["message"] = "Stream disconnect initiated"; callback(jsonResp(resp)); }); } void AdminController::promoteToStreamer(const HttpRequestPtr &req, std::function &&callback, const std::string &userId) { UserInfo user = getUserFromRequest(req); if (user.id == 0 || !user.isAdmin) { callback(jsonError("Unauthorized", k403Forbidden)); return; } int64_t targetUserId = std::stoll(userId); auto dbClient = app().getDbClient(); *dbClient << "UPDATE users SET is_streamer = true WHERE id = $1" << targetUserId >> [callback](const Result&) { Json::Value resp; resp["success"] = true; resp["message"] = "User promoted to streamer"; callback(jsonResp(resp)); } >> [callback](const DrogonDbException& e) { LOG_ERROR << "Failed to promote user: " << e.base().what(); callback(jsonError("Failed to promote user")); }; } void AdminController::demoteFromStreamer(const HttpRequestPtr &req, std::function &&callback, const std::string &userId) { UserInfo user = getUserFromRequest(req); if (user.id == 0 || !user.isAdmin) { callback(jsonError("Unauthorized", k403Forbidden)); return; } int64_t targetUserId = std::stoll(userId); auto dbClient = app().getDbClient(); *dbClient << "UPDATE users SET is_streamer = false WHERE id = $1" << targetUserId >> [callback](const Result&) { Json::Value resp; resp["success"] = true; resp["message"] = "User demoted from streamer"; callback(jsonResp(resp)); } >> [callback](const DrogonDbException& e) { LOG_ERROR << "Failed to demote user: " << e.base().what(); callback(jsonError("Failed to demote user")); }; }