feat(Core/RBAC): Role Based Access Controls (#24641)

Co-authored-by: blinkysc <blinkysc@users.noreply.github.com>
Co-authored-by: Spp <spp@jorge.gr>
Co-authored-by: Spp <spp@tc.plus>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Andrew <47818697+Nyeriah@users.noreply.github.com>
This commit is contained in:
blinkysc
2026-05-01 07:19:30 -05:00
committed by GitHub
parent a783e6c436
commit 779331fc4b
97 changed files with 6276 additions and 1089 deletions
@@ -24,6 +24,7 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
#include "RBAC.h"
#include "ScriptMgr.h"
#include "World.h"
#include "WorldPacket.h"
@@ -321,6 +322,13 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) created auction: {} (Item: {} Count: {}) Bid: {} Buyout: {}",
_player->GetName(), GetAccountId(), AH->Id,
item->GetTemplate()->Name1, item->GetCount(), bid, buyout);
}
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
LOG_INFO("entities.player.auctionhouse", "AuctionHouse: Account: {} (IP: {}), Player [{}] (GUID: {}) created auction #{}: Item '{}' (Entry: {}) x{}, StartBid: {} copper, Buyout: {} copper, Deposit: {} copper",
@@ -388,6 +396,13 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) created auction: {} (Item: {} Count: {}) Bid: {} Buyout: {}",
_player->GetName(), GetAccountId(), AH->Id,
newItem->GetTemplate()->Name1, newItem->GetCount(), bid, buyout);
}
GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
LOG_INFO("entities.player.auctionhouse", "AuctionHouse: Account: {} (IP: {}), Player [{}] (GUID: {}) created auction #{}: Item '{}' (Entry: {}) x{}, StartBid: {} copper, Buyout: {} copper, Deposit: {} copper",
@@ -501,6 +516,13 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK, 0);
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) bid on auction: {} (Item: {} Count: {}) Bid: {}",
player->GetName(), GetAccountId(), auction->Id,
auction->item_template, auction->itemCount, price);
}
LOG_INFO("entities.player.auctionhouse", "AuctionHouse: Account: {} (IP: {}), Player [{}] (GUID: {}) placed bid on auction #{}: Item (Entry: {}) x{}, Bid: {} copper, Owner: {} (GUID: {})",
GetAccountId(), GetRemoteAddress(), player->GetName(), player->GetGUID().GetCounter(),
auction->Id, auction->item_template, auction->itemCount, price, auction->owner.GetCounter(), auction->owner.GetCounter());
@@ -528,6 +550,13 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData)
SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK);
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) bought out auction: {} (Item: {} Count: {}) Buyout: {}",
player->GetName(), GetAccountId(), auction->Id,
auction->item_template, auction->itemCount, auction->buyout);
}
LOG_INFO("entities.player.auctionhouse", "AuctionHouse: Account: {} (IP: {}), Player [{}] (GUID: {}) bought out auction #{}: Item (Entry: {}) x{}, Buyout: {} copper, Owner: {} (GUID: {})",
GetAccountId(), GetRemoteAddress(), player->GetName(), player->GetGUID().GetCounter(),
auction->Id, auction->item_template, auction->itemCount, auction->buyout, auction->owner.GetCounter(), auction->owner.GetCounter());
@@ -161,7 +161,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{
err = ERR_LFG_CANT_USE_BATTLEGROUND;
}
else if (!_player->CanJoinToBattleground()) // has deserter debuff
else if (!_player->CanJoinToBattleground(bg)) // has deserter debuff
{
err = ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS;
}
@@ -473,7 +473,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
if (action == 1 && ginfo.ArenaType == 0)
{
// can't join with deserter, check it here right before joining to be sure
if (!_player->CanJoinToBattleground())
if (!_player->CanJoinToBattleground(bg))
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
+33 -17
View File
@@ -17,6 +17,7 @@
#include "AccountMgr.h"
#include "AreaDefines.h"
#include "RBAC.h"
#include "ArenaTeamMgr.h"
#include "AuctionHouseMgr.h"
#include "Battleground.h"
@@ -285,7 +286,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
>> createInfo->FacialHair
>> createInfo->OutfitId;
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK))
{
if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED))
{
@@ -329,7 +330,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
return;
}
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (createInfo->Race - 1)) & raceMaskDisabled)
@@ -337,7 +338,10 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
SendCharCreate(CHAR_CREATE_DISABLED);
return;
}
}
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK))
{
uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
if ((1 << (createInfo->Class - 1)) & classMaskDisabled)
{
@@ -358,13 +362,16 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
uint8 res = ObjectMgr::CheckPlayerName(createInfo->Name, true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharCreate(ResponseCodes(res));
return;
if (res != CHAR_NAME_RESERVED || !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME))
{
SendCharCreate(ResponseCodes(res));
return;
}
}
// speedup check for heroic class disabled case
uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
if (heroic_free_slots == 0 && AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT)
if (heroic_free_slots == 0 && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEATH_KNIGHT) && createInfo->Class == CLASS_DEATH_KNIGHT)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
return;
@@ -372,7 +379,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// speedup check for heroic class disabled case
uint32 req_level_for_heroic = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEATH_KNIGHT) && createInfo->Class == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
return;
@@ -427,7 +434,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
}
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
@@ -440,9 +447,9 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
bool haveSameRace = false;
uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
bool hasHeroicReqLevel = (heroicReqLevel == 0);
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
bool checkDeathKnightReqs = AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT;
bool checkDeathKnightReqs = !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEATH_KNIGHT) && createInfo->Class == CLASS_DEATH_KNIGHT;
if (result)
{
@@ -1365,8 +1372,11 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
uint8 res = ObjectMgr::CheckPlayerName(renameInfo->Name, true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharRename(ResponseCodes(res), renameInfo.get());
return;
if (res != CHAR_NAME_RESERVED || !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME))
{
SendCharRename(ResponseCodes(res), renameInfo.get());
return;
}
}
// Ensure that the character belongs to the current account, that rename at login is enabled
@@ -1705,8 +1715,11 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomiz
ResponseCodes res = static_cast<ResponseCodes>(ObjectMgr::CheckPlayerName(customizeInfo->Name, true));
if (res != CHAR_NAME_SUCCESS)
{
SendCharCustomize(res, customizeInfo.get());
return;
if (res != CHAR_NAME_RESERVED || !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME))
{
SendCharCustomize(res, customizeInfo.get());
return;
}
}
// character with this name already exist
@@ -2084,7 +2097,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
return;
}
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (factionChangeInfo->Race - 1)) & raceMaskDisabled)
@@ -2104,8 +2117,11 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
ResponseCodes res = static_cast<ResponseCodes>(ObjectMgr::CheckPlayerName(factionChangeInfo->Name, true));
if (res != CHAR_NAME_SUCCESS)
{
SendCharFactionChange(res, factionChangeInfo.get());
return;
if (res != CHAR_NAME_RESERVED || !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME))
{
SendCharFactionChange(res, factionChangeInfo.get());
return;
}
}
// character with this name already exist
@@ -2321,7 +2337,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
guild->DeleteMember(factionChangeInfo->Guid, false, false, true);
}
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND))
if (!HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
{
// Delete Friend List
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SOCIAL_BY_GUID);
+9 -7
View File
@@ -17,6 +17,7 @@
#include "AccountMgr.h"
#include "CellImpl.h"
#include "RBAC.h"
#include "ChannelMgr.h"
#include "Chat.h"
#include "ChatPackets.h"
@@ -112,7 +113,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
// pussywizard: chatting on most chat types requires 2 hours played to prevent spam/abuse
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ))
{
switch (type)
{
@@ -382,8 +383,8 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
Player* receiver = ObjectAccessor::FindPlayerByName(to, false);
bool senderIsPlayer = AccountMgr::IsPlayerAccount(GetSecurity());
bool receiverIsPlayer = AccountMgr::IsPlayerAccount(receiver ? receiver->GetSession()->GetSecurity() : SEC_PLAYER);
bool senderIsPlayer = !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT);
bool receiverIsPlayer = receiver ? !receiver->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT) : true;
if (sender->GetLevel() < sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ) && receiver != sender && receiver && !receiver->IsGameMaster())
{
@@ -391,7 +392,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
if (!receiver || (senderIsPlayer && !receiverIsPlayer && !receiver->isAcceptWhispers() && !receiver->IsInWhisperWhiteList(sender->GetGUID())))
if (!receiver || (lang != LANG_ADDON && !receiver->isAcceptWhispers() && receiver->GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS) && !receiver->IsInWhisperWhiteList(sender->GetGUID())))
{
SendPlayerNotFoundNotice(to);
return;
@@ -404,7 +405,6 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
// pussywizard: optimization
if (GetPlayer()->HasAura(1852) && !receiver->IsGameMaster())
{
ChatHandler(this).SendNotification(LANG_GM_SILENCE, GetPlayer()->GetName());
@@ -412,7 +412,9 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
// If player is a Gamemaster and doesn't accept whisper, we auto-whitelist every player that the Gamemaster is talking to
if (!senderIsPlayer && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID()))
// We also do that if a player is under the required level for whispers.
if (receiver->GetLevel() < sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ) ||
(HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS) && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID())))
sender->AddWhisperWhiteList(receiver->GetGUID());
GetPlayer()->Whisper(msg, Language(lang), receiver);
@@ -554,7 +556,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
break;
case CHAT_MSG_CHANNEL:
{
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ))
{
if (sender->GetLevel() < sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ))
{
+35 -3
View File
@@ -17,6 +17,7 @@
#include "AccountMgr.h"
#include "Chat.h"
#include "RBAC.h"
#include "CharacterCache.h"
#include "DBCStores.h"
#include "DatabaseEnv.h"
@@ -38,9 +39,9 @@ bool WorldSession::CanOpenMailBox(ObjectGuid guid)
{
if (guid == _player->GetGUID())
{
if (_player->GetSession()->GetSecurity() < SEC_MODERATOR)
if (!HasPermission(rbac::RBAC_PERM_COMMAND_MAILBOX))
{
LOG_ERROR("network.opcode", "{} attempt open mailbox in cheating way.", _player->GetName());
LOG_WARN("cheat", "{} attempted to open mailbox by using a cheat.", _player->GetName());
return false;
}
}
@@ -213,7 +214,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sCharacterCache->GetCharacterAccountIdByGuid(receiverGuid);
if (/*!accountBound*/ GetAccountId() != rc_account && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeamId() != rc_teamId && AccountMgr::IsPlayerAccount(GetSecurity()))
if (/*!accountBound*/ GetAccountId() != rc_account && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeamId() != rc_teamId && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM);
return;
@@ -286,6 +287,25 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
player->SendMailResult(0, MAIL_SEND, MAIL_OK);
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
if (items_count > 0)
{
for (uint8 i = 0; i < items_count; ++i)
{
Item* item = items[i];
LOG_GM(GetAccountId(), "GM {} (Account: {}) sent mail to {} (Account: {}) with item: {} (Entry: {} Count: {})",
player->GetName(), GetAccountId(), receiver, rc_account,
item->GetTemplate()->Name1, item->GetEntry(), item->GetCount());
}
}
if (money > 0)
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) sent mail to {} (Account: {}) with money: {}",
player->GetName(), GetAccountId(), receiver, rc_account, money);
}
}
player->ModifyMoney(-int32(reqmoney));
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost);
@@ -585,6 +605,12 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
it->SetState(ITEM_UNCHANGED); // need to set this state, otherwise item cannot be removed later, if neccessary
player->MoveItemToInventory(dest, it, true);
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) took mail item: {} (Entry: {} Count: {}) from mailbox",
player->GetName(), GetAccountId(), it->GetTemplate()->Name1, it->GetEntry(), count);
}
player->SaveInventoryAndGoldToDB(trans);
player->_SaveMail(trans);
CharacterDatabase.CommitTransaction(trans);
@@ -620,6 +646,12 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
return;
}
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
LOG_GM(GetAccountId(), "GM {} (Account: {}) took mail money: {} from mailbox",
player->GetName(), GetAccountId(), m->money);
}
m->money = 0;
m->state = MAIL_STATE_CHANGED;
player->m_mailsUpdated = true;
+11 -19
View File
@@ -17,6 +17,7 @@
#include "AccountMgr.h"
#include "BattlefieldMgr.h"
#include "RBAC.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "CharacterPackets.h"
@@ -283,8 +284,6 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
levelMax = STRONG_MAX_LEVEL;
uint32 team = _player->GetTeamId();
uint32 security = GetSecurity();
bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST);
uint32 displaycount = 0;
@@ -294,20 +293,13 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
for (auto const& target : sWhoListCacheMgr->GetWhoList())
{
if (AccountMgr::IsPlayerAccount(security))
{
// player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
if (target.GetTeamId() != team && !allowTwoSideWhoList)
{
continue;
}
// player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
if (target.GetTeamId() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
continue;
// player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST
if (target.GetSecurity() > AccountTypes(gmLevelInWhoList))
{
continue;
}
}
// player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST
if (!HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target.GetSecurity() > AccountTypes(gmLevelInWhoList))
continue;
// check if target is globally visible for player
if ((_player->GetGUID() != target.GetGuid() && !target.IsVisible()) &&
@@ -429,7 +421,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequ
if (ObjectGuid lguid = GetPlayer()->GetLootGUID())
DoLootRelease(lguid);
bool instantLogout = ((GetSecurity() >= 0 && uint32(GetSecurity()) >= sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT))
bool instantLogout = (HasPermission(rbac::RBAC_PERM_INSTANT_LOGOUT)
|| (GetPlayer()->HasPlayerFlag(PLAYER_FLAGS_RESTING) && !GetPlayer()->IsInCombat())) || GetPlayer()->IsInFlight();
bool preventAfkSanctuaryLogout = sWorld->getIntConfig(CONFIG_AFK_PREVENT_LOGOUT) == 1
@@ -1010,7 +1002,7 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data)
WorldPacket data(SMSG_INSPECT_TALENT, guid_size + 4 + talent_points);
data << player->GetPackGUID();
if (sWorld->getBoolConfig(CONFIG_TALENTS_INSPECTING) || _player->IsGameMaster())
if (sWorld->getBoolConfig(CONFIG_TALENTS_INSPECTING) || _player->CanBeGameMaster())
{
player->BuildPlayerTalentsInfoData(&data);
}
@@ -1081,7 +1073,7 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data)
LOG_DEBUG("network", "CMSG_WORLD_TELEPORT: Player = {}, Time = {}, map = {}, x = {}, y = {}, z = {}, o = {}", GetPlayer()->GetName(), time, mapid, PositionX, PositionY, PositionZ, Orientation);
if (AccountMgr::IsAdminAccount(GetSecurity()))
if (HasPermission(rbac::RBAC_PERM_OPCODE_WORLD_TELEPORT))
GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation);
else
ChatHandler(this).SendNotification(LANG_PERMISSION_DENIED);
@@ -1093,7 +1085,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data)
std::string charname;
recv_data >> charname;
if (!AccountMgr::IsAdminAccount(GetSecurity()))
if (!HasPermission(rbac::RBAC_PERM_OPCODE_WHOIS))
{
ChatHandler(this).SendNotification(LANG_PERMISSION_DENIED);
return;
+3 -2
View File
@@ -17,6 +17,7 @@
#include "AccountMgr.h"
#include "Language.h"
#include "RBAC.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -57,13 +58,13 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recv_data)
TeamId teamId = Player::TeamIdForRace(playerData->Race);
FriendsResult friendResult = FRIEND_NOT_FOUND;
if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND)|| AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
{
if (friendGuid)
{
if (friendGuid == GetPlayer()->GetGUID())
friendResult = FRIEND_SELF;
else if (GetPlayer()->GetTeamId() != teamId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && AccountMgr::IsPlayerAccount(GetSecurity()))
else if (GetPlayer()->GetTeamId() != teamId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
friendResult = FRIEND_ENEMY;
else if (GetPlayer()->GetSocial()->HasFriend(friendGuid))
friendResult = FRIEND_ALREADY;
+33 -1
View File
@@ -22,6 +22,7 @@
#include "ObjectAccessor.h"
#include "Opcodes.h"
#include "Player.h"
#include "RBAC.h"
#include "ScriptMgr.h"
#include "SocialMgr.h"
#include "Spell.h"
@@ -504,6 +505,35 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
trader->ModifyMoney(-int32(his_trade->GetMoney()));
trader->ModifyMoney(my_trade->GetMoney());
if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
if (myItems[i])
LOG_GM(GetAccountId(), "GM {} (Account: {}) traded item: {} (Entry: {} Count: {}) to {}",
_player->GetName(), GetAccountId(),
myItems[i]->GetTemplate()->Name1, myItems[i]->GetEntry(), myItems[i]->GetCount(),
trader->GetName());
}
if (my_trade->GetMoney() > 0)
LOG_GM(GetAccountId(), "GM {} (Account: {}) traded money: {} to {}",
_player->GetName(), GetAccountId(), my_trade->GetMoney(), trader->GetName());
}
if (trader->GetSession()->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE))
{
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
if (hisItems[i])
LOG_GM(trader->GetSession()->GetAccountId(), "GM {} (Account: {}) traded item: {} (Entry: {} Count: {}) to {}",
trader->GetName(), trader->GetSession()->GetAccountId(),
hisItems[i]->GetTemplate()->Name1, hisItems[i]->GetEntry(), hisItems[i]->GetCount(),
_player->GetName());
}
if (his_trade->GetMoney() > 0)
LOG_GM(trader->GetSession()->GetAccountId(), "GM {} (Account: {}) traded money: {} to {}",
trader->GetName(), trader->GetSession()->GetAccountId(), his_trade->GetMoney(), _player->GetName());
}
// log completed trade
LOG_INFO("entities.player.trade", "Trade: Account: {} (IP: {}), Player [{}] ({}) traded with Player [{}] ({}): gave {} copper, received {} copper, gave item(s) [{}], received item(s) [{}]",
GetAccountId(), GetRemoteAddress(), _player->GetName(), _player->GetGUID().GetCounter(),
@@ -671,7 +701,9 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeamId() != _player->GetTeamId())
if (pOther->GetTeamId() != _player->GetTeamId() &&
!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) &&
!GetPlayer()->GetSession()->HasPermission(rbac::RBAC_PERM_ALLOW_TWO_SIDE_TRADE))
{
info.Status = TRADE_STATUS_WRONG_FACTION;
SendTradeStatus(info);