From 2f23a9cb2f2f0ad0e020ae38a486b162d8d762fc Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Wed, 22 Mar 2017 21:45:16 -0400 Subject: [PATCH] Smarter rooms (#2484) * Added VIP only room * Added DONATOR room. * Extended Room to include privilege level. * Updated room join logic * Updated server tab permissions column display based on perm+privlevel definitions * Fixed new client -> old server blank permissions column on server tab Added the ability for registered user - VIP/DONATOR/PRIVILEGED room. --- cockatrice/src/localserver.cpp | 2 +- cockatrice/src/tab_server.cpp | 24 ++++++++++++-- cockatrice/src/tab_server.h | 1 + common/pb/serverinfo_room.proto | 1 + common/server_protocolhandler.cpp | 20 ++---------- common/server_room.cpp | 31 +++++++++++++++++-- common/server_room.h | 5 ++- .../migrations/servatrice_0022_to_0023.sql | 6 ++++ servatrice/servatrice.ini.example | 4 +++ servatrice/servatrice.sql | 5 +-- servatrice/src/servatrice.cpp | 11 ++++--- .../src/servatrice_database_interface.h | 2 +- 12 files changed, 79 insertions(+), 33 deletions(-) create mode 100644 servatrice/migrations/servatrice_0022_to_0023.sql diff --git a/cockatrice/src/localserver.cpp b/cockatrice/src/localserver.cpp index e9035e82..22fcfc1c 100644 --- a/cockatrice/src/localserver.cpp +++ b/cockatrice/src/localserver.cpp @@ -6,7 +6,7 @@ LocalServer::LocalServer(QObject *parent) : Server(parent) { setDatabaseInterface(new LocalServer_DatabaseInterface(this)); - addRoom(new Server_Room(0, 0, QString(), QString(), QString(), false, QString(), QStringList(), this)); + addRoom(new Server_Room(0, 0, QString(), QString(), QString(), QString(), false, QString(), QStringList(), this)); } LocalServer::~LocalServer() diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index c203d363..787b08d8 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -71,7 +71,7 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event) const int roomListSize = event.room_list_size(); for (int i = 0; i < roomListSize; ++i) { const ServerInfo_Room &room = event.room_list(i); - + for (int j = 0; j < roomList->topLevelItemCount(); ++j) { QTreeWidgetItem *twi = roomList->topLevelItem(j); if (twi->data(0, Qt::UserRole).toInt() == room.room_id()) { @@ -80,7 +80,7 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event) if (room.has_description()) twi->setData(1, Qt::DisplayRole, QString::fromStdString(room.description())); if (room.has_permissionlevel()) - twi->setData(2, Qt::DisplayRole, QString::fromStdString(room.permissionlevel()).toLower()); + twi->setData(2, Qt::DisplayRole, getRoomPermissionDisplay(room)); if (room.has_player_count()) twi->setData(3, Qt::DisplayRole, room.player_count()); if (room.has_game_count()) @@ -95,7 +95,7 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event) if (room.has_description()) twi->setData(1, Qt::DisplayRole, QString::fromStdString(room.description())); if (room.has_permissionlevel()) - twi->setData(2, Qt::DisplayRole, QString::fromStdString(room.permissionlevel()).toLower()); + twi->setData(2, Qt::DisplayRole, getRoomPermissionDisplay(room)); twi->setData(3, Qt::DisplayRole, room.player_count()); twi->setData(4, Qt::DisplayRole, room.game_count()); twi->setTextAlignment(2, Qt::AlignRight); @@ -109,6 +109,24 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event) } } +QString RoomSelector::getRoomPermissionDisplay(const ServerInfo_Room & room) +{ + /* + * A room can have a permission level and a privilege level. How ever we want to display only the necessary information + * on the server tab needed to inform users of required permissions to enter a room. If the room has a privilege level + * the server tab will display the privilege level in the "permissions" column in the row however if the room contains + * a permissions level for the room the permissions level defined for the room will be displayed. + */ + + QString roomPermissionDisplay = QString::fromStdString(room.privilegelevel()).toLower(); + if (QString::fromStdString(room.permissionlevel()).toLower() != "none") + roomPermissionDisplay = QString::fromStdString(room.permissionlevel()).toLower(); + if (roomPermissionDisplay == "") // catch all for misconfigured .ini room definitions + roomPermissionDisplay = "none"; + + return roomPermissionDisplay; +} + void RoomSelector::joinClicked() { QTreeWidgetItem *twi = roomList->currentItem(); diff --git a/cockatrice/src/tab_server.h b/cockatrice/src/tab_server.h index b7cd4e2a..baa8b6a6 100644 --- a/cockatrice/src/tab_server.h +++ b/cockatrice/src/tab_server.h @@ -24,6 +24,7 @@ private: QTreeWidget *roomList; QPushButton *joinButton; AbstractClient *client; + QString getRoomPermissionDisplay(const ServerInfo_Room &room); private slots: void processListRoomsEvent(const Event_ListRooms &event); void joinClicked(); diff --git a/common/pb/serverinfo_room.proto b/common/pb/serverinfo_room.proto index 571bc6f7..c1c2e363 100644 --- a/common/pb/serverinfo_room.proto +++ b/common/pb/serverinfo_room.proto @@ -14,4 +14,5 @@ message ServerInfo_Room { repeated ServerInfo_User user_list = 8; repeated ServerInfo_GameType gametype_list = 9; optional string permissionlevel = 10; + optional string privilegelevel = 11; } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 819736e7..85d5f8dc 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -620,23 +620,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoo if (!r) return Response::RespNameNotFound; - QString roomPermission = r->getRoomPermission().toLower(); - if (roomPermission != "none"){ - if (roomPermission == "registered") { - if (!(userInfo->user_level() & ServerInfo_User::IsRegistered)) - return Response::RespUserLevelTooLow; - } - - if (roomPermission == "moderator"){ - if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) - return Response::RespUserLevelTooLow; - } - - if (roomPermission == "administrator"){ - if (!(userInfo->user_level() & ServerInfo_User::IsAdmin)) - return Response::RespUserLevelTooLow; - } - } + if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) + if (!(r->userMayJoin(*userInfo))) + return Response::RespUserLevelTooLow; r->addClient(this); rooms.insert(r->getId(), r); diff --git a/common/server_room.cpp b/common/server_room.cpp index e9338627..752b5fee 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -14,8 +14,8 @@ #include "pb/serverinfo_chat_message.pb.h" #include -Server_Room::Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) - : QObject(parent), id(_id), chatHistorySize(_chatHistorySize), name(_name), description(_description), permissionLevel(_permissionLevel), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), gamesLock(QReadWriteLock::Recursive) +Server_Room::Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, const QString &_privilegeLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) + : QObject(parent), id(_id), chatHistorySize(_chatHistorySize), name(_name), description(_description), permissionLevel(_permissionLevel), privilegeLevel(_privilegeLevel), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), gamesLock(QReadWriteLock::Recursive) { connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)), Qt::QueuedConnection); } @@ -36,6 +36,31 @@ Server_Room::~Server_Room() usersLock.unlock(); } +bool Server_Room::userMayJoin(const ServerInfo_User & userInfo) +{ + + if (permissionLevel.toLower() == "administrator" || permissionLevel.toLower() == "moderator") + return false; + + if (permissionLevel.toLower() == "registered" && !(userInfo.user_level() & ServerInfo_User::IsRegistered)) + return false; + + if (privilegeLevel.toLower() != "none") + { + if (privilegeLevel.toLower() == "privileged") + { + if (privilegeLevel.toLower() == "none") + return false; + } + else + { + if (privilegeLevel.toLower() != QString::fromStdString(userInfo.privlevel()).toLower()) + return false; + } + } + return true; +} + Server *Server_Room::getServer() const { return static_cast(parent()); @@ -44,11 +69,11 @@ Server *Server_Room::getServer() const const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, bool includeExternalData) const { result.set_room_id(id); - result.set_name(name.toStdString()); result.set_description(description.toStdString()); result.set_auto_join(autoJoin); result.set_permissionlevel(permissionLevel.toStdString()); + result.set_privilegelevel(privilegeLevel.toStdString()); gamesLock.lockForRead(); result.set_game_count(games.size() + externalGames.size()); diff --git a/common/server_room.h b/common/server_room.h index af652944..edf2d3fd 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -35,6 +35,7 @@ private: QString name; QString description; QString permissionLevel; + QString privilegeLevel; bool autoJoin; QString joinMessage; QStringList gameTypes; @@ -49,13 +50,15 @@ public: mutable QReadWriteLock usersLock; mutable QReadWriteLock gamesLock; mutable QReadWriteLock historyLock; - Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent ); + Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, const QString &_privilegeLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent ); ~Server_Room(); int getId() const { return id; } QString getName() const { return name; } QString getDescription() const { return description; } QString getRoomPermission() const { return permissionLevel; } + QString getRoomPrivilege() const { return privilegeLevel; } bool getAutoJoin() const { return autoJoin; } + bool userMayJoin(const ServerInfo_User &userInfo); QString getJoinMessage() const { return joinMessage; } const QStringList &getGameTypes() const { return gameTypes; } const QMap &getGames() const { return games; } diff --git a/servatrice/migrations/servatrice_0022_to_0023.sql b/servatrice/migrations/servatrice_0022_to_0023.sql new file mode 100644 index 00000000..12109afa --- /dev/null +++ b/servatrice/migrations/servatrice_0022_to_0023.sql @@ -0,0 +1,6 @@ +-- Servatrice db migration from version 22 to version 23 + +alter table cockatrice_rooms modify column permissionlevel enum('NONE','REGISTERED','MODERATOR','ADMINISTRATOR'); +alter table cockatrice_rooms add column privlevel enum('NONE','PRIVILEGED','VIP','DONATOR') NOT NULL; + +UPDATE cockatrice_schema_version SET version=23 WHERE version=22; diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 5cd5f7c3..0bd49e7f 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -261,6 +261,10 @@ roomlist\1\description="Play anything here." ; Default is none. roomlist\1\permissionlevel=none +; Rooms can restrict the permission level of users that can join, Currnetly supported options are none, privileged, vip, and donator. +; Default is none. +roomlist\1\privilegelevel=none + ; Wether to make users autojoin this room when connected to the server roomlist\1\autojoin=true diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index d3f2a36d..893ef323 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_schema_version` ( PRIMARY KEY (`version`) ) ENGINE=INNODB DEFAULT CHARSET=utf8; -INSERT INTO cockatrice_schema_version VALUES(22); +INSERT INTO cockatrice_schema_version VALUES(23); -- users and user data tables CREATE TABLE IF NOT EXISTS `cockatrice_users` ( @@ -89,7 +89,8 @@ CREATE TABLE IF NOT EXISTS `cockatrice_rooms` ( `id` int(7) unsigned NOT NULL auto_increment, `name` varchar(50) NOT NULL, `descr` varchar(255) NOT NULL, - `permissionlevel` varchar(20) NOT NULL, + `permissionlevel` enum('NONE','REGISTERED','MODERATOR','ADMINISTRATOR') NOT NULL, + `privlevel` enum('NONE','PRIVILEGED','VIP','DONATOR') NOT NULL, `auto_join` tinyint(1) default 0, `join_message` varchar(255) NOT NULL, `chat_history_size` int(4) NOT NULL, diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 7d7bfc04..0139ca37 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -285,7 +285,7 @@ bool Servatrice::initServer() } if (getRoomsMethodString() == "sql") { - QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select id, name, descr, permissionlevel, auto_join, join_message, chat_history_size from {prefix}_rooms where id_server = :id_server order by id asc"); + QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select id, name, descr, permissionlevel, privlevel, auto_join, join_message, chat_history_size from {prefix}_rooms where id_server = :id_server order by id asc"); query->bindValue(":id_server", serverId); servatriceDatabaseInterface->execSqlQuery(query); while (query->next()) { @@ -301,8 +301,9 @@ bool Servatrice::initServer() query->value(1).toString(), query->value(2).toString(), query->value(3).toString().toLower(), - query->value(4).toInt(), - query->value(5).toString(), + query->value(4).toString().toLower(), + query->value(5).toInt(), + query->value(6).toString(), gameTypes, this)); } @@ -317,13 +318,13 @@ bool Servatrice::initServer() gameTypes.append(settingsCache->value("name").toString()); } settingsCache->endArray(); - Server_Room *newRoom = new Server_Room(i,settingsCache->value("chathistorysize").toInt(),settingsCache->value("name").toString(),settingsCache->value("description").toString(),settingsCache->value("permissionlevel").toString().toLower(),settingsCache->value("autojoin").toBool(),settingsCache->value("joinmessage").toString(),gameTypes,this); + Server_Room *newRoom = new Server_Room(i,settingsCache->value("chathistorysize").toInt(),settingsCache->value("name").toString(),settingsCache->value("description").toString(),settingsCache->value("permissionlevel").toString().toLower(),settingsCache->value("privilegelevel").toString().toLower(),settingsCache->value("autojoin").toBool(),settingsCache->value("joinmessage").toString(),gameTypes,this); addRoom(newRoom); } if(size==0) { // no room defined in config, add a dummy one - Server_Room *newRoom = new Server_Room(0,100,"General room","Play anything here.","none",true,"",QStringList("Standard"),this); + Server_Room *newRoom = new Server_Room(0,100,"General room","Play anything here.","none","none",true,"",QStringList("Standard"),this); addRoom(newRoom); } diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index bfdb7810..21cbc111 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -9,7 +9,7 @@ #include "server.h" #include "server_database_interface.h" -#define DATABASE_SCHEMA_VERSION 22 +#define DATABASE_SCHEMA_VERSION 23 class Servatrice;