Core/RBAC: Create new permissions related to character creation

- 'Skips character creation team mask check'
- 'Skips character creation class mask check'
- 'Skips character creation race mask check'
- 'Skips character creation reserved name check'
- 'Skips character creation heroic min level check'
- 'Creation of two side faction characters in same account' (Affected by global config option)
This commit is contained in:
Spp
2013-02-25 15:28:41 +01:00
parent f67330e2ad
commit 019770dddb
5 changed files with 130 additions and 76 deletions

View File

@@ -1,8 +1,8 @@
-- Add new permissions
DELETE FROM `rbac_permissions` WHERE `id` IN (26, 46, 46);
DELETE FROM `rbac_permissions` WHERE `id` IN (26, 45, 46);
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
(26, 'Allow channel chat between factions'),
(46, 'Join channels without announce'),
(45, 'Join channels without announce'),
(46, 'Change channel settings without being channel moderator');
-- Add new role
@@ -16,8 +16,8 @@ INSERT INTO `rbac_roles` (`id`, `name`) VALUES
DELETE FROM `rbac_role_permissions` WHERE `roleId` IN (30, 31, 32);
INSERT INTO `rbac_role_permissions` (`roleId`, `permissionId`) VALUES
(30, 26),
(31, 46),
(32, 4645);
(31, 45),
(32, 46);
-- Add it to all GM+ groups
DELETE FROM `rbac_role_permissions` WHERE `roleId` IN (30, 31, 32);

View File

@@ -0,0 +1,36 @@
-- Add new permissions
DELETE FROM `rbac_permissions` WHERE `id` IN (14, 15, 16, 17, 18, 24);
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
(14, 'Skips character creation team mask check'),
(15, 'Skips character creation class mask check'),
(16, 'Skips character creation race mask check'),
(17, 'Skips character creation reserved name check'),
(18, 'Skips character creation heroic min level check'),
(24, 'Creation of two side faction characters in same account');
-- Add new role
DELETE FROM `rbac_roles` WHERE `id` IN (33, 34);
INSERT INTO `rbac_roles` (`id`, `name`) VALUES
(33, 'Skips character creation checks'),
(34, 'Creation of two side faction characters in same account');
-- Add the permission to the role
DELETE FROM `rbac_role_permissions` WHERE `roleId` IN (33, 34);
INSERT INTO `rbac_role_permissions` (`roleId`, `permissionId`) VALUES
(33, 14),
(33, 15),
(33, 16),
(33, 17),
(33, 18),
(34, 24);
-- Add it to all groups
DELETE FROM `rbac_role_permissions` WHERE `roleId` IN (33, 34);
INSERT INTO `rbac_group_roles` (`groupId`, `roleId`) VALUES
(2, 33),
(3, 33),
(4, 33),
(2, 34),
(3, 34),
(4, 34);

View File

