[Server/Client/Protocol] Address developer role review feedback

Address ZeizaZach's review of the developer staff role:

- Nudge the developer log query to exclude private chat and sender IPs
  (the ModeratorCommand path still sees everything).
- Deduplicate Command_GetLogHistory into Command_ViewLogHistory, which now
  extends both ModeratorCommand (ext) and DeveloperCommand (dev_ext); the
  client picks the DeveloperCommand-scoped extension by extendee, and the
  server reads it via the extension number.
- Pull the uptime snapshot SQL into Servatrice_DatabaseInterface as
  getLatestUptimeSnapshot() and widen the reported counters to 64-bit.
- Document the admin bitfield (1 admin, 2 moderator, 4 judge, 8 developer)
  and add a server-side test for the developer command path.
This commit is contained in:
Lukas Brübach 2026-08-30 21:06:31 +02:00
parent 1ff7ffcaa4
commit 1dc20176b3
14 changed files with 251 additions and 76 deletions

View file

@ -94,7 +94,7 @@ void TabDeveloper::refreshClicked()
void TabDeveloper::serverStatsResponse(const Response &resp)
{
if (resp.response_code() != Response::RespOk) {
statusLabel->setText(tr("Failed to collect server statistics."));
statusLabel->setText(tr("No server statistics available yet."));
return;
}

View file

@ -14,7 +14,6 @@
#include <QTabWidget>
#include <QTableWidget>
#include <libcockatrice/network/client/abstract/abstract_client.h>
#include <libcockatrice/protocol/pb/command_get_log_history.pb.h>
#include <libcockatrice/protocol/pb/moderator_commands.pb.h>
#include <libcockatrice/protocol/pb/response_viewlog_history.pb.h>
#include <libcockatrice/protocol/pending_command.h>
@ -82,7 +81,9 @@ void TabLog::getClicked()
if (!mainRoom->isChecked() && !gameRoom->isChecked() && !privateChat->isChecked()) {
mainRoom->setChecked(true);
gameRoom->setChecked(true);
privateChat->setChecked(true);
if (!canUseDeveloperCommands) {
privateChat->setChecked(true);
}
}
if (maximumResults->value() == 0) {
@ -123,18 +124,7 @@ void TabLog::getClicked()
PendingCommand *pend;
if (canUseDeveloperCommands) {
// Developers query logs through the developer command family.
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);
pend = client->prepareDeveloperCommand(cmd);
} else {
pend = client->prepareModeratorCommand(cmd);
}
@ -192,6 +182,10 @@ 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"));

View file

@ -844,10 +844,10 @@ void TabSupervisor::actTabLog(bool checked)
void TabSupervisor::openTabLog()
{
// 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);
// 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);
myAddTab(tabLog, aTabLog);
connect(tabLog, &QObject::destroyed, this, [this] {
tabLog = nullptr;