diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 8d15ed98..024f7834 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -6,8 +6,8 @@ PROJECT(cockatrice) SET(cockatrice_SOURCES src/abstractcounter.cpp - src/counter_general.cpp - src/dlg_creategame.cpp + src/counter_general.cpp + src/dlg_creategame.cpp src/dlg_filter_games.cpp src/dlg_connect.cpp src/dlg_create_token.cpp diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index c0a99c8c..f01e993e 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -225,7 +225,6 @@ int main(int argc, char *argv[]) ui.setWindowIcon(icon); settingsCache->setClientID(generateClientID()); - qDebug() << "ClientID In Cache: " << settingsCache->getClientID(); ui.show(); qDebug("main(): ui.show() finished"); diff --git a/cockatrice/src/user_context_menu.cpp b/cockatrice/src/user_context_menu.cpp index 9bf0f484..0949f355 100644 --- a/cockatrice/src/user_context_menu.cpp +++ b/cockatrice/src/user_context_menu.cpp @@ -11,12 +11,18 @@ #include "gameselector.h" #include "pending_command.h" +#include +#if QT_VERSION >= 0x050000 +#include +#endif + #include "pb/commands.pb.h" #include "pb/session_commands.pb.h" #include "pb/moderator_commands.pb.h" #include "pb/command_kick_from_game.pb.h" #include "pb/response_get_games_of_user.pb.h" #include "pb/response_get_user_info.pb.h" +#include "pb/response_ban_history.pb.h" UserContextMenu::UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *parent, TabGame *_game) : QObject(parent), client(_tabSupervisor->getClient()), tabSupervisor(_tabSupervisor), game(_game) @@ -32,6 +38,7 @@ UserContextMenu::UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *p aRemoveFromIgnoreList = new QAction(QString(), this); aKick = new QAction(QString(), this); aBan = new QAction(QString(), this); + aBanHistory = new QAction(QString(), this); aPromoteToMod = new QAction(QString(), this); aDemoteFromMod = new QAction(QString(), this); @@ -49,6 +56,7 @@ void UserContextMenu::retranslateUi() aRemoveFromIgnoreList->setText(tr("Remove from &ignore list")); aKick->setText(tr("Kick from &game")); aBan->setText(tr("Ban from &server")); + aBanHistory->setText(tr("View user's &ban history")); aPromoteToMod->setText(tr("&Promote user to moderator")); aDemoteFromMod->setText(tr("Dem&ote user from moderator")); } @@ -94,6 +102,39 @@ void UserContextMenu::banUser_processUserInfoResponse(const Response &r) dlg->show(); } +void UserContextMenu::banUserHistory_processResponse(const Response &resp) { + const Response_BanHistory &response = resp.GetExtension(Response_BanHistory::ext); + if (resp.response_code() == Response::RespOk) { + + if (response.ban_list_size() > 0) { + QTableWidget *table = new QTableWidget(); + table->setWindowTitle(tr("Ban History")); + table->setRowCount(response.ban_list_size()); + table->setColumnCount(5); + table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + table->setHorizontalHeaderLabels( + QString(tr("Ban Time;Moderator;Ban Length;Ban Reason;Visible Reason")).split(";")); + + ServerInfo_Ban ban; for (int i = 0; i < response.ban_list_size(); ++i) { + ban = response.ban_list(i); + table->setItem(i, 0, new QTableWidgetItem(QString::fromStdString(ban.ban_time()))); + table->setItem(i, 1, new QTableWidgetItem(QString::fromStdString(ban.admin_name()))); + table->setItem(i, 2, new QTableWidgetItem(QString::fromStdString(ban.ban_length()))); + table->setItem(i, 3, new QTableWidgetItem(QString::fromStdString(ban.ban_reason()))); + table->setItem(i, 4, new QTableWidgetItem(QString::fromStdString(ban.visible_reason()))); + } + + table->resizeColumnsToContents(); + table->setMinimumSize(table->horizontalHeader()->length() + (table->columnCount() * 5), table->verticalHeader()->length() + (table->rowCount() * 3)); + table->show(); + } else + QMessageBox::information(static_cast(parent()), tr("Ban History"), tr("User has never been banned.")); + + } else + QMessageBox::critical(static_cast(parent()), tr("Ban History"), tr("Failed to collecting ban information.")); +} + void UserContextMenu::adjustMod_processUserResponse(const Response &resp, const CommandContainer &commandContainer) { @@ -158,6 +199,7 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName if (!tabSupervisor->getAdminLocked()) { menu->addSeparator(); menu->addAction(aBan); + menu->addAction(aBanHistory); menu->addSeparator(); if (userLevel.testFlag(ServerInfo_User::IsModerator) && (tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsAdmin)) { @@ -177,6 +219,7 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName aRemoveFromIgnoreList->setEnabled(anotherUser); aKick->setEnabled(anotherUser); aBan->setEnabled(anotherUser); + aBanHistory->setEnabled(anotherUser); aPromoteToMod->setEnabled(anotherUser); aDemoteFromMod->setEnabled(anotherUser); @@ -239,6 +282,12 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName PendingCommand *pend = client->prepareAdminCommand(cmd); connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(adjustMod_processUserResponse(Response, CommandContainer))); client->sendCommand(pend); + } else if (actionClicked == aBanHistory) { + Command_GetBanHistory cmd; + cmd.set_user_name(userName.toStdString()); + PendingCommand *pend = client->prepareModeratorCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(banUserHistory_processResponse(Response))); + client->sendCommand(pend); } delete menu; diff --git a/cockatrice/src/user_context_menu.h b/cockatrice/src/user_context_menu.h index dd0d1ed5..2093616a 100644 --- a/cockatrice/src/user_context_menu.h +++ b/cockatrice/src/user_context_menu.h @@ -26,12 +26,13 @@ private: QAction *aAddToBuddyList, *aRemoveFromBuddyList; QAction *aAddToIgnoreList, *aRemoveFromIgnoreList; QAction *aKick; - QAction *aBan; + QAction *aBan, *aBanHistory; QAction *aPromoteToMod, *aDemoteFromMod; signals: void openMessageDialog(const QString &userName, bool focus); private slots: void banUser_processUserInfoResponse(const Response &resp); + void banUserHistory_processResponse(const Response &resp); void adjustMod_processUserResponse(const Response &resp, const CommandContainer &commandContainer); void banUser_dialogFinished(); void gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer); diff --git a/common/featureset.cpp b/common/featureset.cpp index f940a461..5ed53ac2 100644 --- a/common/featureset.cpp +++ b/common/featureset.cpp @@ -16,6 +16,7 @@ void FeatureSet::initalizeFeatureList(QMap &featureList){ featureList.insert("client_id", false); featureList.insert("client_ver", false); featureList.insert("feature_set", false); + featureList.insert("user_ban_history", false); } void FeatureSet::enableRequiredFeature(QMap &featureList, QString featureName){ diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index d58846c6..3aaf9860 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -116,6 +116,7 @@ SET(PROTO_FILES moderator_commands.proto move_card_to_zone.proto response_activate.proto + response_ban_history.proto response_deck_download.proto response_deck_list.proto response_deck_upload.proto @@ -133,6 +134,7 @@ SET(PROTO_FILES room_commands.proto room_event.proto serverinfo_arrow.proto + serverinfo_ban.proto serverinfo_cardcounter.proto serverinfo_card.proto serverinfo_counter.proto diff --git a/common/pb/moderator_commands.proto b/common/pb/moderator_commands.proto index 89672776..86e4e67f 100644 --- a/common/pb/moderator_commands.proto +++ b/common/pb/moderator_commands.proto @@ -2,6 +2,7 @@ syntax = "proto2"; message ModeratorCommand { enum ModeratorCommandType { BAN_FROM_SERVER = 1000; + BAN_HISTORY = 1001; } extensions 100 to max; } @@ -17,3 +18,10 @@ message Command_BanFromServer { optional string visible_reason = 5; optional string clientid = 6; } + +message Command_GetBanHistory { + extend ModeratorCommand { + optional Command_GetBanHistory ext = 1001; + } + optional string user_name = 1; +} \ No newline at end of file diff --git a/common/pb/response.proto b/common/pb/response.proto index ce2aec00..7004ba50 100644 --- a/common/pb/response.proto +++ b/common/pb/response.proto @@ -52,6 +52,7 @@ message Response { REGISTER = 1009; ACTIVATE = 1010; ADJUST_MOD = 1011; + BAN_HISTORY = 1012; REPLAY_LIST = 1100; REPLAY_DOWNLOAD = 1101; } diff --git a/common/pb/response_ban_history.proto b/common/pb/response_ban_history.proto new file mode 100644 index 00000000..de587d6d --- /dev/null +++ b/common/pb/response_ban_history.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +import "response.proto"; +import "serverinfo_ban.proto"; + +message Response_BanHistory{ + extend Response { + optional Response_BanHistory ext = 1012; + } + repeated ServerInfo_Ban ban_list = 1; +} diff --git a/common/pb/serverinfo_ban.proto b/common/pb/serverinfo_ban.proto new file mode 100644 index 00000000..2ad7ffd4 --- /dev/null +++ b/common/pb/serverinfo_ban.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; +/* + * Historical ban information stored in the ban table + */ +message ServerInfo_Ban { + required string admin_id = 1; // id of the staff member placing the ban + required string admin_name = 2; // name of the staff member placing the ban + required string ban_time = 3; // start time of the ban + required string ban_length = 4; // amount of time in minutes the ban is for + optional string ban_reason = 5; // reason seen only by moderation staff + optional string visible_reason = 6; // reason shown to the user +} diff --git a/common/server.cpp b/common/server.cpp index 873944b0..7274800c 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -40,6 +40,7 @@ Server::Server(bool _threaded, QObject *parent) : QObject(parent), threaded(_threaded), nextLocalGameId(0) { + qRegisterMetaType("ServerInfo_Ban"); qRegisterMetaType("ServerInfo_Game"); qRegisterMetaType("ServerInfo_Room"); qRegisterMetaType("ServerInfo_User"); diff --git a/common/server.h b/common/server.h index f1228b94..537f1a84 100644 --- a/common/server.h +++ b/common/server.h @@ -9,6 +9,7 @@ #include #include "pb/commands.pb.h" #include "pb/serverinfo_user.pb.h" +#include "pb/serverinfo_ban.pb.h" #include "server_player_reference.h" class Server_DatabaseInterface; diff --git a/common/server_metatypes.h b/common/server_metatypes.h index 4266218e..fb858c6c 100644 --- a/common/server_metatypes.h +++ b/common/server_metatypes.h @@ -3,6 +3,7 @@ #include +#include "pb/serverinfo_ban.pb.h" #include "pb/serverinfo_user.pb.h" #include "pb/serverinfo_room.pb.h" #include "pb/serverinfo_game.pb.h" @@ -12,6 +13,7 @@ #include "pb/isl_message.pb.h" #include "pb/room_commands.pb.h" +Q_DECLARE_METATYPE(ServerInfo_Ban) Q_DECLARE_METATYPE(ServerInfo_User) Q_DECLARE_METATYPE(ServerInfo_Room) Q_DECLARE_METATYPE(ServerInfo_Game) diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index f10e841f..f88af904 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -923,3 +923,33 @@ void Servatrice_DatabaseInterface::updateUsersLastLoginData(const QString &userN } } } + +QList Servatrice_DatabaseInterface::getUserBanHistory(const QString userName) +{ + QList results; + ServerInfo_Ban banDetails; + + if (!checkSql()) + return results; + + QSqlQuery *query = prepareQuery("SELECT A.id_admin, A.time_from, A.minutes, A.reason, A.visible_reason, B.name AS name_admin FROM {prefix}_bans A LEFT JOIN {prefix}_users B ON A.id_admin=B.id WHERE A.user_name = :user_name"); + query->bindValue(":user_name", userName); + + if (!execSqlQuery(query)) { + qDebug("Failed to collect ban history information: SQL Error"); + return results; + } + + QString adminID,adminName,banTime,banLength,banReason,visibleReason; + while (query->next()){ + banDetails.set_admin_id(QString(query->value(0).toString()).toStdString()); + banDetails.set_admin_name(QString(query->value(5).toString()).toStdString()); + banDetails.set_ban_time(QString(query->value(1).toString()).toStdString()); + banDetails.set_ban_length(QString(query->value(2).toString()).toStdString()); + banDetails.set_ban_reason(QString(query->value(3).toString()).toStdString()); + banDetails.set_visible_reason(QString(query->value(4).toString()).toStdString()); + results << banDetails; + } + + return results; +} diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index 99630c4e..de9c31fc 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -78,6 +78,7 @@ public: LogMessage_TargetType targetType, const int targetId, const QString &targetName); bool changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword); QChar getGenderChar(ServerInfo_User_Gender const &gender); + QList getUserBanHistory(const QString userName); }; #endif diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 83cb0a5f..5250ee4c 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -51,6 +51,7 @@ #include "pb/event_add_to_list.pb.h" #include "pb/event_remove_from_list.pb.h" #include "pb/event_notify_user.pb.h" +#include "pb/response_ban_history.pb.h" #include "pb/response_deck_list.pb.h" #include "pb/response_deck_download.pb.h" #include "pb/response_deck_upload.pb.h" @@ -60,6 +61,7 @@ #include "pb/serverinfo_replay.pb.h" #include "pb/serverinfo_user.pb.h" #include "pb/serverinfo_deckstorage.pb.h" +#include "pb/serverinfo_ban.pb.h" #include "version_string.h" #include @@ -301,6 +303,7 @@ Response::ResponseCode ServerSocketInterface::processExtendedModeratorCommand(in { switch ((ModeratorCommand::ModeratorCommandType) cmdType) { case ModeratorCommand::BAN_FROM_SERVER: return cmdBanFromServer(cmd.GetExtension(Command_BanFromServer::ext), rc); + case ModeratorCommand::BAN_HISTORY: return cmdGetBanHistory(cmd.GetExtension(Command_GetBanHistory::ext), rc); default: return Response::RespFunctionNotAllowed; } } @@ -747,6 +750,19 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDeleteMatch(const Command // MODERATOR FUNCTIONS. // May be called by admins and moderators. Permission is checked by the calling function. +Response::ResponseCode ServerSocketInterface::cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc) +{ + QList banList; + QString userName = QString::fromStdString(cmd.user_name()); + + Response_BanHistory *re = new Response_BanHistory; + QListIterator banIterator(sqlInterface->getUserBanHistory(userName)); + while (banIterator.hasNext()) + re->add_ban_list()->CopyFrom(banIterator.next()); + rc.setResponseExtension(re); + return Response::RespOk; +} + Response::ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer & /*rc*/) { if (!sqlInterface->checkSql()) diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index a733c6b7..894bd3a9 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -53,6 +53,7 @@ class Command_AccountEdit; class Command_AccountImage; class Command_AccountPassword; + class ServerSocketInterface : public Server_ProtocolHandler { Q_OBJECT @@ -95,6 +96,7 @@ private: Response::ResponseCode cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer &rc); Response::ResponseCode cmdReplayDeleteMatch(const Command_ReplayDeleteMatch &cmd, ResponseContainer &rc); Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc); + Response::ResponseCode cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc); Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc); Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc); Response::ResponseCode cmdRegisterAccount(const Command_Register &cmd, ResponseContainer &rc);