@@ -48,42 +48,48 @@
enum RBACPermissions
{
RBAC_PERM_INSTANT_LOGOUT = 1,
RBAC_PERM_SKIP_QUEUE = 2,
RBAC_PERM_JOIN_NORMAL_BG = 3,
RBAC_PERM_JOIN_RANDOM_BG = 4,
RBAC_PERM_JOIN_ARENAS = 5,
RBAC_PERM_JOIN_DUNGEON_FINDER = 6,
RBAC_PERM_PLAYER_COMMANDS = 7,
RBAC_PERM_MODERATOR_COMMANDS = 8,
RBAC_PERM_GAMEMASTER_COMMANDS = 9,
RBAC_PERM_ADMINISTRATOR_COMMANDS = 10,
RBAC_PERM_LOG_GM_TRADE = 11,
RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13,
RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ = 19,
RBAC_PERM_SKIP_CHECK_DISABLE_MAP = 20,
RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED = 21,
RBAC_PERM_SKIP_CHECK_CHAT_SPAM = 22,
RBAC_PERM_SKIP_CHECK_OVERSPEED_PING = 23,
RBAC_PERM_TWO_SIDE_INTERACTION_CHAT = 25,
RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL = 26,
RBAC_PERM_TWO_SIDE_INTERACTION_MAIL = 27,
RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY = 30,
RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS = 31,
RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET = 32,
RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR = 33,
RBAC_PERM_COMMANDS_APPEAR_IN_GM_LIST = 34,
RBAC_PERM_CAN_FILTER_WHISPERS = 36,
RBAC_PERM_CHAT_USE_STAFF_BADGE = 37,
RBAC_PERM_RESURRECT_WITH_FULL_HPS = 38,
RBAC_PERM_RESTORE_SAVED_GM_STATE = 39,
RBAC_PERM_USE_START_GM_LEVEL = 41,
RBAC_PERM_OPCODE_WORLD_TELEPORT = 42,
RBAC_PERM_OPCODE_WHOIS = 43,
RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE = 44,
RBAC_PERM_SILENTLY_JOIN_CHANNEL = 45,
RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR = 46,
RBAC_PERM_CHECK_FOR_LOWER_SECURITY = 47,
RBAC_PERM_INSTANT_LOGOUT = 1,
RBAC_PERM_SKIP_QUEUE = 2,
RBAC_PERM_JOIN_NORMAL_BG = 3,
RBAC_PERM_JOIN_RANDOM_BG = 4,
RBAC_PERM_JOIN_ARENAS = 5,
RBAC_PERM_JOIN_DUNGEON_FINDER = 6,
RBAC_PERM_PLAYER_COMMANDS = 7,
RBAC_PERM_MODERATOR_COMMANDS = 8,
RBAC_PERM_GAMEMASTER_COMMANDS = 9,
RBAC_PERM_ADMINISTRATOR_COMMANDS = 10,
RBAC_PERM_LOG_GM_TRADE = 11,
RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK = 16,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME = 17,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER = 18,
RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ = 19,
RBAC_PERM_SKIP_CHECK_DISABLE_MAP = 20,
RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED = 21,
RBAC_PERM_SKIP_CHECK_CHAT_SPAM = 22,
RBAC_PERM_SKIP_CHECK_OVERSPEED_PING = 23,
RBAC_PERM_TWO_SIDE_CHARACTER_CREATION = 24,
RBAC_PERM_TWO_SIDE_INTERACTION_CHAT = 25,
RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL = 26,
RBAC_PERM_TWO_SIDE_INTERACTION_MAIL = 27,
RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY = 30,
RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS = 31,
RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET = 32,
RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR = 33,
RBAC_PERM_COMMANDS_APPEAR_IN_GM_LIST = 34,
RBAC_PERM_CAN_FILTER_WHISPERS = 36,
RBAC_PERM_CHAT_USE_STAFF_BADGE = 37,
RBAC_PERM_RESURRECT_WITH_FULL_HPS = 38,
RBAC_PERM_RESTORE_SAVED_GM_STATE = 39,
RBAC_PERM_USE_START_GM_LEVEL = 41,
RBAC_PERM_OPCODE_WORLD_TELEPORT = 42,
RBAC_PERM_OPCODE_WHOIS = 43,
RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE = 44,
RBAC_PERM_SILENTLY_JOIN_CHANNEL = 45,
RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR = 46,
RBAC_PERM_CHECK_FOR_LOWER_SECURITY = 47,
RBAC_PERM_MAX
};

View File

@@ -16774,7 +16774,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// check name limitations
if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS ||
(AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && sObjectMgr->IsReservedName(m_name)))
(!GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) &&
sObjectMgr->IsReservedName(m_name)))
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_RENAME));

View File

@@ -274,7 +274,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK))
{
if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED))
{
@@ -283,13 +283,17 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
uint32 team = Player::TeamForRace(race_);
switch (team)
{
case ALLIANCE: disabled = mask & (1 << 0); break;
case HORDE: disabled = mask & (1 << 1); break;
case ALLIANCE:
disabled = mask & (1 << 0);
break;
case HORDE:
disabled = mask & (1 << 1);
break;
}
if (disabled)
{
data << (uint8)CHAR_CREATE_DISABLED;
data << uint8(CHAR_CREATE_DISABLED);
SendPacket(&data);
return;
}
@@ -299,7 +303,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_);
if (!classEntry)
{
data << (uint8)CHAR_CREATE_FAILED;
data << uint8(CHAR_CREATE_FAILED);
SendPacket(&data);
sLog->outError(LOG_FILTER_NETWORKIO, "Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", class_, GetAccountId());
return;
@@ -308,7 +312,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_);
if (!raceEntry)
{
data << (uint8)CHAR_CREATE_FAILED;
data << uint8(CHAR_CREATE_FAILED);
SendPacket(&data);
sLog->outError(LOG_FILTER_NETWORKIO, "Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", race_, GetAccountId());
return;
@@ -317,7 +321,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion race without Expansion account
if (raceEntry->expansion > Expansion())
{
data << (uint8)CHAR_CREATE_EXPANSION;
data << uint8(CHAR_CREATE_EXPANSION);
sLog->outError(LOG_FILTER_NETWORKIO, "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, race_);
SendPacket(&data);
return;
@@ -326,13 +330,13 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion class without Expansion account
if (classEntry->expansion > Expansion())
{
data << (uint8)CHAR_CREATE_EXPANSION_CLASS;
data << uint8(CHAR_CREATE_EXPANSION_CLASS);
sLog->outError(LOG_FILTER_NETWORKIO, "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, class_);
SendPacket(&data);
return;
}
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (race_ - 1)) & raceMaskDisabled)
@@ -341,7 +345,10 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
SendPacket(&data);
return;
}
}
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK))
{
uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
if ((1 << (class_ - 1)) & classMaskDisabled)
{
@@ -354,7 +361,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating with invalid name
if (!normalizePlayerName(name))
{
data << (uint8)CHAR_NAME_NO_NAME;
data << uint8(CHAR_NAME_NO_NAME);
SendPacket(&data);
sLog->outError(LOG_FILTER_NETWORKIO, "Account:[%d] but tried to Create character with empty [name] ", GetAccountId());
return;
@@ -369,29 +376,32 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
return;
}
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(name))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(name))
{
data << (uint8)CHAR_NAME_RESERVED;
data << uint8(CHAR_NAME_RESERVED);
SendPacket(&data);
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()) && class_ == CLASS_DEATH_KNIGHT)
if (class_ == CLASS_DEATH_KNIGHT && !HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER))
{
data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
SendPacket(&data);
return;
}
// speedup check for heroic class disabled case
uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
if (heroic_free_slots == 0)
{
data << uint8(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
SendPacket(&data);
return;
}
// 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()) && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
SendPacket(&data);
return;
// speedup check for heroic class disabled case
uint32 req_level_for_heroic = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
if (req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT);
SendPacket(&data);
return;
}
}
delete _charCreateCallback.GetParam(); // Delete existing if any, to make the callback chain reset to stage 0
@@ -482,7 +492,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
}
}
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_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
_charCreateCallback.FreeResult();
@@ -506,8 +516,9 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
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_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
bool checkHeroicReqs = createInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER);
if (result)
{
@@ -517,7 +528,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
Field* field = result->Fetch();
uint8 accRace = field[1].GetUInt8();
if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT)
if (checkHeroicReqs)
{
uint8 accClass = field[2].GetUInt8();
if (accClass == CLASS_DEATH_KNIGHT)
@@ -576,7 +587,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (!haveSameRace)
haveSameRace = createInfo->Race == accRace;
if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT)
if (checkHeroicReqs)
{
uint8 acc_class = field[2].GetUInt8();
if (acc_class == CLASS_DEATH_KNIGHT)
@@ -605,7 +616,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
}
}
if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT && !hasHeroicReqLevel)
if (checkHeroicReqs && !hasHeroicReqLevel)
{
WorldPacket data(SMSG_CHAR_CREATE, 1);
data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT);
@@ -1122,7 +1133,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
}
// check name limitations
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << uint8(CHAR_NAME_RESERVED);
@@ -1444,7 +1455,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
}
// check name limitations
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
{
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
data << uint8(CHAR_NAME_RESERVED);
@@ -1690,7 +1701,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
return;
}
if (AccountMgr::IsPlayerAccount(GetSecurity()))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (race - 1)) & raceMaskDisabled)
@@ -1721,7 +1732,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
}
// check name limitations
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newname))
if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newname))
{
WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1);
data << uint8(CHAR_NAME_RESERVED);