aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CreatureAIImpl.h30
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp217
-rw-r--r--src/server/game/Accounts/AccountMgr.h27
-rw-r--r--src/server/game/Chat/Chat.cpp25
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp11
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp11
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp2
-rw-r--r--src/server/game/Miscellaneous/Language.h35
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Server/WorldSession.cpp29
-rw-r--r--src/server/game/Server/WorldSession.h6
-rw-r--r--src/server/game/Server/WorldSocket.cpp1
-rw-r--r--src/server/game/World/World.cpp7
-rw-r--r--src/server/scripts/Commands/CMakeLists.txt1
-rw-r--r--src/server/scripts/Commands/cs_account.cpp34
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp16
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.h10
-rw-r--r--src/server/worldserver/worldserver.conf.dist20
19 files changed, 399 insertions, 87 deletions
diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h
index 7121a031ec2..6c5cb5622b3 100644
--- a/src/server/game/AI/CreatureAIImpl.h
+++ b/src/server/game/AI/CreatureAIImpl.h
@@ -314,10 +314,10 @@ const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, c
class EventMap
{
/**
- * Internal storage type.
+ * Internal storage type.
* Key: Time as uint32 when the event should occur.
- * Value: The event data as uint32.
- *
+ * Value: The event data as uint32.
+ *
* Structure of event data:
* - Bit 0 - 15: Event Id.
* - Bit 16 - 23: Group
@@ -454,7 +454,7 @@ class EventMap
{
if (Empty())
return;
-
+
uint32 eventId = _eventMap.begin()->second;
_eventMap.erase(_eventMap.begin());
ScheduleEvent(eventId, time);
@@ -480,7 +480,7 @@ class EventMap
while (!Empty())
{
EventStore::iterator itr = _eventMap.begin();
-
+
if (itr->first > _time)
return 0;
else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase))
@@ -492,7 +492,7 @@ class EventMap
return eventId;
}
}
-
+
return 0;
}
@@ -506,7 +506,7 @@ class EventMap
while (!Empty())
{
EventStore::iterator itr = _eventMap.begin();
-
+
if (itr->first > _time)
return 0;
else if (_phase && (itr->second & 0xFF000000) && !(itr->second & (_phase << 24)))
@@ -514,7 +514,7 @@ class EventMap
else
return (itr->second & 0x0000FFFF);
}
-
+
return 0;
}
@@ -538,7 +538,7 @@ class EventMap
{
if (!group || group > 8 || Empty())
return;
-
+
EventStore delayed;
for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
@@ -551,7 +551,7 @@ class EventMap
else
++itr;
}
-
+
_eventMap.insert(delayed.begin(), delayed.end());
}
@@ -578,7 +578,7 @@ class EventMap
* @name CancelEventGroup
* @brief Cancel events belonging to specified group.
* @param group Group to cancel.
- */
+ */
void CancelEventGroup(uint32 group)
{
if (!group || group > 8 || Empty())
@@ -610,7 +610,7 @@ class EventMap
return 0;
}
-
+
/**
* @name GetNextEventTime
* @return Time of next event.
@@ -636,14 +636,14 @@ class EventMap
* @name _time
* @brief Internal timer.
*
- * This does not represent the real date/time value.
+ * This does not represent the real date/time value.
* It's more like a stopwatch: It can run, it can be stopped,
* it can be resetted and so on. Events occur when this timer
* has reached their time value. Its value is changed in the
* Update method.
*/
uint32 _time;
-
+
/**
* @name _phase
* @brief Phase mask of the event map.
@@ -653,7 +653,7 @@ class EventMap
* AddPhase. RemovePhase deactives a phase.
*/
uint8 _phase;
-
+
/**
* @name _eventMap
* @brief Internal event storage map. Contains the scheduled events.
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 3c3eded1f68..ce382342de8 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -17,6 +17,7 @@
*/
#include "AccountMgr.h"
+#include "Config.h"
#include "DatabaseEnv.h"
#include "ObjectAccessor.h"
#include "Player.h"
@@ -26,6 +27,7 @@
AccountMgr::AccountMgr()
{
+
}
AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password)
@@ -44,12 +46,22 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
stmt->setString(0, username);
stmt->setString(1, CalculateShaPassHash(username, password));
- LoginDatabase.Execute(stmt);
+ LoginDatabase.DirectExecute(stmt); // Enforce saving, otherwise AddGroup can fail
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT);
LoginDatabase.Execute(stmt);
+ // Add default rbac groups for that security level
+ RBACData* rbac = new RBACData(GetId(username), username, -1);
+ // No need to Load From DB, as it's new data
+
+ RBACGroupContainer const& groupsToAdd = _defaultGroups[0]; // 0: Default sec level
+ for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it)
+ rbac->AddGroup(*it, -1);
+
+ delete rbac;
+
return AOR_OK; // everything's fine
}
@@ -303,3 +315,206 @@ bool AccountMgr::IsConsoleAccount(uint32 gmlevel)
{
return gmlevel == SEC_CONSOLE;
}
+
+void AccountMgr::LoadRBAC()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 count1 = 0;
+ uint32 count2 = 0;
+ uint32 count3 = 0;
+
+ QueryResult result = LoginDatabase.Query("SELECT id, name FROM rbac_permissions");
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account permission definitions. DB table `rbac_permissions` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* field = result->Fetch();
+ uint32 id = field[0].GetUInt32();
+ _permissions[id] = new RBACPermission(id, field[1].GetString());
+ ++count1;
+ }
+ while (result->NextRow());
+
+ result = LoginDatabase.Query("SELECT id, name FROM rbac_roles");
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account role definitions. DB table `rbac_roles` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* field = result->Fetch();
+ uint32 id = field[0].GetUInt32();
+ _roles[id] = new RBACRole(id, field[1].GetString());
+ ++count2;
+ }
+ while (result->NextRow());
+
+ result = LoginDatabase.Query("SELECT roleId, permissionId FROM rbac_role_permissions");
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account role-permission definitions. DB table `rbac_role_permissions` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* field = result->Fetch();
+ uint32 id = field[0].GetUInt32();
+ RBACRole* role = _roles[id];
+ role->GrantPermission(field[1].GetUInt32());
+ }
+ while (result->NextRow());
+
+ result = LoginDatabase.Query("SELECT id, name FROM rbac_groups");
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account group definitions. DB table `rbac_groups` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* field = result->Fetch();
+ uint32 id = field[0].GetUInt32();
+ _groups[id] = new RBACGroup(id, field[1].GetString());
+ ++count3;
+ }
+ while (result->NextRow());
+
+ result = LoginDatabase.Query("SELECT groupId, roleId FROM rbac_group_roles");
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account group-role definitions. DB table `rbac_group_roles` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* field = result->Fetch();
+ uint32 id = field[0].GetUInt32();
+ RBACGroup* group = _groups[id];
+ group->GrantRole(field[1].GetUInt32());
+ }
+ while (result->NextRow());
+
+ result = LoginDatabase.Query("SELECT secId, groupId FROM rbac_security_level_groups ORDER by secId ASC");
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account default groups for security levels definitions. DB table `rbac_security_level_groups` is empty.");
+ return;
+ }
+
+ uint8 lastSecId = 255;
+ RBACGroupContainer* groups = NULL;
+ do
+ {
+ Field* field = result->Fetch();
+ uint8 secId = field[0].GetUInt8();
+
+ if (lastSecId != secId)
+ groups = &_defaultGroups[secId];
+
+ groups->insert(field[1].GetUInt32());
+ }
+ while (result->NextRow());
+
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u permission definitions, %u role definitions and %u group definitions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId)
+{
+ int32 serverRealmId = realmId != -1 ? realmId : ConfigMgr::GetIntDefault("RealmID", 0);
+ bool needDelete = false;
+ if (!rbac)
+ {
+ needDelete = true;
+ rbac = new RBACData(accountId, "", serverRealmId);
+ rbac->LoadFromDB();
+ }
+
+ // Get max security level and realm (checking current realm and -1)
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID);
+ stmt->setUInt32(0, accountId);
+ stmt->setInt32(1, serverRealmId);
+ PreparedQueryResult result = LoginDatabase.Query(stmt);
+ if (result)
+ {
+ do
+ {
+ Field* field = result->Fetch();
+ uint8 secLevel = field[0].GetUInt8();
+ int32 realmId = field[1].GetUInt32();
+
+ RBACGroupContainer const& groupsToRemove = _defaultGroups[secLevel];
+ for (RBACGroupContainer::const_iterator it = groupsToRemove.begin(); it != groupsToRemove.end(); ++it)
+ rbac->RemoveGroup(*it, realmId);
+ }
+ while (result->NextRow());
+ }
+
+ // Add new groups depending on the new security Level
+ RBACGroupContainer const& groupsToAdd = _defaultGroups[securityLevel];
+ for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it)
+ rbac->AddGroup(*it, realmId);
+
+ if (needDelete)
+ delete rbac;
+
+ // Delete old security level from DB
+ if (realmId == -1)
+ {
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS);
+ stmt->setUInt32(0, accountId);
+ LoginDatabase.Execute(stmt);
+ }
+ else
+ {
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM);
+ stmt->setUInt32(0, accountId);
+ stmt->setUInt32(1, realmId);
+ LoginDatabase.Execute(stmt);
+ }
+
+ // Add new security level
+ if (securityLevel)
+ {
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS);
+ stmt->setUInt32(0, accountId);
+ stmt->setUInt8(1, securityLevel);
+ stmt->setInt32(2, realmId);
+ LoginDatabase.Execute(stmt);
+ }
+}
+
+RBACGroup const* AccountMgr::GetRBACGroup(uint32 group) const
+{
+ RBACGroupsContainer::const_iterator it = _groups.find(group);
+ if (it != _groups.end())
+ return it->second;
+
+ return NULL;
+}
+
+RBACRole const* AccountMgr::GetRBACRole(uint32 role) const
+{
+ RBACRolesContainer::const_iterator it = _roles.find(role);
+ if (it != _roles.end())
+ return it->second;
+
+ return NULL;
+}
+
+RBACPermission const* AccountMgr::GetRBACPermission(uint32 permission) const
+{
+ RBACPermissionsContainer::const_iterator it = _permissions.find(permission);
+ if (it != _permissions.end())
+ return it->second;
+
+ return NULL;
+}
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index c8de5688e73..90c533ca5fa 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -19,8 +19,7 @@
#ifndef _ACCMGR_H
#define _ACCMGR_H
-#include "Define.h"
-#include <string>
+#include "RBAC.h"
#include <ace/Singleton.h>
enum AccountOpResult
@@ -35,6 +34,11 @@ enum AccountOpResult
#define MAX_ACCOUNT_STR 16
+typedef std::map<uint32, RBACPermission*> RBACPermissionsContainer;
+typedef std::map<uint32, RBACRole*> RBACRolesContainer;
+typedef std::map<uint32, RBACGroup*> RBACGroupsContainer;
+typedef std::map<uint32, RBACGroupContainer> RBACDefaultSecurityGroupContainer;
+
class AccountMgr
{
friend class ACE_Singleton<AccountMgr, ACE_Null_Mutex>;
@@ -43,7 +47,7 @@ class AccountMgr
AccountMgr();
public:
- static AccountOpResult CreateAccount(std::string username, std::string password);
+ AccountOpResult CreateAccount(std::string username, std::string password);
static AccountOpResult DeleteAccount(uint32 accountId);
static AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
static AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
@@ -62,6 +66,23 @@ class AccountMgr
static bool IsGMAccount(uint32 gmlevel);
static bool IsAdminAccount(uint32 gmlevel);
static bool IsConsoleAccount(uint32 gmlevel);
+
+ void UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId);
+
+ void LoadRBAC();
+ RBACGroup const* GetRBACGroup(uint32 group) const;
+ RBACRole const* GetRBACRole(uint32 role) const;
+ RBACPermission const* GetRBACPermission(uint32 permission) const;
+
+ RBACGroupsContainer const& GetRBACGroupList() const { return _groups; }
+ RBACRolesContainer const& GetRBACRoleList() const { return _roles; }
+ RBACPermissionsContainer const& GetRBACPermissionList() const { return _permissions; }
+
+ private:
+ RBACPermissionsContainer _permissions;
+ RBACRolesContainer _roles;
+ RBACGroupsContainer _groups;
+ RBACDefaultSecurityGroupContainer _defaultGroups;
};
#define sAccountMgr ACE_Singleton<AccountMgr, ACE_Null_Mutex>::instance()
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 0bf7c8591e3..b8f80fb36ac 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -122,8 +122,27 @@ const char *ChatHandler::GetTrinityString(int32 entry) const
bool ChatHandler::isAvailable(ChatCommand const& cmd) const
{
- // check security level only for simple command (without child commands)
- return m_session->GetSecurity() >= AccountTypes(cmd.SecurityLevel);
+ uint32 permission = 0;
+
+ ///@Workaround:: Fast adaptation to RBAC system till all commands are moved to permissions
+ switch (AccountTypes(cmd.SecurityLevel))
+ {
+ case SEC_ADMINISTRATOR:
+ permission = RBAC_PERM_ADMINISTRATOR_COMMANDS;
+ break;
+ case SEC_GAMEMASTER:
+ permission = RBAC_PERM_GAMEMASTER_COMMANDS;
+ break;
+ case SEC_MODERATOR:
+ permission = RBAC_PERM_MODERATOR_COMMANDS;
+ break;
+ case SEC_PLAYER:
+ default:
+ permission = RBAC_PERM_PLAYER_COMMANDS;
+ break;
+ }
+
+ return m_session->HasPermission(permission);
}
bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong)
@@ -431,7 +450,7 @@ bool ChatHandler::ParseCommands(char const* text)
std::string fullcmd = text;
- if (m_session && AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !sWorld->getBoolConfig(CONFIG_ALLOW_PLAYER_COMMANDS))
+ if (m_session && !m_session->HasPermission(RBAC_PERM_PLAYER_COMMANDS))
return false;
/// chat case (.command or !command format)
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index d9d4a897eed..e18a103e21c 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -379,6 +379,7 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */)
uint8 expansion = player->GetSession()->Expansion();
LfgDungeonSet const& dungeons = GetDungeonsByRandom(0);
LfgLockMap lock;
+ bool denyJoin = !player->GetSession()->HasPermission(RBAC_PERM_JOIN_DUNGEON_FINDER);
for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it)
{
@@ -387,7 +388,9 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */)
continue;
uint32 lockData = 0;
- if (dungeon->expansion > expansion)
+ if (denyJoin)
+ lockData = LFG_LOCKSTATUS_RAID_LOCKED;
+ else if (dungeon->expansion > expansion)
lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
@@ -469,7 +472,9 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
}
// Check player or group member restrictions
- if (player->InBattleground() || player->InArena() || player->InBattlegroundQueue())
+ if (!player->GetSession()->HasPermission(RBAC_PERM_JOIN_DUNGEON_FINDER))
+ joinData.result = LFG_JOIN_NOT_MEET_REQS;
+ else if (player->InBattleground() || player->InArena() || player->InBattlegroundQueue())
joinData.result = LFG_JOIN_USING_BG_SYSTEM;
else if (player->HasAura(LFG_SPELL_DUNGEON_DESERTER))
joinData.result = LFG_JOIN_DESERTER;
@@ -488,6 +493,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
{
if (Player* plrg = itr->getSource())
{
+ if (!plrg->GetSession()->HasPermission(RBAC_PERM_JOIN_DUNGEON_FINDER))
+ joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS;
if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER))
joinData.result = LFG_JOIN_PARTY_DESERTER;
else if (plrg->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index da7980647bb..07c4281f86f 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -343,7 +343,7 @@ class LFGMgr
uint32 GetOptions(); // cs_lfg
/// Sets new lfg options
void SetOptions(uint32 options);
- /// Checks if given lfg option is enabled
+ /// Checks if given lfg option is enabled
bool isOptionEnabled(uint32 option);
/// Clears queue - Only for internal testing
void Clean();
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a4356f55340..dc98facc5ab 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -21757,12 +21757,21 @@ void Player::LeaveBattleground(bool teleportToEntryPoint)
}
}
-bool Player::CanJoinToBattleground(Battleground const* /*bg*/) const
+bool Player::CanJoinToBattleground(Battleground const* bg) const
{
// check Deserter debuff
if (HasAura(26013))
return false;
+ if (bg->isArena() && !GetSession()->HasPermission(RBAC_PERM_JOIN_ARENAS))
+ return false;
+
+ if (bg->IsRandom() && !GetSession()->HasPermission(RBAC_PERM_JOIN_RANDOM_BG))
+ return false;
+
+ if (!GetSession()->HasPermission(RBAC_PERM_JOIN_NORMAL_BG))
+ return false;
+
return true;
}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index aa4c9f35085..6272f42ec8c 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -396,7 +396,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
//instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf
if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight() ||
- GetSecurity() >= AccountTypes(sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)))
+ HasPermission(RBAC_PERM_INSTANT_LOGOUT))
{
WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4);
data << uint8(0);
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index e13cc86747c..5868b60b722 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -86,7 +86,40 @@ enum TrinityStrings
LANG_CONNECTED_PLAYERS = 60,
LANG_ACCOUNT_ADDON = 61,
LANG_IMPROPER_VALUE = 62,
- // Room for more level 0 63-99 not used
+ LANG_RBAC_WRONG_PARAMETER_ID = 63,
+ LANG_RBAC_WRONG_PARAMETER_REALM = 64,
+ LANG_RBAC_GROUP_IN_LIST = 65,
+ LANG_RBAC_GROUP_NOT_IN_LIST = 66,
+ LANG_RBAC_GROUP_ADDED = 67,
+ LANG_RBAC_GROUP_REMOVED = 68,
+ LANG_RBAC_GROUP_LIST_HEADER = 69,
+ LANG_RBAC_LIST_EMPTY = 70,
+ LANG_RBAC_LIST_ELEMENT = 71,
+ LANG_RBAC_ROLE_GRANTED_IN_LIST = 72,
+ LANG_RBAC_ROLE_GRANTED_IN_DENIED_LIST = 73,
+ LANG_RBAC_ROLE_GRANTED = 74,
+ LANG_RBAC_ROLE_DENIED_IN_LIST = 75,
+ LANG_RBAC_ROLE_DENIED_IN_GRANTED_LIST = 76,
+ LANG_RBAC_ROLE_DENIED = 77,
+ LANG_RBAC_ROLE_REVOKED = 78,
+ LANG_RBAC_ROLE_REVOKED_NOT_IN_LIST = 79,
+ LANG_RBAC_ROLE_LIST_HEADER_GRANTED = 80,
+ LANG_RBAC_ROLE_LIST_HEADER_DENIED = 81,
+ LANG_RBAC_PERM_GRANTED_IN_LIST = 82,
+ LANG_RBAC_PERM_GRANTED_IN_DENIED_LIST = 83,
+ LANG_RBAC_PERM_GRANTED = 84,
+ LANG_RBAC_PERM_DENIED_IN_LIST = 85,
+ LANG_RBAC_PERM_DENIED_IN_GRANTED_LIST = 86,
+ LANG_RBAC_PERM_DENIED = 87,
+ LANG_RBAC_PERM_REVOKED = 88,
+ LANG_RBAC_PERM_REVOKED_NOT_IN_LIST = 89,
+ LANG_RBAC_PERM_LIST_HEADER_GRANTED = 90,
+ LANG_RBAC_PERM_LIST_HEADER_DENIED = 91,
+ LANG_RBAC_PERM_LIST_GLOBAL = 92,
+ LANG_RBAC_LIST_GROUPS_HEADER = 93,
+ LANG_RBAC_LIST_ROLES_HEADER = 94,
+ LANG_RBAC_LIST_PERMISSIONS_HEADER = 95,
+ // Room for more level 0 96-99 not used
// level 1 chat
LANG_GLOBAL_NOTIFY = 100,
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index efd45188d42..afc153a5000 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -70,6 +70,7 @@ void AddSC_mmaps_commandscript();
void AddSC_modify_commandscript();
void AddSC_npc_commandscript();
void AddSC_quest_commandscript();
+void AddSC_rbac_commandscript();
void AddSC_reload_commandscript();
void AddSC_reset_commandscript();
void AddSC_server_commandscript();
@@ -700,6 +701,7 @@ void AddCommandScripts()
AddSC_modify_commandscript();
AddSC_npc_commandscript();
AddSC_quest_commandscript();
+ AddSC_rbac_commandscript();
AddSC_reload_commandscript();
AddSC_reset_commandscript();
AddSC_server_commandscript();
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 6c689319bc7..522dc95105d 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -21,6 +21,7 @@
*/
#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it
+#include "Config.h"
#include "Common.h"
#include "DatabaseEnv.h"
#include "Log.h"
@@ -115,7 +116,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
m_TutorialsChanged(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
- timeLastWhoCommand(0)
+ timeLastWhoCommand(0),
+ _RBACData(NULL)
{
if (sock)
{
@@ -143,8 +145,8 @@ WorldSession::~WorldSession()
m_Socket = NULL;
}
- if (_warden)
- delete _warden;
+ delete _warden;
+ delete _RBACData;
///- empty incoming packet queue
WorldPacket* packet = NULL;
@@ -1200,3 +1202,24 @@ void WorldSession::InitWarden(BigNumber* k, std::string const& os)
// _warden->Init(this, k);
}
}
+
+void WorldSession::LoadPermissions()
+{
+ uint32 id = GetAccountId();
+ std::string name;
+ int32 realmId = ConfigMgr::GetIntDefault("RealmID", 0);
+ AccountMgr::GetName(id, name);
+
+ _RBACData = new RBACData(id, name, realmId);
+ _RBACData->LoadFromDB();
+}
+
+RBACData* WorldSession::GetRBACData()
+{
+ return _RBACData;
+}
+
+bool WorldSession::HasPermission(uint32 permission)
+{
+ return _RBACData->HasPermission(permission);
+}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 11bb7a36f5a..d6877b8a18a 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -24,6 +24,7 @@
#define __WORLDSESSION_H
#include "Common.h"
+#include "AccountMgr.h"
#include "SharedDefines.h"
#include "AddonMgr.h"
#include "DatabaseEnv.h"
@@ -216,6 +217,10 @@ class WorldSession
void SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos = 0);
void SendClientCacheVersion(uint32 version);
+ RBACData* GetRBACData();
+ bool HasPermission(uint32 permissionId);
+ void LoadPermissions();
+
AccountTypes GetSecurity() const { return _security; }
uint32 GetAccountId() const { return _accountId; }
Player* GetPlayer() const { return _player; }
@@ -954,6 +959,7 @@ class WorldSession
bool isRecruiter;
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
time_t timeLastWhoCommand;
+ RBACData* _RBACData;
};
#endif
/// @}
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index c80d25be139..c77cad70186 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -953,6 +953,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
m_Session->LoadGlobalAccountData();
m_Session->LoadTutorialsData();
m_Session->ReadAddonsInfo(recvPacket);
+ m_Session->LoadPermissions();
// Initialize Warden system only if it is enabled by config
if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED))
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index f28b9548e5f..d02ba402c53 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -267,7 +267,7 @@ void World::AddSession_(WorldSession* s)
if (decrease_session)
--Sessions;
- if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !HasRecentlyDisconnected(s))
+ if (pLimit > 0 && Sessions >= pLimit && !s->HasPermission(RBAC_PERM_SKIP_QUEUE) && !HasRecentlyDisconnected(s))
{
AddQueuedPlayer(s);
UpdateMaxSessionCounters();
@@ -585,7 +585,6 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_TICKET_LEVEL_REQ] = ConfigMgr::GetIntDefault("LevelReq.Ticket", 1);
m_int_configs[CONFIG_AUCTION_LEVEL_REQ] = ConfigMgr::GetIntDefault("LevelReq.Auction", 1);
m_int_configs[CONFIG_MAIL_LEVEL_REQ] = ConfigMgr::GetIntDefault("LevelReq.Mail", 1);
- m_bool_configs[CONFIG_ALLOW_PLAYER_COMMANDS] = ConfigMgr::GetBoolDefault("AllowPlayerCommands", 1);
m_bool_configs[CONFIG_PRESERVE_CUSTOM_CHANNELS] = ConfigMgr::GetBoolDefault("PreserveCustomChannels", false);
m_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION] = ConfigMgr::GetIntDefault("PreserveCustomChannelDuration", 14);
m_bool_configs[CONFIG_GRID_UNLOAD] = ConfigMgr::GetBoolDefault("GridUnload", true);
@@ -1059,8 +1058,6 @@ void World::LoadConfigSettings(bool reload)
sLog->outError(LOG_FILTER_SERVER_LOADING, "ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
}
- m_int_configs[CONFIG_INSTANT_LOGOUT] = ConfigMgr::GetIntDefault("InstantLogout", SEC_MODERATOR);
-
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = ConfigMgr::GetIntDefault("Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS);
if (m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] > GUILD_EVENTLOG_MAX_RECORDS)
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = GUILD_EVENTLOG_MAX_RECORDS;
@@ -1348,6 +1345,8 @@ void World::SetInitialWorldSettings()
sObjectMgr->SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Localization strings loaded in %u ms", GetMSTimeDiffToNow(oldMSTime));
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Account Roles and Permissions...");
+ sAccountMgr->LoadRBAC();
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Page Texts...");
sObjectMgr->LoadPageTexts();
diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt
index 7b9e2444952..83e97b2c80d 100644
--- a/src/server/scripts/Commands/CMakeLists.txt
+++ b/src/server/scripts/Commands/CMakeLists.txt
@@ -35,6 +35,7 @@ set(scripts_STAT_SRCS
Commands/cs_modify.cpp
Commands/cs_npc.cpp
Commands/cs_quest.cpp
+ Commands/cs_rbac.cpp
Commands/cs_reload.cpp
Commands/cs_reset.cpp
Commands/cs_tele.cpp
diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp
index 3a20a03bb4a..4dc44bbfc58 100644
--- a/src/server/scripts/Commands/cs_account.cpp
+++ b/src/server/scripts/Commands/cs_account.cpp
@@ -106,7 +106,7 @@ public:
if (!accountName || !password)
return false;
- AccountOpResult result = AccountMgr::CreateAccount(std::string(accountName), std::string(password));
+ AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password));
switch (result)
{
case AOR_OK:
@@ -503,36 +503,8 @@ public:
return false;
}
- // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID
- PreparedStatement* stmt;
-
- if (gmRealmID == -1)
- {
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS);
-
- stmt->setUInt32(0, targetAccountId);
- }
- else
- {
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM);
-
- stmt->setUInt32(0, targetAccountId);
- stmt->setUInt32(1, realmID);
- }
-
- LoginDatabase.Execute(stmt);
-
- if (gm != 0)
- {
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS);
-
- stmt->setUInt32(0, targetAccountId);
- stmt->setUInt8(1, uint8(gm));
- stmt->setInt32(2, gmRealmID);
-
- LoginDatabase.Execute(stmt);
- }
-
+ RBACData* rbac = isAccountNameGiven ? NULL : handler->getSelectedPlayer()->GetSession()->GetRBACData();
+ sAccountMgr->UpdateAccountAccess(rbac, targetAccountId, uint8(gm), gmRealmID);
handler->PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm);
return true;
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index 227680b2d6b..210e2b3ac60 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -55,7 +55,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_SUM_REALM_CHARACTERS, "SELECT SUM(numchars) FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, joindate) VALUES(?, ?, NOW())", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, joindate) VALUES(?, ?, NOW())", CONNECTION_SYNCH);
PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
@@ -87,4 +87,18 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
+
+ PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH);
+
+ PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_GROUPS, "SELECT groupId FROM rbac_account_groups WHERE accountId = ? AND (realmId = ? OR realmId = -1) GROUP BY groupId", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_GROUP, "INSERT INTO rbac_account_groups (accountId, groupId, realmId) VALUES (?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_DEL_RBAC_ACCOUNT_GROUP, "DELETE FROM rbac_account_groups WHERE accountId = ? AND groupId = ? AND (realmId = ? OR realmId = -1)", CONNECTION_ASYNC);
+
+ PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_ROLES, "SELECT roleId, granted FROM rbac_account_roles WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY roleId, realmId", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_ROLE, "INSERT INTO rbac_account_roles (accountId, roleId, granted, realmId) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE granted = VALUES(granted)", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_DEL_RBAC_ACCOUNT_ROLE, "DELETE FROM rbac_account_roles WHERE accountId = ? AND roleId = ? AND (realmId = ? OR realmId = -1)", CONNECTION_ASYNC);
+
+ PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION, "INSERT INTO rbac_account_permissions (accountId, permissionId, granted, realmId) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE granted = VALUES(granted)", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION, "DELETE FROM rbac_account_permissions WHERE accountId = ? AND permissionId = ? AND (realmId = ? OR realmId = -1)", CONNECTION_ASYNC);
}
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h
index 798016d553d..211706b26b8 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.h
+++ b/src/server/shared/Database/Implementation/LoginDatabase.h
@@ -108,6 +108,16 @@ enum LoginDatabaseStatements
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
LOGIN_DEL_ACCOUNT,
+ LOGIN_SEL_ACCOUNT_ACCESS_BY_ID,
+ LOGIN_SEL_RBAC_ACCOUNT_GROUPS,
+ LOGIN_INS_RBAC_ACCOUNT_GROUP,
+ LOGIN_DEL_RBAC_ACCOUNT_GROUP,
+ LOGIN_SEL_RBAC_ACCOUNT_ROLES,
+ LOGIN_INS_RBAC_ACCOUNT_ROLE,
+ LOGIN_DEL_RBAC_ACCOUNT_ROLE,
+ LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS,
+ LOGIN_INS_RBAC_ACCOUNT_PERMISSION,
+ LOGIN_DEL_RBAC_ACCOUNT_PERMISSION,
MAX_LOGINDATABASE_STATEMENTS
};
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 641fe1ebb62..f6a09667dda 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -814,18 +814,6 @@ RecruitAFriend.MaxLevel = 60
RecruitAFriend.MaxDifference = 4
#
-# InstantLogout
-# Description: Required security level for instantly logging out everywhere.
-# Does not work while in combat, dueling or falling.
-# Default: 1 - (Enabled, Mods/GMs/Admins)
-# 0 - (Enabled, Everyone)
-# 2 - (Enabled, GMs/Admins)
-# 3 - (Enabled, Admins)
-# 4 - (Disabled)
-
-InstantLogout = 1
-
-#
# DisableWaterBreath
# Description: Required security level for water breathing.
# Default: 4 - (Disabled)
@@ -1568,14 +1556,6 @@ ChatLevelReq.Whisper = 1
ChatLevelReq.Say = 1
#
-# AllowPlayerCommands
-# Description: Allow players to use commands.
-# Default: 1 - (Enabled)
-# 0 - (Disabled)
-
-AllowPlayerCommands = 1
-
-#
# PreserveCustomChannels
# Description: Store custom chat channel settings like password, automatic ownership handout
# or ban list in the database. Needs to be enabled to save custom