diff --git a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp index 72e7c41b2..c8a842604 100644 --- a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp @@ -727,4 +727,4 @@ void UserContextMenu::execAdjustDeveloper(const QString &userName, bool shouldBe PendingCommand *pend = client->prepareAdminCommand(cmd); connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse); client->sendCommand(pend); -} +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/tab_developer.cpp b/cockatrice/src/interface/widgets/tabs/tab_developer.cpp index 5456b86b0..d685b9b94 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_developer.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_developer.cpp @@ -135,7 +135,7 @@ void TabDeveloper::refreshClicked() void TabDeveloper::serverStatsResponse(const Response &resp) { if (resp.response_code() != Response::RespOk) { - statusLabel->setText(tr("No server statistics available yet.")); + statusLabel->setText(tr("Failed to collect server statistics.")); return; } diff --git a/cockatrice/src/interface/widgets/tabs/tab_logs.cpp b/cockatrice/src/interface/widgets/tabs/tab_logs.cpp index d5b704818..cd019d6d9 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_logs.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_logs.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -81,9 +82,7 @@ void TabLog::getClicked() if (!mainRoom->isChecked() && !gameRoom->isChecked() && !privateChat->isChecked()) { mainRoom->setChecked(true); gameRoom->setChecked(true); - if (!canUseDeveloperCommands) { - privateChat->setChecked(true); - } + privateChat->setChecked(true); } if (maximumResults->value() == 0) { @@ -124,7 +123,18 @@ void TabLog::getClicked() PendingCommand *pend; if (canUseDeveloperCommands) { // Developers query logs through the developer command family. - pend = client->prepareDeveloperCommand(cmd); + Command_GetLogHistory devCmd; + devCmd.set_user_name(cmd.user_name()); + devCmd.set_ip_address(cmd.ip_address()); + devCmd.set_game_name(cmd.game_name()); + devCmd.set_game_id(cmd.game_id()); + devCmd.set_message(cmd.message()); + for (int i = 0; i < cmd.log_location_size(); ++i) { + devCmd.add_log_location(cmd.log_location(i)); + } + devCmd.set_date_range(cmd.date_range()); + devCmd.set_maximum_results(cmd.maximum_results()); + pend = client->prepareDeveloperCommand(devCmd); } else { pend = client->prepareModeratorCommand(cmd); } @@ -182,10 +192,6 @@ void TabLog::createDock() mainRoom = new QCheckBox(tr("Main Room")); gameRoom = new QCheckBox(tr("Game Room")); privateChat = new QCheckBox(tr("Private Chat")); - if (canUseDeveloperCommands) { - // Developers cannot query private conversations. - privateChat->setVisible(false); - } pastDays = new QRadioButton(tr("Past X Days: ")); today = new QRadioButton(tr("Today")); diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index ee89b4792..bb242e349 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -834,10 +834,10 @@ void TabSupervisor::actTabLog(bool checked) void TabSupervisor::openTabLog() { - // Developers query logs through the developer command family, so tell the - // tab which family to use. - const bool useDeveloperCommands = (userInfo->user_level() & ServerInfo_User::IsDeveloper) != 0; - tabLog = new TabLog(this, client, useDeveloperCommands); + // Developers without moderation rights query logs through the developer + // command family, so tell the tab which family to use. + const bool isDeveloper = (userInfo->user_level() & ServerInfo_User::IsDeveloper) != 0; + tabLog = new TabLog(this, client, isDeveloper); myAddTab(tabLog, aTabLog); connect(tabLog, &QObject::destroyed, this, [this] { tabLog = nullptr; diff --git a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp index 687d93666..de3f896f5 100644 --- a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp +++ b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp @@ -258,19 +258,6 @@ PendingCommand *AbstractClient::prepareDeveloperCommand(const ::google::protobuf { CommandContainer cont; DeveloperCommand *c = cont.add_developer_command(); - // A developer command message may also be usable through other command - // families, so select the extension scoped to DeveloperCommand rather than - // guessing by name. - const ::google::protobuf::Descriptor *cmdDescriptor = cmd.GetDescriptor(); - const ::google::protobuf::Descriptor *developerDescriptor = DeveloperCommand::descriptor(); - const ::google::protobuf::FieldDescriptor *developerExtension = nullptr; - for (int i = 0; i < cmdDescriptor->extension_count(); ++i) { - if (cmdDescriptor->extension(i)->containing_type() == developerDescriptor) { - developerExtension = cmdDescriptor->extension(i); - break; - } - } - Q_ASSERT(developerExtension != nullptr); - c->GetReflection()->MutableMessage(c, developerExtension)->CopyFrom(cmd); + c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd); return new PendingCommand(cont); } diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt index 73745e7ed..df62b4afb 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt @@ -22,10 +22,11 @@ set(PROTO_FILES command_del_counter.proto command_delete_arrow.proto command_draw_cards.proto + command_get_log_history.proto + command_get_server_stats.proto command_dump_zone.proto command_flip_card.proto command_game_say.proto - command_get_server_stats.proto command_inc_card_counter.proto command_inc_counter.proto command_kick_from_game.proto diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/command_get_log_history.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/command_get_log_history.proto new file mode 100644 index 000000000..7ae13bbee --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/command_get_log_history.proto @@ -0,0 +1,19 @@ +syntax = "proto2"; +import "developer_commands.proto"; + +// Developer counterpart of Command_ViewLogHistory: identical query fields, but +// routed through the developer command family so developers never need the +// moderator command container. +message Command_GetLogHistory { + extend DeveloperCommand { + optional Command_GetLogHistory ext = 1001; + } + optional string user_name = 1; // user that created message + optional string ip_address = 2; // ip address of user that created message + optional string game_name = 3; // client id of user that created the message + optional string game_id = 4; // game number the message was sent to + optional string message = 5; // raw message that was sent + repeated string log_location = 6; // destination of message (ex: main room, game room, private chat) + required uint32 date_range = 7; // the length of time (in minutes) to look back for + optional uint32 maximum_results = 8; // the maximum number of query results +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto index 4f1e80c27..685408830 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto @@ -1,5 +1,4 @@ syntax = "proto2"; -import "developer_commands.proto"; message ModeratorCommand { enum ModeratorCommandType { BAN_FROM_SERVER = 1000; @@ -81,9 +80,6 @@ message Command_ViewLogHistory { extend ModeratorCommand { optional Command_ViewLogHistory ext = 1005; } - extend DeveloperCommand { - optional Command_ViewLogHistory dev_ext = 1001; - } optional string user_name = 1; // user that created message optional string ip_address = 2; // ip address of user that created message optional string game_name = 3; // client id of user that created the message diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index cfb1ef5d8..5dbf69cbc 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -25,9 +25,6 @@ INSERT INTO cockatrice_schema_version VALUES(36); -- users and user data tables CREATE TABLE IF NOT EXISTS `cockatrice_users` ( `id` int(7) unsigned zerofill NOT NULL auto_increment, - -- Bitfield of staff levels: 1 = admin (implies moderator), 2 = moderator, - -- 4 = judge, 8 = developer. Operators set these by hand with - -- "UPDATE cockatrice_users SET admin = ...". `admin` tinyint(1) NOT NULL, `name` varchar(35) NOT NULL, `realname` varchar(255) NOT NULL, diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index 36604bae7..cb55764d0 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -1487,38 +1487,6 @@ QList Servatrice_DatabaseInterface::getModeratorLastL return results; } -Servatrice_DatabaseInterface::UptimeSnapshot Servatrice_DatabaseInterface::getLatestUptimeSnapshot(int serverId) -{ - UptimeSnapshot snapshot; - - if (!checkSql()) { - return snapshot; - } - - QSqlQuery *query = prepareQuery("SELECT users_count, mods_count, games_count, tx_bytes, rx_bytes, uptime, " - "UNIX_TIMESTAMP(timest) FROM {prefix}_uptime " - "WHERE id_server = :id_server ORDER BY timest DESC LIMIT 1"); - query->bindValue(":id_server", serverId); - - if (!execSqlQuery(query)) { - qCWarning(DatabaseInterfaceLog) << "Failed to collect server stats snapshot: SQL Error"; - return snapshot; - } - - if (query->next()) { - snapshot.valid = true; - snapshot.usersCount = query->value(0).toULongLong(); - snapshot.modsCount = query->value(1).toULongLong(); - snapshot.gamesCount = query->value(2).toULongLong(); - snapshot.txBytes = query->value(3).toULongLong(); - snapshot.rxBytes = query->value(4).toULongLong(); - snapshot.uptimeSecs = query->value(5).toULongLong(); - snapshot.timest = query->value(6).toULongLong(); - } - - return snapshot; -} - bool Servatrice_DatabaseInterface::removeUserAvatar(const QString &userName) { if (!checkSql()) { diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index a891c7a3d..cd76ae288 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -140,21 +140,6 @@ public: QList getUserSessions(const QString &userName, int limit); QList getUserAlts(const QString &userName); QList getModeratorLastLogins(); - - // Uptime snapshot as recorded by Servatrice::statusUpdate() into the - // {prefix}_uptime table. valid is false when no snapshot exists yet. - struct UptimeSnapshot - { - bool valid = false; - quint64 usersCount = 0; - quint64 modsCount = 0; - quint64 gamesCount = 0; - quint64 txBytes = 0; - quint64 rxBytes = 0; - quint64 uptimeSecs = 0; - quint64 timest = 0; - }; - UptimeSnapshot getLatestUptimeSnapshot(int serverId); bool removeUserAvatar(const QString &userName); bool addForgotPassword(const QString &user); bool removeForgotPassword(const QString &user) override; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index aa607d8c9..878db7774 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -324,7 +325,7 @@ Response::ResponseCode AbstractServerSocketInterface::processExtendedModeratorCo case ModeratorCommand::REPORT_RESOLVE: return cmdReportResolve(cmd.GetExtension(Command_ReportResolve::ext), rc); case ModeratorCommand::VIEWLOG_HISTORY: - return cmdGetLogHistory(cmd.GetExtension(Command_ViewLogHistory::ext), rc, true); + return cmdGetLogHistory(cmd.GetExtension(Command_ViewLogHistory::ext), rc); case ModeratorCommand::GRANT_REPLAY_ACCESS: return cmdGrantReplayAccess(cmd.GetExtension(Command_GrantReplayAccess::ext), rc); case ModeratorCommand::REPLAY_DOWNLOAD_BY_GAME_ID: @@ -388,9 +389,21 @@ Response::ResponseCode AbstractServerSocketInterface::processExtendedDeveloperCo case DeveloperCommand::GET_SERVER_STATS: return cmdGetServerStats(cmd.GetExtension(Command_GetServerStats::ext), rc); case DeveloperCommand::VIEWLOG_HISTORY: { - // Same query as the moderator log view, carried by the developer - // command family, but narrows out private chats and sender IPs. - return cmdGetLogHistory(cmd.GetExtension(Command_ViewLogHistory::dev_ext), rc, false); + // Same query as the moderator log view, just carried by the + // developer command family. + const Command_GetLogHistory &devCmd = cmd.GetExtension(Command_GetLogHistory::ext); + Command_ViewLogHistory modCmd; + modCmd.set_user_name(devCmd.user_name()); + modCmd.set_ip_address(devCmd.ip_address()); + modCmd.set_game_name(devCmd.game_name()); + modCmd.set_game_id(devCmd.game_id()); + modCmd.set_message(devCmd.message()); + for (int i = 0; i < devCmd.log_location_size(); ++i) { + modCmd.add_log_location(devCmd.log_location(i)); + } + modCmd.set_date_range(devCmd.date_range()); + modCmd.set_maximum_results(devCmd.maximum_results()); + return cmdGetLogHistory(modCmd, rc); } default: return Response::RespFunctionNotAllowed; @@ -1080,13 +1093,12 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplaySubmitCode(const // MODERATOR FUNCTIONS. // May be called by admins and moderators. Permission is checked by the calling function. Response::ResponseCode AbstractServerSocketInterface::cmdGetLogHistory(const Command_ViewLogHistory &cmd, - ResponseContainer &rc, - bool allowPrivateChat) + ResponseContainer &rc) { QList messageList; QString userName = nameFromStdString(cmd.user_name()); - QString ipAddress = allowPrivateChat ? nameFromStdString(cmd.ip_address()) : QString(); + QString ipAddress = nameFromStdString(cmd.ip_address()); QString gameName = nameFromStdString(cmd.game_name()); QString gameID = nameFromStdString(cmd.game_id()); QString message = textFromStdString(cmd.message()); @@ -1101,7 +1113,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetLogHistory(const Com if (nameFromStdString(cmd.log_location(i)).simplified() == "game") { gameType = true; } - if (nameFromStdString(cmd.log_location(i)).simplified() == "chat" && allowPrivateChat) { + if (nameFromStdString(cmd.log_location(i)).simplified() == "chat") { chatType = true; } } @@ -1115,11 +1127,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetLogHistory(const Com QListIterator messageIterator(sqlInterface->getMessageLogHistory( userName, ipAddress, gameName, gameID, message, chatType, gameType, roomType, dateRange, maximumResults)); while (messageIterator.hasNext()) { - ServerInfo_ChatMessage chatMessage = messageIterator.next(); - if (!allowPrivateChat) { - chatMessage.clear_sender_ip(); - } - re->add_log_message()->CopyFrom(chatMessage); + re->add_log_message()->CopyFrom(messageIterator.next()); } } else { ServerInfo_ChatMessage chatMessage; @@ -1717,20 +1725,24 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetServerStats(const Co // Servatrice::statusUpdate() periodically snapshots server health into the // uptime table. Serve the freshest snapshot for this server. - const auto snapshot = sqlInterface->getLatestUptimeSnapshot(servatrice->getServerID()); - if (!snapshot.valid) { - // No snapshot yet (fresh server, or statusUpdate() has not ticked). + QSqlQuery *query = sqlInterface->prepareQuery( + "SELECT users_count, mods_count, games_count, tx_bytes, rx_bytes, uptime, UNIX_TIMESTAMP(timest) " + "FROM {prefix}_uptime WHERE id_server = :id_server ORDER BY timest DESC LIMIT 1"); + query->bindValue(":id_server", servatrice->getServerID()); + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; } auto *re = new Response_GetServerStats; - re->set_users_count(snapshot.usersCount); - re->set_mods_count(snapshot.modsCount); - re->set_games_count(snapshot.gamesCount); - re->set_tx_bytes(snapshot.txBytes); - re->set_rx_bytes(snapshot.rxBytes); - re->set_uptime_secs(snapshot.uptimeSecs); - re->set_timest(snapshot.timest); + if (query->next()) { + re->set_users_count(query->value(0).toUInt()); + re->set_mods_count(query->value(1).toUInt()); + re->set_games_count(query->value(2).toUInt()); + re->set_tx_bytes(query->value(3).toUInt()); + re->set_rx_bytes(query->value(4).toUInt()); + re->set_uptime_secs(query->value(5).toUInt()); + re->set_timest(query->value(6).toUInt()); + } // Live metrics from the in-process MetricsRegistry (resets on server restart) re->set_cards_in_games(static_cast(servatrice->getCardsInGamesTotal())); diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index b464e6a9b..9bf4c563b 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -117,8 +118,7 @@ private: Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc); Response::ResponseCode cmdReportList(const Command_ReportList &cmd, ResponseContainer &rc); Response::ResponseCode cmdWarnUser(const Command_WarnUser &cmd, ResponseContainer &rc); - Response::ResponseCode - cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc, bool allowPrivateChat); + Response::ResponseCode cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetWarnList(const Command_GetWarnList &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetWarnHistory(const Command_GetWarnHistory &cmd, ResponseContainer &rc); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0530715bd..c7c65dd0a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,7 +11,6 @@ add_test(NAME playmat_resolver_test COMMAND playmat_resolver_test) add_test(NAME server_card_counter_test COMMAND server_card_counter_test) add_test(NAME server_counter_test COMMAND server_counter_test) add_test(NAME server_rate_limiter_test COMMAND server_rate_limiter_test) -add_test(NAME server_developer_role_test COMMAND server_developer_role_test) add_test(NAME warning_categories_test COMMAND warning_categories_test) add_test(NAME lag_monitor_test COMMAND lag_monitor_test) add_test(NAME latency_tracker_test COMMAND latency_tracker_test) @@ -32,7 +31,6 @@ add_executable(deck_hash_performance_test deck_hash_performance_test.cpp) add_executable(server_card_counter_test server_card_counter_test.cpp) add_executable(server_counter_test server_counter_test.cpp) add_executable(server_rate_limiter_test server_rate_limiter_test.cpp) -add_executable(server_developer_role_test server_developer_role_test.cpp) add_executable(warning_categories_test warning_categories_test.cpp) add_executable(lag_monitor_test ${CMAKE_SOURCE_DIR}/cockatrice/src/client/lag_monitor.cpp lag_monitor_test.cpp) target_include_directories(lag_monitor_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src) @@ -74,7 +72,6 @@ if(NOT GTEST_FOUND) add_dependencies(server_card_counter_test gtest) add_dependencies(server_counter_test gtest) add_dependencies(server_rate_limiter_test gtest) - add_dependencies(server_developer_role_test gtest) add_dependencies(warning_categories_test gtest) add_dependencies(lag_monitor_test gtest) add_dependencies(latency_tracker_test gtest) @@ -110,10 +107,6 @@ target_link_libraries( target_link_libraries( server_rate_limiter_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ) -target_link_libraries( - server_developer_role_test libcockatrice_network libcockatrice_rng Threads::Threads ${GTEST_BOTH_LIBRARIES} - ${TEST_QT_MODULES} -) target_link_libraries( warning_categories_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ) diff --git a/tests/server_developer_role_test.cpp b/tests/server_developer_role_test.cpp deleted file mode 100644 index 127f606a8..000000000 --- a/tests/server_developer_role_test.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/** @file server_developer_role_test.cpp - * @brief Tests for the developer staff role authorization and dispatch. - * @ingroup Tests - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -// The server_remote library references the global RNG, which is normally -// defined by the servatrice/client executable main(). Provide a stub so the -// unit test can link against it. -RNG_Abstract *rng = nullptr; - -namespace -{ - -class TestDeveloperHandler : public Server_ProtocolHandler -{ -public: - explicit TestDeveloperHandler(Server *_server) : Server_ProtocolHandler(_server, nullptr) - { - } - - QString getAddress() const override - { - return {}; - } - QString getConnectionType() const override - { - return {}; - } - - // Buffer the last response code sent to the client so tests can assert on - // the outcome of processCommandContainer(). - Response::ResponseCode lastResponseCode = Response::RespNothing; - int dispatchCount = 0; - -protected: - void transmitProtocolItem(const ServerMessage &item) override - { - if (item.message_type() == ServerMessage::RESPONSE) { - lastResponseCode = item.response().response_code(); - } - } - - Response::ResponseCode - processExtendedDeveloperCommand(int cmdType, const DeveloperCommand &, ResponseContainer &) override - { - ++dispatchCount; - // Fail closed for anything not explicitly handled. - if (cmdType != DeveloperCommand::GET_SERVER_STATS) { - return Response::RespFunctionNotAllowed; - } - return Response::RespOk; - } -}; - -class DeveloperRoleTest : public ::testing::Test -{ -protected: - Server server; - TestDeveloperHandler handler{&server}; - - void setUserLevel(uint32_t level) - { - ServerInfo_User user; - user.set_user_level(level); - handler.setUserInfo(user); - } -}; - -TEST_F(DeveloperRoleTest, RejectsWhenNotLoggedIn) -{ - CommandContainer cont; - cont.add_developer_command(); - handler.processCommandContainer(cont); - EXPECT_EQ(handler.lastResponseCode, Response::RespLoginNeeded); - EXPECT_EQ(handler.dispatchCount, 0); -} - -TEST_F(DeveloperRoleTest, RejectsPlainUser) -{ - setUserLevel(ServerInfo_User::IsUser | ServerInfo_User::IsRegistered); - - CommandContainer cont; - cont.add_developer_command(); - handler.processCommandContainer(cont); - EXPECT_EQ(handler.lastResponseCode, Response::RespLoginNeeded); - EXPECT_EQ(handler.dispatchCount, 0); -} - -TEST_F(DeveloperRoleTest, RejectsModeratorThatIsNotDeveloper) -{ - setUserLevel(ServerInfo_User::IsModerator); - - CommandContainer cont; - cont.add_developer_command(); - handler.processCommandContainer(cont); - EXPECT_EQ(handler.lastResponseCode, Response::RespLoginNeeded); -} - -TEST_F(DeveloperRoleTest, DispatchesToDeveloperCommandForDeveloper) -{ - setUserLevel(ServerInfo_User::IsDeveloper); - - CommandContainer cont; - DeveloperCommand *cmd = cont.add_developer_command(); - cmd->MutableExtension(Command_GetServerStats::ext); - handler.processCommandContainer(cont); - EXPECT_EQ(handler.lastResponseCode, Response::RespOk); - EXPECT_EQ(handler.dispatchCount, 1); -} - -TEST_F(DeveloperRoleTest, FailClosedForUnknownDeveloperCommand) -{ - setUserLevel(ServerInfo_User::IsDeveloper); - - CommandContainer cont; - cont.add_developer_command(); // no extension set -> getPbExtension() returns -1 - handler.processCommandContainer(cont); - EXPECT_EQ(handler.lastResponseCode, Response::RespFunctionNotAllowed); - EXPECT_EQ(handler.dispatchCount, 1); -} - -} // namespace - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -}