From 2973083ddaeae5dbf1d78b460dc0060447dab202 Mon Sep 17 00:00:00 2001 From: Keleborn <22352763+Celandriel@users.noreply.github.com> Date: Fri, 22 May 2026 19:23:18 -0700 Subject: [PATCH] RBAC sync (#2355) ## Pull Request Description Implement RBAC Permission system in checks. Claude flagged the following PlayerbotMgr.cpp:751 <= SEC_PLAYER SecurityCheckAction.cpp:27 == SEC_PLAYER In these two cases a moderator level account has access to these commands. This was preserved in PR. The question is whether mods should maintain the override. ## Feature Evaluation - Describe the **minimum logic** required to achieve the intended behavior. - Describe the **processing cost** when this logic executes across many bots. ## How to Test the Changes ## Impact Assessment - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [x] No - - [ ] Yes (**explain why**) - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## AI Assistance Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers --- src/Ai/Base/Actions/BattleGroundTactics.cpp | 2 +- src/Ai/Base/Actions/ChangeStrategyAction.cpp | 2 +- src/Ai/Base/Actions/SecurityCheckAction.cpp | 2 +- src/Bot/PlayerbotAI.cpp | 7 ++++--- src/Bot/PlayerbotMgr.cpp | 20 ++++++++++---------- src/Mgr/Security/PlayerbotSecurity.cpp | 7 +++---- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Ai/Base/Actions/BattleGroundTactics.cpp b/src/Ai/Base/Actions/BattleGroundTactics.cpp index efb2fce7f..238a2291e 100644 --- a/src/Ai/Base/Actions/BattleGroundTactics.cpp +++ b/src/Ai/Base/Actions/BattleGroundTactics.cpp @@ -1299,7 +1299,7 @@ std::string const BGTactics::HandleConsoleCommandPrivate(WorldSession* session, Player* player = session->GetPlayer(); if (!player) return "Error - session player not found"; - if (player->GetSession()->GetSecurity() < SEC_GAMEMASTER) + if (!player->CanBeGameMaster()) return "Command can only be used by a GM"; Battleground* bg = player->GetBattleground(); if (!bg) diff --git a/src/Ai/Base/Actions/ChangeStrategyAction.cpp b/src/Ai/Base/Actions/ChangeStrategyAction.cpp index e81096b2a..9c8c92552 100644 --- a/src/Ai/Base/Actions/ChangeStrategyAction.cpp +++ b/src/Ai/Base/Actions/ChangeStrategyAction.cpp @@ -49,7 +49,7 @@ bool ChangeNonCombatStrategyAction::Execute(Event event) uint32 account = bot->GetSession()->GetAccountId(); if (sPlayerbotAIConfig.IsInRandomAccountList(account) && botAI->GetMaster() && - botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER) + !botAI->GetMaster()->CanBeGameMaster()) { if (text.find("loot") != std::string::npos || text.find("gather") != std::string::npos) { diff --git a/src/Ai/Base/Actions/SecurityCheckAction.cpp b/src/Ai/Base/Actions/SecurityCheckAction.cpp index 3d1b4c601..d4daa367a 100644 --- a/src/Ai/Base/Actions/SecurityCheckAction.cpp +++ b/src/Ai/Base/Actions/SecurityCheckAction.cpp @@ -12,7 +12,7 @@ bool SecurityCheckAction::isUseful() { return RandomPlayerbotMgr::instance().IsRandomBot(bot) && botAI->GetMaster() - && botAI->GetMaster()->GetSession()->GetSecurity() < SEC_GAMEMASTER + && !botAI->GetMaster()->CanBeGameMaster() && !GET_PLAYERBOT_AI(botAI->GetMaster()); } diff --git a/src/Bot/PlayerbotAI.cpp b/src/Bot/PlayerbotAI.cpp index 958a5799a..a9eb598e5 100644 --- a/src/Bot/PlayerbotAI.cpp +++ b/src/Bot/PlayerbotAI.cpp @@ -43,6 +43,7 @@ #include "PlayerbotGuildMgr.h" #include "Playerbots.h" #include "PositionValue.h" +#include "RBAC.h" #include "RandomPlayerbotMgr.h" #include "SayAction.h" #include "ScriptMgr.h" @@ -507,7 +508,7 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal logout = true; if (bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || bot->HasUnitState(UNIT_STATE_IN_FLIGHT) || - botWorldSessionPtr->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)) + botWorldSessionPtr->HasPermission(rbac::RBAC_PERM_INSTANT_LOGOUT)) { logout = true; } @@ -515,7 +516,7 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal if (master && (master->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || master->HasUnitState(UNIT_STATE_IN_FLIGHT) || (master->GetSession() && - master->GetSession()->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)))) + master->GetSession()->HasPermission(rbac::RBAC_PERM_INSTANT_LOGOUT)))) { logout = true; } @@ -3003,7 +3004,7 @@ bool PlayerbotAI::IsTellAllowed(PlayerbotSecurityLevel securityLevel) return false; if (sPlayerbotAIConfig.whisperDistance && !bot->GetGroup() && sRandomPlayerbotMgr.IsRandomBot(bot) && - master->GetSession()->GetSecurity() < SEC_GAMEMASTER && + !master->CanBeGameMaster() && (bot->GetMapId() != master->GetMapId() || ServerFacade::instance().GetDistance2d(bot, master) > sPlayerbotAIConfig.whisperDistance)) return false; diff --git a/src/Bot/PlayerbotMgr.cpp b/src/Bot/PlayerbotMgr.cpp index 9d3d61ca3..7a8c311ce 100644 --- a/src/Bot/PlayerbotMgr.cpp +++ b/src/Bot/PlayerbotMgr.cpp @@ -919,7 +919,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!strcmp(cmd, "initself")) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { // OnBotLogin(master); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_EPIC); @@ -938,7 +938,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg { if (!strcmp(cmd, "initself=uncommon")) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { // OnBotLogin(master); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_UNCOMMON); @@ -954,7 +954,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg } if (!strcmp(cmd, "initself=rare")) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { // OnBotLogin(master); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_RARE); @@ -970,7 +970,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg } if (!strcmp(cmd, "initself=epic")) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { // OnBotLogin(master); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_EPIC); @@ -986,7 +986,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg } if (!strcmp(cmd, "initself=legendary")) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { // OnBotLogin(master); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_LEGENDARY); @@ -1003,7 +1003,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg int32 gs; if (sscanf(cmd, "initself=%d", &gs) != -1) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { // OnBotLogin(master); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_LEGENDARY, gs); @@ -1027,7 +1027,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!strcmp(cmd, "reload")) { - if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (master->CanBeGameMaster()) { sPlayerbotAIConfig.Initialize(); messages.push_back("Config reloaded."); @@ -1059,7 +1059,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg } else if (sPlayerbotAIConfig.selfBotLevel == 0) messages.push_back("Self-bot is disabled"); - else if (sPlayerbotAIConfig.selfBotLevel == 1 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) + else if (sPlayerbotAIConfig.selfBotLevel == 1 && !master->CanBeGameMaster()) messages.push_back("You do not have permission to enable player botAI"); else { @@ -1079,7 +1079,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!strcmp(cmd, "addclass")) { - if (sPlayerbotAIConfig.addClassCommand == 0 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) + if (sPlayerbotAIConfig.addClassCommand == 0 && !master->CanBeGameMaster()) { messages.push_back("You do not have permission to create bot by addclass command"); return messages; @@ -1304,7 +1304,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg else if (master && member != master->GetGUID()) { out << ProcessBotCommand(cmdStr, member, master->GetGUID(), - master->GetSession()->GetSecurity() >= SEC_GAMEMASTER, + master->CanBeGameMaster(), master->GetSession()->GetAccountId(), master->GetGuildId()); } else if (!master) diff --git a/src/Mgr/Security/PlayerbotSecurity.cpp b/src/Mgr/Security/PlayerbotSecurity.cpp index 4a3bd3655..f2a2863ac 100644 --- a/src/Mgr/Security/PlayerbotSecurity.cpp +++ b/src/Mgr/Security/PlayerbotSecurity.cpp @@ -27,7 +27,7 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea } // GMs always have full access - if (from->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (from->CanBeGameMaster()) return PLAYERBOT_SECURITY_ALLOW_ALL; PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); @@ -188,9 +188,8 @@ bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent, Player* master = botAI->GetMaster(); if (master && botAI->IsOpposing(master)) - if (WorldSession* session = master->GetSession()) - if (session->GetSecurity() < SEC_GAMEMASTER) - return false; + if (master->GetSession() && !master->CanBeGameMaster()) + return false; std::ostringstream out;