mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-22 01:25:10 -07:00
[Server/Client/Protocol] Add developer staff role
Introduce a Developer staff level (proto flag 32, DB admin bit 8) that sits between admin and moderator: no kick/ban/warn/report/admin powers, but gets server log access via a new developer command container family (GET_SERVER_STATS, VIEWLOG_HISTORY) and an idle-timeout exemption. - Protocol: IsDeveloper flag, developer_commands.proto envelope, Command_GetServerStats/Command_GetLogHistory, Response_GetServerStats, Command_AdjustMod.should_be_developer - Servatrice: fail-closed developer dispatcher, uptime snapshot handler, shared log history handler reuse, bit-8 DB mapping - Client: burgundy pawn/badge/labels/sort order, prepareDeveloperCommand, minimal Developer stats tab, log tab access, promote/demote actions Took 24 minutes Took 18 seconds
This commit is contained in:
parent
7d867b9745
commit
1ff7ffcaa4
31 changed files with 515 additions and 23 deletions
|
|
@ -51,6 +51,8 @@ UserContextMenu::UserContextMenu(TabSupervisor *_tabSupervisor, QWidget *parent,
|
|||
aDemoteFromMod = new QAction(QString(), this);
|
||||
aPromoteToJudge = new QAction(QString(), this);
|
||||
aDemoteFromJudge = new QAction(QString(), this);
|
||||
aPromoteToDeveloper = new QAction(QString(), this);
|
||||
aDemoteFromDeveloper = new QAction(QString(), this);
|
||||
aGetAdminNotes = new QAction(QString(), this);
|
||||
aInvestigateUser = new QAction(QString(), this);
|
||||
|
||||
|
|
@ -76,6 +78,8 @@ void UserContextMenu::retranslateUi()
|
|||
aDemoteFromMod->setText(tr("Dem&ote user from moderator"));
|
||||
aPromoteToJudge->setText(tr("Promote user to &judge"));
|
||||
aDemoteFromJudge->setText(tr("Demote user from judge"));
|
||||
aPromoteToDeveloper->setText(tr("Promote user to &developer"));
|
||||
aDemoteFromDeveloper->setText(tr("Demote user from de&veloper"));
|
||||
aGetAdminNotes->setText(tr("View admin notes"));
|
||||
aInvestigateUser->setText(tr("Investigate user"));
|
||||
}
|
||||
|
|
@ -268,7 +272,7 @@ void UserContextMenu::adjustMod_processUserResponse(const Response &resp, const
|
|||
const Command_AdjustMod &cmd = commandContainer.admin_command(0).GetExtension(Command_AdjustMod::ext);
|
||||
|
||||
if (resp.response_code() == Response::RespOk) {
|
||||
if (cmd.should_be_mod() || cmd.should_be_judge()) {
|
||||
if (cmd.should_be_mod() || cmd.should_be_judge() || cmd.should_be_developer()) {
|
||||
QMessageBox::information(static_cast<QWidget *>(parent()), tr("Success"),
|
||||
tr("Successfully promoted user."));
|
||||
} else {
|
||||
|
|
@ -276,7 +280,7 @@ void UserContextMenu::adjustMod_processUserResponse(const Response &resp, const
|
|||
}
|
||||
|
||||
} else {
|
||||
if (cmd.should_be_mod() || cmd.should_be_judge()) {
|
||||
if (cmd.should_be_mod() || cmd.should_be_judge() || cmd.should_be_developer()) {
|
||||
QMessageBox::information(static_cast<QWidget *>(parent()), tr("Failed"), tr("Failed to promote user."));
|
||||
} else {
|
||||
QMessageBox::information(static_cast<QWidget *>(parent()), tr("Failed"), tr("Failed to demote user."));
|
||||
|
|
@ -437,6 +441,15 @@ void UserContextMenu::showContextMenu(const QPoint &pos,
|
|||
(tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsAdmin)) {
|
||||
menu->addAction(aPromoteToJudge);
|
||||
}
|
||||
|
||||
if (userLevel.testFlag(ServerInfo_User::IsDeveloper) &&
|
||||
(tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsAdmin)) {
|
||||
menu->addAction(aDemoteFromDeveloper);
|
||||
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsRegistered) &&
|
||||
(tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsAdmin)) {
|
||||
menu->addAction(aPromoteToDeveloper);
|
||||
}
|
||||
}
|
||||
aDetails->setEnabled(true);
|
||||
aChat->setEnabled(anotherUser && online && !userListProxy->isUserIgnored(userName));
|
||||
|
|
@ -455,6 +468,10 @@ void UserContextMenu::showContextMenu(const QPoint &pos,
|
|||
aInvestigateUser->setEnabled(anotherUser);
|
||||
aPromoteToMod->setEnabled(anotherUser);
|
||||
aDemoteFromMod->setEnabled(anotherUser);
|
||||
aPromoteToJudge->setEnabled(anotherUser);
|
||||
aDemoteFromJudge->setEnabled(anotherUser);
|
||||
aPromoteToDeveloper->setEnabled(anotherUser);
|
||||
aDemoteFromDeveloper->setEnabled(anotherUser);
|
||||
|
||||
QAction *actionClicked = menu->exec(pos);
|
||||
if (actionClicked == nullptr) {
|
||||
|
|
@ -489,6 +506,8 @@ void UserContextMenu::showContextMenu(const QPoint &pos,
|
|||
execAdjustMod(userName, actionClicked == aPromoteToMod);
|
||||
} else if (actionClicked == aPromoteToJudge || actionClicked == aDemoteFromJudge) {
|
||||
execAdjustJudge(userName, actionClicked == aPromoteToJudge);
|
||||
} else if (actionClicked == aPromoteToDeveloper || actionClicked == aDemoteFromDeveloper) {
|
||||
execAdjustDeveloper(userName, actionClicked == aPromoteToDeveloper);
|
||||
} else if (actionClicked == aBanHistory) {
|
||||
execBanHistory(userName);
|
||||
} else if (actionClicked == aWarnUser) {
|
||||
|
|
@ -706,4 +725,14 @@ void UserContextMenu::execAdjustJudge(const QString &userName, bool shouldBeJudg
|
|||
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
||||
client->sendCommand(pend);
|
||||
}
|
||||
|
||||
void UserContextMenu::execAdjustDeveloper(const QString &userName, bool shouldBeDeveloper)
|
||||
{
|
||||
Command_AdjustMod cmd;
|
||||
cmd.set_user_name(userName.toStdString());
|
||||
cmd.set_should_be_developer(shouldBeDeveloper);
|
||||
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
||||
client->sendCommand(pend);
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ private:
|
|||
QAction *aBan, *aBanHistory;
|
||||
QAction *aPromoteToMod, *aDemoteFromMod;
|
||||
QAction *aPromoteToJudge, *aDemoteFromJudge;
|
||||
QAction *aPromoteToDeveloper, *aDemoteFromDeveloper;
|
||||
QAction *aWarnUser, *aWarnHistory;
|
||||
QAction *aGetAdminNotes;
|
||||
std::function<QList<GameInviteOption>()> gameInviteLinkProvider;
|
||||
|
|
@ -123,6 +124,7 @@ public:
|
|||
void execInvestigateUser(const QString &userName);
|
||||
void execAdjustMod(const QString &userName, bool shouldBeMod);
|
||||
void execAdjustJudge(const QString &userName, bool shouldBeJudge);
|
||||
void execAdjustDeveloper(const QString &userName, bool shouldBeDeveloper);
|
||||
|
||||
private:
|
||||
void execInvite(const QString &userName, const GameInviteOption &option);
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user)
|
|||
QString userLevelText;
|
||||
if (userLevel.testFlag(ServerInfo_User::IsAdmin)) {
|
||||
userLevelText = tr("Administrator");
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsDeveloper)) {
|
||||
userLevelText = tr("Developer");
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsModerator)) {
|
||||
userLevelText = tr("Moderator");
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsRegistered)) {
|
||||
|
|
|
|||
|
|
@ -245,6 +245,9 @@ void UserInfoHeaderWidget::paintEvent(QPaintEvent *)
|
|||
if (level.testFlag(ServerInfo_User::IsAdmin)) {
|
||||
return QColor(245, 158, 11);
|
||||
}
|
||||
if (level.testFlag(ServerInfo_User::IsDeveloper)) {
|
||||
return QColor(185, 28, 28);
|
||||
}
|
||||
if (level.testFlag(ServerInfo_User::IsModerator)) {
|
||||
return QColor(59, 130, 246);
|
||||
}
|
||||
|
|
@ -300,6 +303,8 @@ void UserInfoHeaderWidget::paintEvent(QPaintEvent *)
|
|||
} badge;
|
||||
if (level.testFlag(ServerInfo_User::IsAdmin)) {
|
||||
badge = {"ADMIN", QColor(245, 158, 11)};
|
||||
} else if (level.testFlag(ServerInfo_User::IsDeveloper)) {
|
||||
badge = {"DEV", QColor(185, 28, 28)};
|
||||
} else if (level.testFlag(ServerInfo_User::IsModerator)) {
|
||||
badge = {"MOD", QColor(59, 130, 246)};
|
||||
} else if (level.testFlag(ServerInfo_User::IsJudge)) {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ QColor UserListPainter::getAccentColor(const UserLevelFlags &userLevel, bool onl
|
|||
|
||||
if (userLevel.testFlag(ServerInfo_User::IsAdmin)) {
|
||||
accentColor = QColor(245, 158, 11);
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsDeveloper)) {
|
||||
accentColor = QColor(185, 28, 28);
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsModerator)) {
|
||||
accentColor = QColor(59, 130, 246);
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsJudge)) {
|
||||
|
|
@ -299,6 +301,8 @@ QList<UserListPainter::Badge> UserListPainter::buildBadges(const UserLevelFlags
|
|||
|
||||
if (userLevel.testFlag(ServerInfo_User::IsAdmin)) {
|
||||
badges << Badge{"ADMIN", QColor(245, 158, 11)};
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsDeveloper)) {
|
||||
badges << Badge{"DEV", QColor(185, 28, 28)};
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsModerator)) {
|
||||
badges << Badge{"MOD", QColor(59, 130, 246)};
|
||||
} else if (userLevel.testFlag(ServerInfo_User::IsJudge)) {
|
||||
|
|
@ -385,9 +389,9 @@ void UserListPainter::paint(QPainter *painter,
|
|||
const QString userName = QString::fromStdString(userInfo.name());
|
||||
const QString privLevel = QString::fromStdString(userInfo.privlevel());
|
||||
const QColor accentColor = getAccentColor(userLevel, online);
|
||||
const bool hasRole = userLevel.testFlag(ServerInfo_User::IsAdmin) ||
|
||||
userLevel.testFlag(ServerInfo_User::IsModerator) ||
|
||||
userLevel.testFlag(ServerInfo_User::IsJudge);
|
||||
const bool hasRole =
|
||||
userLevel.testFlag(ServerInfo_User::IsAdmin) || userLevel.testFlag(ServerInfo_User::IsDeveloper) ||
|
||||
userLevel.testFlag(ServerInfo_User::IsModerator) || userLevel.testFlag(ServerInfo_User::IsJudge);
|
||||
const QRectF cardRect = QRectF(rect).adjusted(3, 2, -3, -2);
|
||||
const int cardRight = getCardRight(option, rect);
|
||||
|
||||
|
|
|
|||
|
|
@ -234,9 +234,11 @@ bool UserListTWI::operator<(const QTreeWidgetItem &other) const
|
|||
const auto &lhsUserLevelFlags = UserLevelFlags(data(0, Qt::UserRole).toInt());
|
||||
const auto &rhsUserLevelFlags = UserLevelFlags(other.data(0, Qt::UserRole).toInt());
|
||||
|
||||
// Admins & Mods need no additional comparison checks, just to see if they're an admin or a moderator
|
||||
// Admins, Developers & Mods need no additional comparison checks, just to see if they're an admin, a developer
|
||||
// or a moderator
|
||||
static const QList<ServerInfo_User_UserLevelFlag> userLevelWithNoOtherPrefOrder = {
|
||||
ServerInfo_User_UserLevelFlag_IsAdmin, ServerInfo_User_UserLevelFlag_IsModerator};
|
||||
ServerInfo_User_UserLevelFlag_IsAdmin, ServerInfo_User_UserLevelFlag_IsDeveloper,
|
||||
ServerInfo_User_UserLevelFlag_IsModerator};
|
||||
for (const auto &userLevelEntry : userLevelWithNoOtherPrefOrder) {
|
||||
if (lhsUserLevelFlags.testFlag(userLevelEntry) &&
|
||||
lhsUserLevelFlags.testFlag(userLevelEntry) == rhsUserLevelFlags.testFlag(userLevelEntry)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue