diff --git a/data/sql/updates/pending_db_auth/rev_1770173499134350791.sql b/data/sql/updates/pending_db_auth/rev_1770173499134350791.sql new file mode 100644 index 000000000..1f86ccdd8 --- /dev/null +++ b/data/sql/updates/pending_db_auth/rev_1770173499134350791.sql @@ -0,0 +1,1006 @@ +-- RBAC System for AzerothCore +-- Ported from TrinityCore + +-- Permission List table +DROP TABLE IF EXISTS `rbac_account_permissions`; +DROP TABLE IF EXISTS `rbac_default_permissions`; +DROP TABLE IF EXISTS `rbac_linked_permissions`; +DROP TABLE IF EXISTS `rbac_permissions`; + +CREATE TABLE `rbac_permissions` ( + `id` int unsigned NOT NULL DEFAULT '0' COMMENT 'Permission id', + `name` varchar(100) NOT NULL COMMENT 'Permission name', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Permission List'; + +-- Permission to Permission relation (for role inheritance) +CREATE TABLE `rbac_linked_permissions` ( + `id` int unsigned NOT NULL COMMENT 'Permission id', + `linkedId` int unsigned NOT NULL COMMENT 'Linked Permission id', + PRIMARY KEY (`id`,`linkedId`), + KEY `fk__rbac_linked_permissions__rbac_permissions1` (`id`), + KEY `fk__rbac_linked_permissions__rbac_permissions2` (`linkedId`), + CONSTRAINT `fk__rbac_linked_permissions__rbac_permissions1` FOREIGN KEY (`id`) REFERENCES `rbac_permissions` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk__rbac_linked_permissions__rbac_permissions2` FOREIGN KEY (`linkedId`) REFERENCES `rbac_permissions` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Permission - Linked Permission relation'; + +-- Default permissions by security level +CREATE TABLE `rbac_default_permissions` ( + `secId` int unsigned NOT NULL COMMENT 'Security Level id', + `permissionId` int unsigned NOT NULL COMMENT 'permission id', + `realmId` int NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all', + PRIMARY KEY (`secId`,`permissionId`,`realmId`), + KEY `fk__rbac_default_permissions__rbac_permissions` (`permissionId`), + CONSTRAINT `fk__rbac_default_permissions__rbac_permissions` FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Default permission to assign to different account security levels'; + +-- Account specific permissions +CREATE TABLE `rbac_account_permissions` ( + `accountId` int unsigned NOT NULL COMMENT 'Account id', + `permissionId` int unsigned NOT NULL COMMENT 'Permission id', + `granted` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Granted = 1, Denied = 0', + `realmId` int NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all', + PRIMARY KEY (`accountId`,`permissionId`,`realmId`), + KEY `fk__rbac_account_roles__rbac_permissions` (`permissionId`), + CONSTRAINT `fk__rbac_account_permissions__account` FOREIGN KEY (`accountId`) REFERENCES `account` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk__rbac_account_roles__rbac_permissions` FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Account-Permission relation'; + +-- ============================================================================ +-- Insert permissions +-- ============================================================================ +INSERT INTO `rbac_permissions` VALUES +-- Core permissions (1-53) +(1,'Instant logout'), +(2,'Skip Queue'), +(3,'Join Normal Battleground'), +(4,'Join Random Battleground'), +(5,'Join Arenas'), +(6,'Join Dungeon Finder'), +(7,'Skip idle connection check'), +(8,'Cannot earn achievements'), +(9,'Cannot earn realm first achievements'), +(11,'Log GM trades'), +(13,'Skip Instance required bosses check'), +(14,'Skip character creation team mask check'), +(15,'Skip character creation class mask check'), +(16,'Skip character creation race mask check'), +(17,'Skip character creation reserved name check'), +(18,'Skip character creation death knight min level check'), +(19,'Skip needed requirements to use channel check'), +(20,'Skip disable map check'), +(21,'Skip reset talents when used more than allowed check'), +(22,'Skip spam chat check'), +(23,'Skip over-speed ping check'), +(24,'Two side faction characters on the same account'), +(25,'Allow say chat between factions'), +(26,'Allow channel chat between factions'), +(27,'Two side mail interaction'), +(28,'See two side who list'), +(29,'Add friends of other faction'), +(30,'Save character without delay with .save command'), +(31,'Use params with .unstuck command'), +(32,'Can be assigned tickets with .assign ticket command'), +(33,'Notify if a command was not found'), +(34,'Check if should appear in list using .gm ingame command'), +(35,'See all security levels with who command'), +(36,'Filter whispers'), +(37,'Use staff badge in chat'), +(38,'Resurrect with full Health Points'), +(39,'Restore saved gm setting states'), +(40,'Allows to add a gm to friend list'), +(41,'Use Config option START_GM_LEVEL to assign new character level'), +(42,'Allows to use CMSG_WORLD_TELEPORT opcode'), +(43,'Allows to use CMSG_WHOIS opcode'), +(44,'Receive global GM messages/texts'), +(45,'Join channels without announce'), +(46,'Change channel settings without being channel moderator'), +(47,'Can ignore lower security checks'), +(48,'Enable IP, Last Login and EMail output in pinfo'), +(49,'Forces to enter the email for confirmation on password change'), +(50,'Allow user to check his own email with .account'), +(51,'Allow trading between factions'), +(52,'No battleground deserter debuff'), +(53,'Can be AFK on the battleground'), +-- Roles (192-199) +(192,'Role: Sec Level Administrator'), +(193,'Role: Sec Level Gamemaster'), +(194,'Role: Sec Level Moderator'), +(195,'Role: Sec Level Player'), +(196,'Role: Administrator Commands'), +(197,'Role: Gamemaster Commands'), +(198,'Role: Moderator Commands'), +(199,'Role: Player Commands'), +-- RBAC commands (200-206) +(200,'Command: rbac'), +(201,'Command: rbac account'), +(202,'Command: rbac account list'), +(203,'Command: rbac account grant'), +(204,'Command: rbac account deny'), +(205,'Command: rbac account revoke'), +(206,'Command: rbac list'), +-- Account commands (217-229) +(217,'Command: account'), +(218,'Command: account addon'), +(219,'Command: account create'), +(220,'Command: account delete'), +(221,'Command: account lock'), +(222,'Command: account lock country'), +(223,'Command: account lock ip'), +(224,'Command: account onlinelist'), +(225,'Command: account password'), +(226,'Command: account set'), +(227,'Command: account set addon'), +(228,'Command: account set gmlevel'), +(229,'Command: account set password'), +-- Achievement commands (231-232) +(231,'Command: achievement add'), +(232,'Command: achievement checkall'), +-- Arena commands (233-238) +(233,'Command: arena captain'), +(234,'Command: arena create'), +(235,'Command: arena disband'), +(236,'Command: arena info'), +(237,'Command: arena lookup'), +(238,'Command: arena rename'), +-- Ban commands (240-256) +(240,'Command: ban account'), +(241,'Command: ban character'), +(242,'Command: ban ip'), +(243,'Command: ban playeraccount'), +(245,'Command: baninfo account'), +(246,'Command: baninfo character'), +(247,'Command: baninfo ip'), +(249,'Command: banlist account'), +(250,'Command: banlist character'), +(251,'Command: banlist ip'), +(253,'Command: unban account'), +(254,'Command: unban character'), +(255,'Command: unban ip'), +(256,'Command: unban playeraccount'), +-- Battlefield commands (258-262) +(258,'Command: bf start'), +(259,'Command: bf stop'), +(260,'Command: bf switch'), +(261,'Command: bf timer'), +(262,'Command: bf enable'), +-- Account email commands (263-266) +(263,'Command: account email'), +(265,'Command: account set sec email'), +(266,'Command: account set sec regmail'), +-- Cast commands (267-272) +(267,'Command: cast'), +(268,'Command: cast back'), +(269,'Command: cast dist'), +(270,'Command: cast self'), +(271,'Command: cast target'), +(272,'Command: cast dest'), +-- Character commands (274-290) +(274,'Command: character customize'), +(275,'Command: character changefaction'), +(276,'Command: character changerace'), +(278,'Command: character deleted delete'), +(279,'Command: character deleted list'), +(280,'Command: character deleted restore'), +(281,'Command: character deleted old'), +(282,'Command: character erase'), +(283,'Command: character level'), +(284,'Command: character rename'), +(285,'Command: character reputation'), +(286,'Command: character titles'), +(287,'Command: levelup'), +(289,'Command: pdump load'), +(290,'Command: pdump write'), +-- Cheat commands (292-299) +(292,'Command: cheat casttime'), +(293,'Command: cheat cooldown'), +(294,'Command: cheat explore'), +(295,'Command: cheat god'), +(296,'Command: cheat power'), +(297,'Command: cheat status'), +(298,'Command: cheat taxi'), +(299,'Command: cheat waterwalk'), +-- Debug command (300) +(300,'Command: debug'), +-- Deserter commands (343-347) +(343,'Command: deserter bg add'), +(344,'Command: deserter bg remove'), +(346,'Command: deserter instance add'), +(347,'Command: deserter instance remove'), +-- Disable commands (350-366) +(350,'Command: disable add achievement_criteria'), +(351,'Command: disable add battleground'), +(352,'Command: disable add map'), +(353,'Command: disable add mmap'), +(354,'Command: disable add outdoorpvp'), +(355,'Command: disable add quest'), +(356,'Command: disable add spell'), +(357,'Command: disable add vmap'), +(359,'Command: disable remove achievement_criteria'), +(360,'Command: disable remove battleground'), +(361,'Command: disable remove map'), +(362,'Command: disable remove mmap'), +(363,'Command: disable remove outdoorpvp'), +(364,'Command: disable remove quest'), +(365,'Command: disable remove spell'), +(366,'Command: disable remove vmap'), +-- Event commands (367-370) +(367,'Command: event info'), +(368,'Command: event activelist'), +(369,'Command: event start'), +(370,'Command: event stop'), +-- GM commands (371-376) +(371,'Command: gm'), +(372,'Command: gm chat'), +(373,'Command: gm fly'), +(374,'Command: gm ingame'), +(375,'Command: gm list'), +(376,'Command: gm visible'), +-- Go command (377) +(377,'Command: go'), +-- Gobject commands (388-399) +(388,'Command: gobject activate'), +(389,'Command: gobject add'), +(390,'Command: gobject add temp'), +(391,'Command: gobject delete'), +(392,'Command: gobject info'), +(393,'Command: gobject move'), +(394,'Command: gobject near'), +(396,'Command: gobject set phase'), +(397,'Command: gobject set state'), +(398,'Command: gobject target'), +(399,'Command: gobject turn'), +-- Guild commands (401-407) +(401,'Command: guild'), +(402,'Command: guild create'), +(403,'Command: guild delete'), +(404,'Command: guild invite'), +(405,'Command: guild uninvite'), +(406,'Command: guild rank'), +(407,'Command: guild rename'), +-- Honor commands (409-411) +(409,'Command: honor add'), +(410,'Command: honor add kill'), +(411,'Command: honor update'), +-- Instance commands (413-416) +(413,'Command: instance listbinds'), +(414,'Command: instance unbind'), +(415,'Command: instance stats'), +(416,'Command: instance savedata'), +-- Learn commands (417-429) +(417,'Command: learn'), +(419,'Command: learn all my'), +(420,'Command: learn all my class'), +(421,'Command: learn my pettalents'), +(422,'Command: learn all my spells'), +(423,'Command: learn all talents'), +(424,'Command: learn all gm'), +(425,'Command: learn all crafts'), +(426,'Command: learn all default'), +(427,'Command: learn all lang'), +(428,'Command: learn all recipes'), +(429,'Command: unlearn'), +-- LFG commands (431-436) +(431,'Command: lfg player'), +(432,'Command: lfg group'), +(433,'Command: lfg queue'), +(434,'Command: lfg clean'), +(435,'Command: lfg options'), +(436,'Command: lfg cooldown'), +-- List commands (437-441) +(437,'Command: list creature'), +(438,'Command: list item'), +(439,'Command: list object'), +(440,'Command: list auras'), +(441,'Command: list mail'), +-- Lookup commands (442-461) +(442,'Command: lookup'), +(443,'Command: lookup area'), +(444,'Command: lookup creature'), +(445,'Command: lookup event'), +(446,'Command: lookup faction'), +(447,'Command: lookup item'), +(448,'Command: lookup itemset'), +(449,'Command: lookup object'), +(450,'Command: lookup quest'), +(451,'Command: lookup player'), +(452,'Command: lookup player ip'), +(453,'Command: lookup player account'), +(454,'Command: lookup player email'), +(455,'Command: lookup skill'), +(456,'Command: lookup spell'), +(457,'Command: lookup spell id'), +(458,'Command: lookup taxinode'), +(459,'Command: lookup tele'), +(460,'Command: lookup title'), +(461,'Command: lookup map'), +-- Announce/Channel commands (462-471) +(462,'Command: announce'), +(463,'Command: channel'), +(464,'Command: channel set'), +(465,'Command: channel set ownership'), +(466,'Command: gmannounce'), +(467,'Command: gmnameannounce'), +(468,'Command: gmnotify'), +(469,'Command: nameannounce'), +(470,'Command: notify'), +(471,'Command: whispers'), +-- Group commands (472-478) +(472,'Command: group'), +(473,'Command: group leader'), +(474,'Command: group disband'), +(475,'Command: group remove'), +(476,'Command: group join'), +(477,'Command: group list'), +(478,'Command: group summon'), +-- Pet commands (479-482) +(479,'Command: pet'), +(480,'Command: pet create'), +(481,'Command: pet learn'), +(482,'Command: pet unlearn'), +-- Send commands (483-487) +(483,'Command: send'), +(484,'Command: send items'), +(485,'Command: send mail'), +(486,'Command: send message'), +(487,'Command: send money'), +-- Misc commands (488-535) +(488,'Command: additem'), +(489,'Command: additemset'), +(490,'Command: appear'), +(491,'Command: aura'), +(492,'Command: bank'), +(493,'Command: bindsight'), +(494,'Command: combatstop'), +(495,'Command: cometome'), +(496,'Command: commands'), +(497,'Command: cooldown'), +(498,'Command: damage'), +(499,'Command: dev'), +(500,'Command: die'), +(501,'Command: dismount'), +(502,'Command: distance'), +(503,'Command: flusharenapoints'), +(504,'Command: freeze'), +(505,'Command: gps'), +(506,'Command: guid'), +(507,'Command: help'), +(508,'Command: hidearea'), +(509,'Command: itemmove'), +(510,'Command: kick'), +(511,'Command: linkgrave'), +(512,'Command: listfreeze'), +(513,'Command: maxskill'), +(514,'Command: movegens'), +(515,'Command: mute'), +(516,'Command: neargrave'), +(517,'Command: pinfo'), +(518,'Command: playall'), +(519,'Command: possess'), +(520,'Command: recall'), +(521,'Command: repairitems'), +(522,'Command: respawn'), +(523,'Command: revive'), +(524,'Command: saveall'), +(525,'Command: save'), +(526,'Command: setskill'), +(527,'Command: showarea'), +(528,'Command: summon'), +(529,'Command: unaura'), +(530,'Command: unbindsight'), +(531,'Command: unfreeze'), +(532,'Command: unmute'), +(533,'Command: unpossess'), +(534,'Command: unstuck'), +(535,'Command: wchange'), +-- MMap commands (536-541) +(536,'Command: mmap'), +(537,'Command: mmap loadedtiles'), +(538,'Command: mmap loc'), +(539,'Command: mmap path'), +(540,'Command: mmap stats'), +(541,'Command: mmap testarea'), +-- Morph commands (542-543) +(542,'Command: morph'), +(543,'Command: demorph'), +-- Modify commands (544-569) +(544,'Command: modify'), +(545,'Command: modify arenapoints'), +(546,'Command: modify bit'), +(547,'Command: modify drunk'), +(548,'Command: modify energy'), +(549,'Command: modify faction'), +(550,'Command: modify gender'), +(551,'Command: modify honor'), +(552,'Command: modify hp'), +(553,'Command: modify mana'), +(554,'Command: modify money'), +(555,'Command: modify mount'), +(556,'Command: modify phase'), +(557,'Command: modify rage'), +(558,'Command: modify reputation'), +(559,'Command: modify runicpower'), +(560,'Command: modify scale'), +(561,'Command: modify speed'), +(562,'Command: modify speed all'), +(563,'Command: modify speed backwalk'), +(564,'Command: modify speed fly'), +(565,'Command: modify speed walk'), +(566,'Command: modify speed swim'), +(567,'Command: modify spell'), +(568,'Command: modify standstate'), +(569,'Command: modify talentpoints'), +-- NPC commands (571-601) +(571,'Command: npc add'), +(572,'Command: npc add formation'), +(573,'Command: npc add item'), +(574,'Command: npc add move'), +(575,'Command: npc add temp'), +(576,'Command: npc delete'), +(577,'Command: npc delete item'), +(578,'Command: npc follow'), +(579,'Command: npc follow stop'), +(580,'Command: npc set'), +(581,'Command: npc set allowmove'), +(582,'Command: npc set entry'), +(583,'Command: npc set factionid'), +(584,'Command: npc set flag'), +(585,'Command: npc set level'), +(586,'Command: npc set link'), +(587,'Command: npc set model'), +(588,'Command: npc set movetype'), +(589,'Command: npc set phase'), +(590,'Command: npc set spawndist'), +(591,'Command: npc set spawntime'), +(592,'Command: npc set data'), +(593,'Command: npc info'), +(594,'Command: npc near'), +(595,'Command: npc move'), +(596,'Command: npc playemote'), +(597,'Command: npc say'), +(598,'Command: npc textemote'), +(599,'Command: npc whisper'), +(600,'Command: npc yell'), +(601,'Command: npc tame'), +-- Quest commands (602-606) +(602,'Command: quest'), +(603,'Command: quest add'), +(604,'Command: quest complete'), +(605,'Command: quest remove'), +(606,'Command: quest reward'), +-- Reload commands (607-709) +(607,'Command: reload'), +(608,'Command: reload access_requirement'), +(609,'Command: reload achievement_criteria_data'), +(610,'Command: reload achievement_reward'), +(611,'Command: reload all'), +(612,'Command: reload all achievement'), +(613,'Command: reload all area'), +(614,'Command: reload broadcast_text'), +(615,'Command: reload all gossips'), +(616,'Command: reload all item'), +(617,'Command: reload all locales'), +(618,'Command: reload all loot'), +(619,'Command: reload all npc'), +(620,'Command: reload all quest'), +(621,'Command: reload all scripts'), +(622,'Command: reload all spell'), +(623,'Command: reload areatrigger_involvedrelation'), +(624,'Command: reload areatrigger_tavern'), +(625,'Command: reload areatrigger_teleport'), +(626,'Command: reload auctions'), +(627,'Command: reload autobroadcast'), +(629,'Command: reload conditions'), +(630,'Command: reload config'), +(631,'Command: reload battleground_template'), +(632,'Command: mutehistory'), +(633,'Command: reload creature_linked_respawn'), +(634,'Command: reload creature_loot_template'), +(635,'Command: reload creature_onkill_reputation'), +(636,'Command: reload creature_questender'), +(637,'Command: reload creature_queststarter'), +(638,'Command: reload creature_summon_groups'), +(639,'Command: reload creature_template'), +(640,'Command: reload creature_text'), +(641,'Command: reload disables'), +(642,'Command: reload disenchant_loot_template'), +(643,'Command: reload event_scripts'), +(644,'Command: reload fishing_loot_template'), +(645,'Command: reload graveyard_zone'), +(646,'Command: reload game_tele'), +(647,'Command: reload gameobject_questender'), +(648,'Command: reload gameobject_quest_loot_template'), +(649,'Command: reload gameobject_queststarter'), +(650,'Command: reload gm_tickets'), +(651,'Command: reload gossip_menu'), +(652,'Command: reload gossip_menu_option'), +(653,'Command: reload item_enchantment_template'), +(654,'Command: reload item_loot_template'), +(655,'Command: reload item_set_names'), +(656,'Command: reload lfg_dungeon_rewards'), +(657,'Command: reload achievement_reward_locale'), +(658,'Command: reload creature_template_locale'), +(659,'Command: reload creature_text_locale'), +(660,'Command: reload gameobject_template_locale'), +(661,'Command: reload gossip_menu_option_locale'), +(662,'Command: reload item_template_locale'), +(663,'Command: reload item_set_name_locale'), +(664,'Command: reload npc_text_locale'), +(665,'Command: reload page_text_locale'), +(666,'Command: reload points_of_interest_locale'), +(667,'Command: reload quest_template_locale'), +(668,'Command: reload mail_level_reward'), +(669,'Command: reload mail_loot_template'), +(670,'Command: reload milling_loot_template'), +(671,'Command: reload npc_spellclick_spells'), +(672,'Command: reload trainer'), +(673,'Command: reload npc_vendor'), +(674,'Command: reload page_text'), +(675,'Command: reload pickpocketing_loot_template'), +(676,'Command: reload points_of_interest'), +(677,'Command: reload prospecting_loot_template'), +(678,'Command: reload quest_poi'), +(679,'Command: reload quest_template'), +(680,'Command: reload rbac'), +(681,'Command: reload reference_loot_template'), +(682,'Command: reload reserved_name'), +(683,'Command: reload reputation_reward_rate'), +(684,'Command: reload reputation_spillover_template'), +(685,'Command: reload skill_discovery_template'), +(686,'Command: reload skill_extra_item_template'), +(687,'Command: reload skill_fishing_base_level'), +(688,'Command: reload skinning_loot_template'), +(689,'Command: reload smart_scripts'), +(690,'Command: reload spell_required'), +(691,'Command: reload spell_area'), +(692,'Command: reload spell_bonus_data'), +(693,'Command: reload spell_group'), +(694,'Command: reload spell_learn_spell'), +(695,'Command: reload spell_loot_template'), +(696,'Command: reload spell_linked_spell'), +(697,'Command: reload spell_pet_auras'), +(698,'Command: character changeaccount'), +(699,'Command: reload spell_proc'), +(701,'Command: reload spell_target_position'), +(702,'Command: reload spell_threats'), +(703,'Command: reload spell_group_stack_rules'), +(704,'Command: reload acore_string'), +(706,'Command: reload waypoint_scripts'), +(707,'Command: reload waypoint_data'), +(708,'Command: reload vehicle_accessory'), +(709,'Command: reload vehicle_template_accessory'), +-- Reset commands (710-717) +(710,'Command: reset'), +(711,'Command: reset achievements'), +(712,'Command: reset honor'), +(713,'Command: reset level'), +(714,'Command: reset spells'), +(715,'Command: reset stats'), +(716,'Command: reset talents'), +(717,'Command: reset all'), +-- Server commands (718-736) +(718,'Command: server'), +(719,'Command: server corpses'), +(720,'Command: server exit'), +(721,'Command: server idlerestart'), +(722,'Command: server idlerestart cancel'), +(723,'Command: server idleshutdown'), +(724,'Command: server idleshutdown cancel'), +(725,'Command: server info'), +(726,'Command: server plimit'), +(727,'Command: server restart'), +(728,'Command: server restart cancel'), +(729,'Command: server set'), +(730,'Command: server set closed'), +(731,'Command: server set difftime'), +(732,'Command: server set loglevel'), +(733,'Command: server set motd'), +(734,'Command: server shutdown'), +(735,'Command: server shutdown cancel'), +(736,'Command: server motd'), +-- Tele commands (737-741) +(737,'Command: tele'), +(738,'Command: tele add'), +(739,'Command: tele del'), +(740,'Command: tele name'), +(741,'Command: tele group'), +-- Ticket commands (742-760) +(742,'Command: ticket'), +(743,'Command: ticket assign'), +(744,'Command: ticket close'), +(745,'Command: ticket closedlist'), +(746,'Command: ticket comment'), +(747,'Command: ticket complete'), +(748,'Command: ticket delete'), +(749,'Command: ticket escalate'), +(750,'Command: ticket escalatedlist'), +(751,'Command: ticket list'), +(752,'Command: ticket onlinelist'), +(753,'Command: ticket reset'), +(754,'Command: ticket response'), +(755,'Command: ticket response append'), +(756,'Command: ticket response appendln'), +(757,'Command: ticket togglesystem'), +(758,'Command: ticket unassign'), +(759,'Command: ticket viewid'), +(760,'Command: ticket viewname'), +-- Titles commands (762-766) +(762,'Command: titles add'), +(763,'Command: titles current'), +(764,'Command: titles remove'), +(766,'Command: titles set mask'), +-- WP commands (767-774) +(767,'Command: wp'), +(768,'Command: wp add'), +(769,'Command: wp event'), +(770,'Command: wp load'), +(771,'Command: wp modify'), +(772,'Command: wp unload'), +(773,'Command: wp reload'), +(774,'Command: wp show'), +-- Mailbox command (777) +(777,'Command: mailbox'), +-- AHBot commands (779-793) +(779,'Command: ahbot items'), +(780,'Command: ahbot items gray'), +(781,'Command: ahbot items white'), +(782,'Command: ahbot items green'), +(783,'Command: ahbot items blue'), +(784,'Command: ahbot items purple'), +(785,'Command: ahbot items orange'), +(786,'Command: ahbot items yellow'), +(787,'Command: ahbot ratio'), +(788,'Command: ahbot ratio alliance'), +(789,'Command: ahbot ratio horde'), +(790,'Command: ahbot ratio neutral'), +(791,'Command: ahbot rebuild'), +(792,'Command: ahbot reload'), +(793,'Command: ahbot status'), +-- Guild info / Instance boss / PVPStats / Modify XP (794-798) +(794,'Command: guild info'), +(795,'Command: instance setbossstate'), +(796,'Command: instance getbossstate'), +(797,'Command: pvpstats'), +(798,'Command: modify xp'), +-- Additional commands (837-843) +(837,'Command: npc evade'), +(838,'Command: pet level'), +(839,'Command: server shutdown force'), +(840,'Command: server restart force'), +(841,'Command: neargraveyard'), +(843,'Command: reload quest_greeting'), +-- Spawngroup / Group / NPC / List commands (856-868) +(856,'Command: npc spawngroup'), +(857,'Command: npc despawngroup'), +(858,'Command: gobject spawngroup'), +(859,'Command: gobject despawngroup'), +(860,'Command: list respawns'), +(861,'Command: group set'), +(862,'Command: group set assistant'), +(863,'Command: group set maintank'), +(864,'Command: group set mainassist'), +(865,'Command: npc showloot'), +(866,'Command: list spawnpoints'), +(867,'Command: reload quest_greeting_locale'), +(868,'Command: group revive'), +-- Server debug / Reload / Settings / Lookup (872-877) +(872,'Command: server debug'), +(873,'Command: reload creature_movement_override'), +(874,'Command: settings announcer'), +(875,'Command: lookup map id'), +(876,'Command: lookup item id'), +(877,'Command: lookup quest id'), +-- PDump copy / Reload vehicle template (880-881) +(880,'Command: pdump copy'), +(881,'Command: reload vehicle_template'), +-- BG start/stop (884-885) +(884,'Command: bg start'), +(885,'Command: bg stop'), +-- AC-specific commands (886-896) +(886,'Command: item restore'), +(887,'Command: item restore list'), +(888,'Command: item refund'), +(889,'Command: commentator'), +(890,'Command: skirmish'), +(891,'Command: string'), +(892,'Command: opendoor'), +(893,'Command: beastmaster'), +(894,'Command: packetlog'), +(895,'Command: aura stack'), +(896,'Command: respawn all'), +-- Gear / Spectator commands (897-904) +(897,'Command: gear repair'), +(898,'Command: gear stats'), +(899,'Command: spect'), +(900,'Command: spect version'), +(901,'Command: spect reset'), +(902,'Command: spect spectate'), +(903,'Command: spect watch'), +(904,'Command: spect leave'), +-- Arena season commands (905-908) +(905,'Command: arena season state'), +(906,'Command: arena season reward'), +(907,'Command: arena season deleteteams'), +(908,'Command: arena season start'), +-- Character check commands (909-911) +(909,'Command: character check bank'), +(910,'Command: character check bag'), +(911,'Command: character check profession'), +(912,'Command: gobject load'), +(913,'Command: bf queue'); + +-- ============================================================================ +-- Link roles to permissions +-- ============================================================================ +INSERT INTO `rbac_linked_permissions` VALUES +-- --------------------------------------------------------------------------- +-- Role 192 (Administrator): Core admin permissions + links to GM role and Admin commands +-- --------------------------------------------------------------------------- +(192, 7), -- Skip idle check +(192, 21), -- Skip talent reset check +(192, 42), -- World teleport opcode +(192, 43), -- Whois opcode +(192, 193), -- Links to GM role +(192, 196), -- Admin commands role +-- --------------------------------------------------------------------------- +-- Role 193 (Gamemaster): GM-specific core permissions + links to Mod role and GM commands +-- --------------------------------------------------------------------------- +(193, 45), -- Join channels without announce +(193, 48), -- Pinfo personal data +(193, 52), -- No BG deserter debuff +(193, 53), -- Can AFK in BG +(193, 194), -- Links to Moderator role +(193, 197), -- GM commands role +-- --------------------------------------------------------------------------- +-- Role 194 (Moderator): Moderator core permissions + links to Player role and Mod commands +-- --------------------------------------------------------------------------- +(194, 1), -- Instant logout +(194, 2), -- Skip queue +(194, 9), -- Cannot earn realm first achievements +(194, 11), -- Log GM trades +(194, 13), -- Skip instance required bosses check +(194, 14), -- Skip character creation team mask check +(194, 15), -- Skip character creation class mask check +(194, 16), -- Skip character creation race mask check +(194, 17), -- Skip character creation reserved name check +(194, 18), -- Skip character creation death knight check +(194, 19), -- Skip channel requirements check +(194, 20), -- Skip disable map check +(194, 22), -- Skip spam chat check +(194, 23), -- Skip over-speed ping check +(194, 25), -- Allow say chat between factions +(194, 26), -- Allow channel chat between factions +(194, 27), -- Two side mail interaction +(194, 28), -- See two side who list +(194, 29), -- Add friends of other faction +(194, 30), -- Save without delay +(194, 31), -- Unstuck with args +(194, 32), -- Can be assigned tickets +(194, 33), -- Notify command not found +(194, 34), -- Appear in GM list +(194, 35), -- See all sec levels +(194, 36), -- Filter whispers +(194, 37), -- Staff badge +(194, 38), -- Resurrect full HP +(194, 39), -- Restore GM state +(194, 40), -- Allow GM friend +(194, 41), -- Start GM level +(194, 44), -- Receive global GM messages +(194, 46), -- Change channel settings +(194, 47), -- Ignore lower security +(194, 51), -- Allow two side trade +(194, 195), -- Links to Player role +(194, 198), -- Mod commands role +(194, 632), -- Mutehistory +(194, 798), -- Modify XP +-- --------------------------------------------------------------------------- +-- Role 195 (Player): Basic player permissions + player commands +-- --------------------------------------------------------------------------- +(195, 3), -- Join BG +(195, 4), -- Join Random BG +(195, 5), -- Join Arenas +(195, 6), -- Join Dungeon Finder +(195, 24), -- Two side character creation +(195, 49), -- Email confirm for pass change +(195, 199), -- Player commands role +-- --------------------------------------------------------------------------- +-- Role 196 (Admin Commands): Server management, reload, reset, disable, etc. +-- --------------------------------------------------------------------------- +-- RBAC commands +(196, 200), (196, 201), (196, 202), (196, 203), (196, 204), (196, 205), (196, 206), +-- Account administration +(196, 219), (196, 220), (196, 224), (196, 226), (196, 227), (196, 228), (196, 229), +(196, 265), (196, 266), +-- Battlefield management +(196, 258), (196, 259), (196, 260), (196, 261), (196, 262), +-- Character admin (destructive operations) +(196, 278), (196, 281), (196, 282), (196, 698), +-- PDump +(196, 289), (196, 290), (196, 880), +-- Disable commands +(196, 350), (196, 351), (196, 352), (196, 353), (196, 354), (196, 355), (196, 356), (196, 357), +(196, 359), (196, 360), (196, 361), (196, 362), (196, 363), (196, 364), (196, 365), (196, 366), +-- Channel management +(196, 463), (196, 464), (196, 465), +-- Mass operations +(196, 503), (196, 511), (196, 524), +-- Reload commands +(196, 607), (196, 608), (196, 609), (196, 610), (196, 611), (196, 612), (196, 613), (196, 614), +(196, 615), (196, 616), (196, 617), (196, 618), (196, 619), (196, 620), (196, 621), (196, 622), +(196, 623), (196, 624), (196, 625), (196, 626), (196, 627), (196, 629), (196, 630), (196, 631), +(196, 633), (196, 634), (196, 635), (196, 636), (196, 637), (196, 638), (196, 639), (196, 640), +(196, 641), (196, 642), (196, 643), (196, 644), (196, 645), (196, 646), (196, 647), (196, 648), +(196, 649), (196, 650), (196, 651), (196, 652), (196, 653), (196, 654), (196, 655), (196, 656), +(196, 657), (196, 658), (196, 659), (196, 660), (196, 661), (196, 662), (196, 663), (196, 664), +(196, 665), (196, 666), (196, 667), (196, 668), (196, 669), (196, 670), (196, 671), (196, 672), +(196, 673), (196, 674), (196, 675), (196, 676), (196, 677), (196, 678), (196, 679), (196, 680), +(196, 681), (196, 682), (196, 683), (196, 684), (196, 685), (196, 686), (196, 687), (196, 688), +(196, 689), (196, 690), (196, 691), (196, 692), (196, 693), (196, 694), (196, 695), (196, 696), +(196, 697), (196, 699), (196, 701), (196, 702), (196, 703), (196, 704), (196, 706), (196, 707), +(196, 708), (196, 709), +(196, 843), (196, 867), (196, 873), (196, 881), +-- Reset commands +(196, 710), (196, 711), (196, 712), (196, 713), (196, 714), (196, 715), (196, 716), (196, 717), +-- Server commands +(196, 718), (196, 719), (196, 720), (196, 721), (196, 722), (196, 723), (196, 724), +(196, 726), (196, 727), (196, 728), (196, 729), (196, 730), (196, 731), (196, 732), +(196, 733), (196, 734), (196, 735), (196, 736), +(196, 839), (196, 840), (196, 872), +-- Ticket admin (destructive) +(196, 748), (196, 753), (196, 757), +-- WP reload +(196, 773), +-- Mailbox +(196, 777), +-- AHBot +(196, 779), (196, 780), (196, 781), (196, 782), (196, 783), (196, 784), (196, 785), +(196, 786), (196, 787), (196, 788), (196, 789), (196, 790), (196, 791), (196, 792), (196, 793), +-- Gobject load / List spawnpoints +(196, 912), (196, 866), +-- Arena season commands +(196, 905), (196, 906), (196, 907), (196, 908), +-- AC-specific admin commands +(196, 886), (196, 887), (196, 888), (196, 891), (196, 894), (196, 896), +-- --------------------------------------------------------------------------- +-- Role 197 (GM Commands): Game manipulation, character, NPC, gobject, quest, etc. +-- --------------------------------------------------------------------------- +-- Achievement +(197, 231), (197, 232), +-- Arena +(197, 233), (197, 234), (197, 235), (197, 236), (197, 237), (197, 238), +-- Cast +(197, 267), (197, 268), (197, 269), (197, 270), (197, 271), (197, 272), +-- Character +(197, 274), (197, 275), (197, 276), (197, 279), (197, 280), +(197, 283), (197, 284), (197, 285), (197, 286), (197, 287), +(197, 909), (197, 910), (197, 911), +-- Cheat +(197, 292), (197, 293), (197, 294), (197, 295), (197, 296), (197, 297), (197, 298), (197, 299), +-- Debug +(197, 300), +-- Deserter +(197, 343), (197, 344), (197, 346), (197, 347), +-- Event +(197, 367), (197, 368), (197, 369), (197, 370), +-- GM / Go +(197, 371), (197, 372), (197, 373), (197, 376), (197, 377), +-- Gobject +(197, 388), (197, 389), (197, 390), (197, 391), (197, 392), (197, 393), (197, 394), +(197, 396), (197, 397), (197, 398), (197, 399), +-- Guild +(197, 401), (197, 402), (197, 403), (197, 404), (197, 405), (197, 406), (197, 407), +-- Honor +(197, 409), (197, 410), (197, 411), +-- Instance +(197, 413), (197, 414), (197, 415), (197, 416), +-- Learn +(197, 417), (197, 419), (197, 420), (197, 421), (197, 422), (197, 423), (197, 424), +(197, 425), (197, 426), (197, 427), (197, 428), (197, 429), +-- LFG +(197, 431), (197, 432), (197, 433), (197, 434), (197, 435), (197, 436), +-- List +(197, 437), (197, 438), (197, 439), (197, 440), (197, 441), +-- Lookup (GM-level) +(197, 445), (197, 448), (197, 449), (197, 451), (197, 452), (197, 453), (197, 454), +(197, 457), (197, 458), (197, 460), (197, 461), +-- Group +(197, 472), (197, 473), (197, 474), (197, 475), (197, 476), (197, 477), (197, 478), +-- Pet +(197, 479), (197, 480), (197, 481), (197, 482), +-- Send +(197, 483), (197, 484), (197, 485), (197, 486), (197, 487), +-- Misc game commands +(197, 488), (197, 489), (197, 490), (197, 491), (197, 492), (197, 493), (197, 494), (197, 495), +(197, 497), (197, 498), (197, 499), (197, 500), +(197, 502), (197, 504), (197, 506), (197, 508), (197, 509), +(197, 512), (197, 513), (197, 514), (197, 516), (197, 518), (197, 519), (197, 520), +(197, 521), (197, 522), (197, 523), (197, 526), (197, 527), (197, 528), (197, 529), (197, 530), (197, 531), +(197, 533), (197, 535), +-- MMap +(197, 536), (197, 537), (197, 538), (197, 539), (197, 540), (197, 541), +-- Morph +(197, 542), (197, 543), +-- Modify +(197, 544), (197, 545), (197, 546), (197, 547), (197, 548), (197, 549), (197, 550), (197, 551), +(197, 552), (197, 553), (197, 554), (197, 555), (197, 556), (197, 557), (197, 558), (197, 559), +(197, 560), (197, 561), (197, 562), (197, 563), (197, 564), (197, 565), (197, 566), (197, 567), +(197, 568), (197, 569), +-- NPC +(197, 571), (197, 572), (197, 573), (197, 574), (197, 575), (197, 576), (197, 577), (197, 578), +(197, 579), (197, 580), (197, 581), (197, 582), (197, 583), (197, 584), (197, 585), (197, 586), +(197, 587), (197, 588), (197, 589), (197, 590), (197, 591), (197, 592), (197, 593), (197, 594), +(197, 595), (197, 596), (197, 597), (197, 598), (197, 599), (197, 600), (197, 601), +-- Quest +(197, 602), (197, 603), (197, 604), (197, 605), (197, 606), +-- Tele +(197, 737), (197, 738), (197, 739), (197, 740), (197, 741), +-- Titles +(197, 762), (197, 763), (197, 764), (197, 766), +-- WP (except reload which is in 196) +(197, 767), (197, 768), (197, 769), (197, 770), (197, 771), (197, 772), (197, 774), +-- Guild info / Instance boss state / Modify XP +(197, 794), (197, 795), (197, 796), (197, 798), +-- NPC evade / Pet level / Neargraveyard +(197, 837), (197, 838), (197, 841), +-- Spawngroup / List respawns +(197, 856), (197, 857), (197, 858), (197, 859), (197, 860), +-- Group set / NPC showloot +(197, 861), (197, 862), (197, 863), (197, 864), (197, 865), +-- Group revive / Settings announcer +(197, 868), (197, 874), +-- Lookup map/item/quest id +(197, 875), (197, 876), (197, 877), +-- BG start/stop / BF queue +(197, 884), (197, 885), (197, 913), +-- AC-specific GM commands +(197, 889), (197, 890), (197, 892), (197, 893), (197, 895), +-- Gear repair +(197, 897), +-- --------------------------------------------------------------------------- +-- Role 198 (Mod Commands): Community management - ban, mute, kick, tickets, announce +-- --------------------------------------------------------------------------- +-- Ban/Unban +(198, 240), (198, 241), (198, 242), (198, 243), +(198, 245), (198, 246), (198, 247), +(198, 249), (198, 250), (198, 251), +(198, 253), (198, 254), (198, 255), (198, 256), +-- Announce/Notify +(198, 462), (198, 466), (198, 467), (198, 468), (198, 469), (198, 470), (198, 471), +-- Kick/Mute/Pinfo/Unmute +(198, 510), (198, 515), (198, 517), (198, 532), +-- Mutehistory +(198, 632), +-- Ticket commands (excluding admin-only 748 delete, 753 reset, 757 togglesystem) +(198, 742), (198, 743), (198, 744), (198, 745), (198, 746), (198, 747), +(198, 749), (198, 750), (198, 751), (198, 752), +(198, 754), (198, 755), (198, 756), (198, 758), (198, 759), (198, 760), +-- --------------------------------------------------------------------------- +-- Role 199 (Player Commands): Self-service account management, basic lookups +-- --------------------------------------------------------------------------- +-- Account self-management +(199, 217), (199, 218), (199, 221), (199, 222), (199, 223), (199, 225), (199, 263), +-- GM info +(199, 374), (199, 375), +-- Lookup (basic) +(199, 442), (199, 443), (199, 444), (199, 446), (199, 447), (199, 450), (199, 455), (199, 456), (199, 459), +-- Basic commands +(199, 496), (199, 501), (199, 505), (199, 507), (199, 525), (199, 534), +-- Server info / PVPStats +(199, 725), (199, 797), +-- Gear stats +(199, 898), +-- Spectator +(199, 899), (199, 900), (199, 901), (199, 902), (199, 903), (199, 904); + +-- ============================================================================ +-- Default permissions by security level +-- ============================================================================ +-- SEC_PLAYER = 0 gets Player role (195) +-- SEC_MODERATOR = 1 gets Moderator role (194, which includes 195) +-- SEC_GAMEMASTER = 2 gets GM role (193, which includes 194) +-- SEC_ADMINISTRATOR = 3 gets Admin role (192, which includes 193) +INSERT INTO `rbac_default_permissions` VALUES +(3, 192, -1), -- Admin gets Admin role +(2, 193, -1), -- GM gets GM role +(1, 194, -1), -- Moderator gets Mod role +(0, 195, -1); -- Player gets Player role diff --git a/data/sql/updates/pending_db_world/rev_1770173911371830386.sql b/data/sql/updates/pending_db_world/rev_1770173911371830386.sql new file mode 100644 index 000000000..c91c489bc --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1770173911371830386.sql @@ -0,0 +1,20 @@ +-- RBAC Language strings (uses {} format placeholders for Acore::StringFormat) +DELETE FROM `acore_string` WHERE `entry` BETWEEN 63 AND 79; +INSERT INTO `acore_string` (`entry`, `content_default`) VALUES +(63, 'Wrong parameter id: {}, does not exist'), +(64, 'Wrong parameter realmId: {}'), +(65, 'Account {} ({}) granted permissions:'), +(66, 'Account {} ({}) denied permissions:'), +(67, 'Account {} ({}) inherited permissions by sec level {} ({}):'), +(68, 'Permissions:'), +(69, 'Linked permissions:'), +(70, 'Empty List'), +(71, '- {} ({})'), +(72, 'Could not grant permission {} ({}) realmId {}. Account {} ({}) already has that permission'), +(73, 'Could not grant permission {} ({}) realmId {}. Account {} ({}) has that permission in deny list'), +(74, 'Granted permission {} ({}) realmId {} to account {} ({})'), +(75, 'Could not deny permission {} ({}) realmId {}. Account {} ({}) already has that permission'), +(76, 'Could not deny permission {} ({}) realmId {}. Account {} ({}) has that permission in grant list'), +(77, 'Denied permission {} ({}) realmId {} to account {} ({})'), +(78, 'Revoked permission {} ({}) realmId {} to account {} ({})'), +(79, 'Could not revoke permission {} ({}) realmId {}. Account {} ({}) does not have that permission'); diff --git a/data/sql/updates/pending_db_world/rev_1777553106653644140.sql b/data/sql/updates/pending_db_world/rev_1777553106653644140.sql new file mode 100644 index 000000000..b1bd2ea86 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1777553106653644140.sql @@ -0,0 +1,12 @@ +-- RBAC command help strings +DELETE FROM `acore_string` WHERE `entry` BETWEEN 83 AND 86; +INSERT INTO `acore_string` (`entry`, `content_default`) VALUES +(83, 'Syntax: .rbac account list $account\nList granted, denied, and inherited permissions for the account.'), +(84, 'Syntax: .rbac account grant $account $permissionId [$realmId]\nGrant a permission to the account. Optional realmId (-1 = all realms).'), +(85, 'Syntax: .rbac account deny $account $permissionId [$realmId]\nDeny a permission for the account. Optional realmId (-1 = all realms).'), +(86, 'Syntax: .rbac account revoke $account $permissionId [$realmId]\nRevoke a previously granted or denied permission. Optional realmId (-1 = all realms).'); + +-- Update inherited permissions header to include sec level name +DELETE FROM `acore_string` WHERE `entry` = 67; +INSERT INTO `acore_string` (`entry`, `content_default`) VALUES +(67, 'Account {} ({}) inherited permissions by sec level {} ({}):'); diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 256664672..a90e1bcd7 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -153,6 +153,14 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_UPD_ACCOUNT_TOTP_SECRET, "UPDATE account SET totp_secret = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_INS_UPTIME, "INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES (?, ?, 0, ?)", CONNECTION_ASYNC); + + PrepareStatement(LOGIN_GET_EMAIL_BY_ID, "SELECT email FROM account WHERE id = ?", CONNECTION_SYNCH); + + // RBAC + 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_BOTH); + 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); + PrepareStatement(LOGIN_SEL_RBAC_DEFAULT_PERMISSIONS, "SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = ? OR realmId = -1) ORDER BY secId ASC", CONNECTION_SYNCH); } LoginDatabaseConnection::LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index 6b6debb81..140166dda 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -133,6 +133,14 @@ enum LoginDatabaseStatements : uint32 LOGIN_INS_UPTIME, + LOGIN_GET_EMAIL_BY_ID, + + // RBAC + LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, + LOGIN_INS_RBAC_ACCOUNT_PERMISSION, + LOGIN_DEL_RBAC_ACCOUNT_PERMISSION, + LOGIN_SEL_RBAC_DEFAULT_PERMISSIONS, + MAX_LOGINDATABASE_STATEMENTS }; diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 8be9d5168..83e689fa9 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -1,10 +1,10 @@ /* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -18,315 +18,525 @@ #include "AccountMgr.h" #include "Common.h" #include "DatabaseEnv.h" +#include "Log.h" #include "ObjectAccessor.h" #include "Player.h" +#include "Realm.h" #include "SRP6.h" #include "ScriptMgr.h" #include "Util.h" #include "WorldSession.h" -namespace AccountMgr +AccountMgr::AccountMgr() { } + +AccountMgr::~AccountMgr() { + ClearRBAC(); +} - AccountOpResult CreateAccount(std::string username, std::string password, std::string email /*= ""*/) +AccountMgr* AccountMgr::instance() +{ + static AccountMgr instance; + return &instance; +} + +AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/) +{ + if (utf8length(username) > MAX_ACCOUNT_STR) + return AOR_NAME_TOO_LONG; // username's too long + + if (utf8length(password) > MAX_PASS_STR) + return AOR_PASS_TOO_LONG; // password's too long + + if (utf8length(email) > MAX_EMAIL_STR) + return AOR_EMAIL_TOO_LONG; // email is too long + + Utf8ToUpperOnlyLatin(username); + Utf8ToUpperOnlyLatin(password); + Utf8ToUpperOnlyLatin(email); + + if (GetId(username)) + return AOR_NAME_ALREADY_EXIST; // username does already exist + + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT); + + stmt->SetData(0, username); + auto [salt, verifier] = Acore::Crypto::SRP6::MakeRegistrationData(username, password); + stmt->SetData(1, salt); + stmt->SetData(2, verifier); + stmt->SetData(3, uint8(sWorld->getIntConfig(CONFIG_EXPANSION))); + stmt->SetData(4, email); + stmt->SetData(5, email); + + LoginDatabase.Execute(stmt); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT); + + LoginDatabase.Execute(stmt); + + return AOR_OK; // everything's fine +} + +AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail) +{ + std::string username; + + if (!GetName(accountId, username)) { - if (utf8length(username) > MAX_ACCOUNT_STR) - return AOR_NAME_TOO_LONG; // username's too long - - if (utf8length(password) > MAX_PASS_STR) - return AOR_PASS_TOO_LONG; // password's too long - - if (utf8length(email) > MAX_EMAIL_STR) - return AOR_EMAIL_TOO_LONG; // email is too long - - Utf8ToUpperOnlyLatin(username); - Utf8ToUpperOnlyLatin(password); - Utf8ToUpperOnlyLatin(email); - - if (GetId(username)) - return AOR_NAME_ALREADY_EXIST; // username does already exist - - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT); - - stmt->SetData(0, username); - auto [salt, verifier] = Acore::Crypto::SRP6::MakeRegistrationData(username, password); - stmt->SetData(1, salt); - stmt->SetData(2, verifier); - stmt->SetData(3, uint8(sWorld->getIntConfig(CONFIG_EXPANSION))); - stmt->SetData(4, email); - stmt->SetData(5, email); - - LoginDatabase.Execute(stmt); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT); - - LoginDatabase.Execute(stmt); - - return AOR_OK; // everything's fine + sScriptMgr->OnFailedEmailChange(accountId); + return AOR_NAME_NOT_EXIST; // account doesn't exist } - AccountOpResult ChangeEmail(uint32 accountId, std::string newEmail) + if (utf8length(newEmail) > MAX_EMAIL_STR) { - std::string username; - - if (!GetName(accountId, username)) - { - sScriptMgr->OnFailedEmailChange(accountId); - return AOR_NAME_NOT_EXIST; // account doesn't exist - } - - if (utf8length(newEmail) > MAX_EMAIL_STR) - { - sScriptMgr->OnFailedEmailChange(accountId); - return AOR_EMAIL_TOO_LONG; // email's too long - } - - Utf8ToUpperOnlyLatin(newEmail); - - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EMAIL); - stmt->SetData(0, newEmail); - stmt->SetData(1, accountId); - LoginDatabase.Execute(stmt); - - sScriptMgr->OnEmailChange(accountId); - return AOR_OK; + sScriptMgr->OnFailedEmailChange(accountId); + return AOR_EMAIL_TOO_LONG; // email's too long } - AccountOpResult DeleteAccount(uint32 accountId) + Utf8ToUpperOnlyLatin(newEmail); + + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EMAIL); + stmt->SetData(0, newEmail); + stmt->SetData(1, accountId); + LoginDatabase.Execute(stmt); + + sScriptMgr->OnEmailChange(accountId); + return AOR_OK; +} + +AccountOpResult AccountMgr::DeleteAccount(uint32 accountId) +{ + // Check if accounts exists + LoginDatabasePreparedStatement* loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID); + loginStmt->SetData(0, accountId); + + PreparedQueryResult result = LoginDatabase.Query(loginStmt); + if (!result) + return AOR_NAME_NOT_EXIST; + + sScriptMgr->OnBeforeAccountDelete(accountId); + + // Obtain accounts characters + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID); + stmt->SetData(0, accountId); + + result = CharacterDatabase.Query(stmt); + + if (result) { - // Check if accounts exists - LoginDatabasePreparedStatement* loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID); - loginStmt->SetData(0, accountId); - - PreparedQueryResult result = LoginDatabase.Query(loginStmt); - if (!result) - return AOR_NAME_NOT_EXIST; - - sScriptMgr->OnBeforeAccountDelete(accountId); - - // Obtain accounts characters - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID); - stmt->SetData(0, accountId); - - result = CharacterDatabase.Query(stmt); - - if (result) + do { - do + ObjectGuid guid = ObjectGuid::Create((*result)[0].Get()); + + // Kick if player is online + if (Player* p = ObjectAccessor::FindPlayer(guid)) { - ObjectGuid guid = ObjectGuid::Create((*result)[0].Get()); + WorldSession* s = p->GetSession(); + s->KickPlayer("Delete account"); // mark session to remove at next session list update + s->LogoutPlayer(false); // logout player without waiting next session list update + } - // Kick if player is online - if (Player* p = ObjectAccessor::FindPlayer(guid)) - { - WorldSession* s = p->GetSession(); - s->KickPlayer("Delete account"); // mark session to remove at next session list update - s->LogoutPlayer(false); // logout player without waiting next session list update - } - - Player::DeleteFromDB(guid.GetCounter(), accountId, false, true); // no need to update realm characters - } while (result->NextRow()); - } - - // table realm specific but common for all characters of account for realm - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TUTORIALS); - stmt->SetData(0, accountId); - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ACCOUNT_DATA); - stmt->SetData(0, accountId); - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_BAN); - stmt->SetData(0, accountId); - CharacterDatabase.Execute(stmt); - - LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction(); - - loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT); - loginStmt->SetData(0, accountId); - trans->Append(loginStmt); - - loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); - loginStmt->SetData(0, accountId); - trans->Append(loginStmt); - - loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS); - loginStmt->SetData(0, accountId); - trans->Append(loginStmt); - - loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_BANNED); - loginStmt->SetData(0, accountId); - trans->Append(loginStmt); - - loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_MUTED); - loginStmt->SetData(0, accountId); - trans->Append(loginStmt); - - LoginDatabase.CommitTransaction(trans); - - return AOR_OK; + Player::DeleteFromDB(guid.GetCounter(), accountId, false, true); // no need to update realm characters + } while (result->NextRow()); } - AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword) + // table realm specific but common for all characters of account for realm + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TUTORIALS); + stmt->SetData(0, accountId); + CharacterDatabase.Execute(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ACCOUNT_DATA); + stmt->SetData(0, accountId); + CharacterDatabase.Execute(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_BAN); + stmt->SetData(0, accountId); + CharacterDatabase.Execute(stmt); + + LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction(); + + loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT); + loginStmt->SetData(0, accountId); + trans->Append(loginStmt); + + loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); + loginStmt->SetData(0, accountId); + trans->Append(loginStmt); + + loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS); + loginStmt->SetData(0, accountId); + trans->Append(loginStmt); + + loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_BANNED); + loginStmt->SetData(0, accountId); + trans->Append(loginStmt); + + loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_MUTED); + loginStmt->SetData(0, accountId); + trans->Append(loginStmt); + + LoginDatabase.CommitTransaction(trans); + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword) +{ + // Check if accounts exists + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID); + stmt->SetData(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (!result) + return AOR_NAME_NOT_EXIST; + + if (utf8length(newUsername) > MAX_ACCOUNT_STR) + return AOR_NAME_TOO_LONG; + + if (utf8length(newPassword) > MAX_PASS_STR) + return AOR_PASS_TOO_LONG; // password's too long + + Utf8ToUpperOnlyLatin(newUsername); + Utf8ToUpperOnlyLatin(newPassword); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_USERNAME); + stmt->SetData(0, newUsername); + stmt->SetData(1, accountId); + LoginDatabase.Execute(stmt); + + auto [salt, verifier] = Acore::Crypto::SRP6::MakeRegistrationData(newUsername, newPassword); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); + stmt->SetData(0, salt); + stmt->SetData(1, verifier); + stmt->SetData(2, accountId); + LoginDatabase.Execute(stmt); + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPassword) +{ + std::string username; + + if (!GetName(accountId, username)) { - // Check if accounts exists - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID); + sScriptMgr->OnFailedPasswordChange(accountId); + return AOR_NAME_NOT_EXIST; // account doesn't exist + } + + if (utf8length(newPassword) > MAX_PASS_STR) + { + sScriptMgr->OnFailedEmailChange(accountId); + return AOR_PASS_TOO_LONG; // password's too long + } + + Utf8ToUpperOnlyLatin(username); + Utf8ToUpperOnlyLatin(newPassword); + + auto [salt, verifier] = Acore::Crypto::SRP6::MakeRegistrationData(username, newPassword); + + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); + stmt->SetData(0, salt); + stmt->SetData(1, verifier); + stmt->SetData(2, accountId); + LoginDatabase.Execute(stmt); + + sScriptMgr->OnPasswordChange(accountId); + return AOR_OK; +} + +uint32 AccountMgr::GetId(std::string const& username) +{ + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME); + stmt->SetData(0, username); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + return (result) ? (*result)[0].Get() : 0; +} + +uint32 AccountMgr::GetSecurity(uint32 accountId) +{ + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL); + stmt->SetData(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + return (result) ? (*result)[0].Get() : uint32(SEC_PLAYER); +} + +uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId) +{ + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); + stmt->SetData(0, accountId); + stmt->SetData(1, realmId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + return (result) ? (*result)[0].Get() : uint32(SEC_PLAYER); +} + +bool AccountMgr::GetName(uint32 accountId, std::string& name) +{ + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_USERNAME_BY_ID); + stmt->SetData(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (result) + { + name = (*result)[0].Get(); + return true; + } + + return false; +} + +bool AccountMgr::CheckPassword(uint32 accountId, std::string password) +{ + std::string username; + + if (!GetName(accountId, username)) + return false; + + Utf8ToUpperOnlyLatin(username); + Utf8ToUpperOnlyLatin(password); + + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD); + stmt->SetData(0, accountId); + if (PreparedQueryResult result = LoginDatabase.Query(stmt)) + { + Acore::Crypto::SRP6::Salt salt = (*result)[0].Get(); + Acore::Crypto::SRP6::Verifier verifier = (*result)[1].Get(); + if (Acore::Crypto::SRP6::CheckLogin(username, password, salt, verifier)) + return true; + } + + return false; +} + +uint32 AccountMgr::GetCharactersCount(uint32 accountId) +{ + // check character count + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS); + stmt->SetData(0, accountId); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + + return (result) ? (*result)[0].Get() : 0; +} + +bool AccountMgr::IsPlayerAccount(uint32 gmlevel) +{ + return gmlevel == SEC_PLAYER; +} + +bool AccountMgr::IsGMAccount(uint32 gmlevel) +{ + return gmlevel >= SEC_GAMEMASTER; +} + +bool AccountMgr::IsAdminAccount(uint32 gmlevel) +{ + return gmlevel >= SEC_ADMINISTRATOR && gmlevel <= SEC_CONSOLE; +} + +bool AccountMgr::IsConsoleAccount(uint32 gmlevel) +{ + return gmlevel == SEC_CONSOLE; +} + +bool AccountMgr::HasPermission(uint32 accountId, uint32 permission, uint32 realmId) +{ + if (!accountId) + { + LOG_ERROR("rbac", "AccountMgr::HasPermission: Wrong accountId 0"); + return false; + } + + rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId, realmId)); + rbac.LoadFromDB(); + bool hasPermission = rbac.HasPermission(permission); + + LOG_DEBUG("rbac", "AccountMgr::HasPermission [AccountId: {}, PermissionId: {}, realmId: {}]: {}", + accountId, permission, realmId, hasPermission); + + return hasPermission; +} + +void AccountMgr::UpdateAccountAccess(rbac::RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId) +{ + if (rbac && securityLevel != rbac->GetSecurityLevel()) + rbac->SetSecurityLevel(securityLevel); + + LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction(); + + // Delete old security level from DB + if (realmId == -1) + { + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); stmt->SetData(0, accountId); - PreparedQueryResult result = LoginDatabase.Query(stmt); - - if (!result) - return AOR_NAME_NOT_EXIST; - - if (utf8length(newUsername) > MAX_ACCOUNT_STR) - return AOR_NAME_TOO_LONG; - - if (utf8length(newPassword) > MAX_PASS_STR) - return AOR_PASS_TOO_LONG; // password's too long - - Utf8ToUpperOnlyLatin(newUsername); - Utf8ToUpperOnlyLatin(newPassword); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_USERNAME); - stmt->SetData(0, newUsername); - stmt->SetData(1, accountId); - LoginDatabase.Execute(stmt); - - auto [salt, verifier] = Acore::Crypto::SRP6::MakeRegistrationData(newUsername, newPassword); - stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); - stmt->SetData(0, salt); - stmt->SetData(1, verifier); - stmt->SetData(2, accountId); - LoginDatabase.Execute(stmt); - - return AOR_OK; + trans->Append(stmt); } - - AccountOpResult ChangePassword(uint32 accountId, std::string newPassword) + else { - std::string username; - - if (!GetName(accountId, username)) - { - sScriptMgr->OnFailedPasswordChange(accountId); - return AOR_NAME_NOT_EXIST; // account doesn't exist - } - - if (utf8length(newPassword) > MAX_PASS_STR) - { - sScriptMgr->OnFailedEmailChange(accountId); - return AOR_PASS_TOO_LONG; // password's too long - } - - Utf8ToUpperOnlyLatin(username); - Utf8ToUpperOnlyLatin(newPassword); - - auto [salt, verifier] = Acore::Crypto::SRP6::MakeRegistrationData(username, newPassword); - - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); - stmt->SetData(0, salt); - stmt->SetData(1, verifier); - stmt->SetData(2, accountId); - LoginDatabase.Execute(stmt); - - sScriptMgr->OnPasswordChange(accountId); - return AOR_OK; - } - - uint32 GetId(std::string const& username) - { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME); - stmt->SetData(0, username); - PreparedQueryResult result = LoginDatabase.Query(stmt); - - return (result) ? (*result)[0].Get() : 0; - } - - uint32 GetSecurity(uint32 accountId) - { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL); - stmt->SetData(0, accountId); - PreparedQueryResult result = LoginDatabase.Query(stmt); - - return (result) ? (*result)[0].Get() : uint32(SEC_PLAYER); - } - - uint32 GetSecurity(uint32 accountId, int32 realmId) - { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM); stmt->SetData(0, accountId); stmt->SetData(1, realmId); - PreparedQueryResult result = LoginDatabase.Query(stmt); - - return (result) ? (*result)[0].Get() : uint32(SEC_PLAYER); + trans->Append(stmt); } - bool GetName(uint32 accountId, std::string& name) + // Add new security level + if (securityLevel) { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_USERNAME_BY_ID); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS); stmt->SetData(0, accountId); - PreparedQueryResult result = LoginDatabase.Query(stmt); + stmt->SetData(1, securityLevel); + stmt->SetData(2, realmId); + trans->Append(stmt); + } - if (result) + LoginDatabase.CommitTransaction(trans); +} + +void AccountMgr::LoadRBAC() +{ + ClearRBAC(); + + LOG_DEBUG("rbac", "AccountMgr::LoadRBAC"); + uint32 oldMSTime = getMSTime(); + uint32 count1 = 0; + uint32 count2 = 0; + uint32 count3 = 0; + + LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading permissions"); + QueryResult result = LoginDatabase.Query("SELECT id, name FROM rbac_permissions"); + if (!result) + { + LOG_INFO("server.loading", ">> Loaded 0 RBAC permissions. DB table `rbac_permissions` is empty."); + LOG_INFO("server.loading", " "); + return; + } + + do + { + Field* field = result->Fetch(); + uint32 id = field[0].Get(); + _permissions[id] = new rbac::RBACPermission(id, field[1].Get()); + ++count1; + } + while (result->NextRow()); + + LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading linked permissions"); + result = LoginDatabase.Query("SELECT id, linkedId FROM rbac_linked_permissions ORDER BY id ASC"); + if (!result) + { + LOG_INFO("server.loading", ">> Loaded {} RBAC permissions", count1); + LOG_INFO("server.loading", " "); + } + else + { + uint32 permissionId = 0; + rbac::RBACPermission* permission = nullptr; + + do { - name = (*result)[0].Get(); - return true; + Field* field = result->Fetch(); + uint32 newId = field[0].Get(); + if (permissionId != newId) + { + permissionId = newId; + permission = _permissions[newId]; + } + + uint32 linkedPermissionId = field[1].Get(); + if (linkedPermissionId == permissionId) + { + LOG_ERROR("sql.sql", "RBAC Permission {} has itself as linked permission. Ignored", permissionId); + continue; + } + permission->AddLinkedPermission(linkedPermissionId); + ++count2; + } + while (result->NextRow()); + + LOG_INFO("server.loading", ">> Loaded {} RBAC permissions and {} linked permissions in {} ms", count1, count2, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); + } + + LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions"); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_DEFAULT_PERMISSIONS); + stmt->SetData(0, int32(realm.Id.Realm)); + PreparedQueryResult defaultPermResult = LoginDatabase.Query(stmt); + if (!defaultPermResult) + { + LOG_INFO("server.loading", ">> Loaded 0 RBAC default permissions. DB table `rbac_default_permissions` is empty."); + LOG_INFO("server.loading", " "); + return; + } + + uint8 secId = 255; + rbac::RBACPermissionContainer* permissions = nullptr; + do + { + Field* field = defaultPermResult->Fetch(); + uint8 newId = field[0].Get(); + if (secId != newId || permissions == nullptr) + { + secId = newId; + permissions = &_defaultPermissions[secId]; } - return false; + permissions->insert(field[1].Get()); + ++count3; } + while (defaultPermResult->NextRow()); - bool CheckPassword(uint32 accountId, std::string password) - { - std::string username; + LOG_INFO("server.loading", ">> Loaded {} RBAC default permissions in {} ms", count3, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); +} - if (!GetName(accountId, username)) - return false; +rbac::RBACPermission const* AccountMgr::GetRBACPermission(uint32 permissionId) const +{ + LOG_TRACE("rbac", "AccountMgr::GetRBACPermission: {}", permissionId); + rbac::RBACPermissionsContainer::const_iterator it = _permissions.find(permissionId); + if (it != _permissions.end()) + return it->second; - Utf8ToUpperOnlyLatin(username); - Utf8ToUpperOnlyLatin(password); + return nullptr; +} - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD); - stmt->SetData(0, accountId); - if (PreparedQueryResult result = LoginDatabase.Query(stmt)) - { - Acore::Crypto::SRP6::Salt salt = (*result)[0].Get(); - Acore::Crypto::SRP6::Verifier verifier = (*result)[1].Get(); - if (Acore::Crypto::SRP6::CheckLogin(username, password, salt, verifier)) - return true; - } +rbac::RBACPermissionContainer const& AccountMgr::GetRBACDefaultPermissions(uint8 secLevel) +{ + LOG_TRACE("rbac", "AccountMgr::GetRBACDefaultPermissions: secLevel {} - size: {}", secLevel, uint32(_defaultPermissions[secLevel].size())); + return _defaultPermissions[secLevel]; +} - return false; - } +void AccountMgr::ClearRBAC() +{ + for (std::pair& permission : _permissions) + delete permission.second; - uint32 GetCharactersCount(uint32 accountId) - { - // check character count - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS); - stmt->SetData(0, accountId); - PreparedQueryResult result = CharacterDatabase.Query(stmt); + _permissions.clear(); + _defaultPermissions.clear(); +} - return (result) ? (*result)[0].Get() : 0; - } +void AccountMgr::AddPermissionForTest(uint32 permissionId, std::string const& name) +{ + if (_permissions.find(permissionId) != _permissions.end()) + return; - bool IsPlayerAccount(uint32 gmlevel) - { - return gmlevel == SEC_PLAYER; - } + _permissions[permissionId] = new rbac::RBACPermission(permissionId, name); +} - bool IsGMAccount(uint32 gmlevel) - { - return gmlevel >= SEC_GAMEMASTER; - } +void AccountMgr::AddLinkedPermissionForTest(uint32 permissionId, uint32 linkedPermissionId) +{ + auto it = _permissions.find(permissionId); + if (it != _permissions.end()) + it->second->AddLinkedPermission(linkedPermissionId); +} - bool IsAdminAccount(uint32 gmlevel) - { - return gmlevel >= SEC_ADMINISTRATOR && gmlevel <= SEC_CONSOLE; - } +void AccountMgr::AddDefaultPermissionForTest(uint8 secLevel, uint32 permissionId) +{ + _defaultPermissions[secLevel].insert(permissionId); +} - bool IsConsoleAccount(uint32 gmlevel) - { - return gmlevel == SEC_CONSOLE; - } - -} // Namespace AccountMgr +void AccountMgr::ClearPermissionsForTest() +{ + ClearRBAC(); +} diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h index c6fbbea31..d0d7ccfc9 100644 --- a/src/server/game/Accounts/AccountMgr.h +++ b/src/server/game/Accounts/AccountMgr.h @@ -1,10 +1,10 @@ /* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -18,9 +18,7 @@ #ifndef _ACCMGR_H #define _ACCMGR_H -#include "Define.h" -#include "Common.h" -#include +#include "RBAC.h" enum AccountOpResult { @@ -37,25 +35,61 @@ enum AccountOpResult #define MAX_PASS_STR 16 #define MAX_EMAIL_STR 255 -namespace AccountMgr +namespace rbac { +typedef std::map RBACPermissionsContainer; +typedef std::map RBACDefaultPermissionsContainer; +} + +class AC_GAME_API AccountMgr +{ +private: + AccountMgr(); + ~AccountMgr(); + +public: + static AccountMgr* instance(); + AccountOpResult CreateAccount(std::string username, std::string password, std::string email = ""); - AccountOpResult DeleteAccount(uint32 accountId); - AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword); - AccountOpResult ChangePassword(uint32 accountId, std::string newPassword); - AccountOpResult ChangeEmail(uint32 accountId, std::string email); - bool CheckPassword(uint32 accountId, 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); + static AccountOpResult ChangeEmail(uint32 accountId, std::string email); + static bool CheckPassword(uint32 accountId, std::string password); - uint32 GetId(std::string const& username); - uint32 GetSecurity(uint32 accountId); - uint32 GetSecurity(uint32 accountId, int32 realmId); - bool GetName(uint32 accountId, std::string& name); - uint32 GetCharactersCount(uint32 accountId); + static uint32 GetId(std::string const& username); + static uint32 GetSecurity(uint32 accountId); + static uint32 GetSecurity(uint32 accountId, int32 realmId); + static bool GetName(uint32 accountId, std::string& name); + static uint32 GetCharactersCount(uint32 accountId); - bool IsPlayerAccount(uint32 gmlevel); - bool IsGMAccount(uint32 gmlevel); - bool IsAdminAccount(uint32 gmlevel); - bool IsConsoleAccount(uint32 gmlevel); + static bool IsPlayerAccount(uint32 gmlevel); + static bool IsGMAccount(uint32 gmlevel); + static bool IsAdminAccount(uint32 gmlevel); + static bool IsConsoleAccount(uint32 gmlevel); + + static bool HasPermission(uint32 accountId, uint32 permission, uint32 realmId); + + void UpdateAccountAccess(rbac::RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId); + + void LoadRBAC(); + rbac::RBACPermission const* GetRBACPermission(uint32 permission) const; + + rbac::RBACPermissionsContainer const& GetRBACPermissionList() const { return _permissions; } + rbac::RBACPermissionContainer const& GetRBACDefaultPermissions(uint8 secLevel); + + // For unit testing - allows adding permissions without database + void AddPermissionForTest(uint32 permissionId, std::string const& name); + void AddLinkedPermissionForTest(uint32 permissionId, uint32 linkedPermissionId); + void AddDefaultPermissionForTest(uint8 secLevel, uint32 permissionId); + void ClearPermissionsForTest(); + +private: + void ClearRBAC(); + rbac::RBACPermissionsContainer _permissions; + rbac::RBACDefaultPermissionsContainer _defaultPermissions; }; +#define sAccountMgr AccountMgr::instance() + #endif diff --git a/src/server/game/Accounts/RBAC.cpp b/src/server/game/Accounts/RBAC.cpp new file mode 100644 index 000000000..99f80ef32 --- /dev/null +++ b/src/server/game/Accounts/RBAC.cpp @@ -0,0 +1,283 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "RBAC.h" +#include "AccountMgr.h" +#include "DatabaseEnv.h" +#include "Log.h" +#include "QueryResult.h" +#include + +namespace rbac +{ + +std::string GetDebugPermissionString(RBACPermissionContainer const& perms) +{ + std::string str = ""; + if (!perms.empty()) + { + std::ostringstream o; + RBACPermissionContainer::const_iterator itr = perms.begin(); + o << (*itr); + for (++itr; itr != perms.end(); ++itr) + o << ", " << uint32(*itr); + str = o.str(); + } + + return str; +} + +RBACCommandResult RBACData::GrantPermission(uint32 permissionId, int32 realmId /* = 0*/) +{ + // Check if permission Id exists + RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId); + if (!perm) + { + LOG_TRACE("rbac", "RBACData::GrantPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Permission does not exists", + GetId(), GetName(), permissionId, realmId); + return RBAC_ID_DOES_NOT_EXISTS; + } + + // Check if already added in denied list + if (HasDeniedPermission(permissionId)) + { + LOG_TRACE("rbac", "RBACData::GrantPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Permission in deny list", + GetId(), GetName(), permissionId, realmId); + return RBAC_IN_DENIED_LIST; + } + + // Already added? + if (HasGrantedPermission(permissionId)) + { + LOG_TRACE("rbac", "RBACData::GrantPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Permission already granted", + GetId(), GetName(), permissionId, realmId); + return RBAC_CANT_ADD_ALREADY_ADDED; + } + + AddGrantedPermission(permissionId); + + // Do not save to db when loading data from DB (realmId = 0) + if (realmId) + { + LOG_TRACE("rbac", "RBACData::GrantPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Ok and DB updated", + GetId(), GetName(), permissionId, realmId); + SavePermission(permissionId, true, realmId); + CalculateNewPermissions(); + } + else + LOG_TRACE("rbac", "RBACData::GrantPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Ok", + GetId(), GetName(), permissionId, realmId); + + return RBAC_OK; +} + +RBACCommandResult RBACData::DenyPermission(uint32 permissionId, int32 realmId /* = 0*/) +{ + // Check if permission Id exists + RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId); + if (!perm) + { + LOG_TRACE("rbac", "RBACData::DenyPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Permission does not exists", + GetId(), GetName(), permissionId, realmId); + return RBAC_ID_DOES_NOT_EXISTS; + } + + // Check if already added in granted list + if (HasGrantedPermission(permissionId)) + { + LOG_TRACE("rbac", "RBACData::DenyPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Permission in grant list", + GetId(), GetName(), permissionId, realmId); + return RBAC_IN_GRANTED_LIST; + } + + // Already added? + if (HasDeniedPermission(permissionId)) + { + LOG_TRACE("rbac", "RBACData::DenyPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Permission already denied", + GetId(), GetName(), permissionId, realmId); + return RBAC_CANT_ADD_ALREADY_ADDED; + } + + AddDeniedPermission(permissionId); + + // Do not save to db when loading data from DB (realmId = 0) + if (realmId) + { + LOG_TRACE("rbac", "RBACData::DenyPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Ok and DB updated", + GetId(), GetName(), permissionId, realmId); + SavePermission(permissionId, false, realmId); + CalculateNewPermissions(); + } + else + LOG_TRACE("rbac", "RBACData::DenyPermission [Id: {} Name: {}] (Permission {}, RealmId {}). Ok", + GetId(), GetName(), permissionId, realmId); + + return RBAC_OK; +} + +void RBACData::SavePermission(uint32 permission, bool granted, int32 realmId) +{ + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION); + stmt->SetData(0, GetId()); + stmt->SetData(1, permission); + stmt->SetData(2, granted); + stmt->SetData(3, realmId); + LoginDatabase.Execute(stmt); +} + +RBACCommandResult RBACData::RevokePermission(uint32 permissionId, int32 realmId /* = 0*/) +{ + // Check if it's present in any list + if (!HasGrantedPermission(permissionId) && !HasDeniedPermission(permissionId)) + { + LOG_TRACE("rbac", "RBACData::RevokePermission [Id: {} Name: {}] (Permission {}, RealmId {}). Not granted or revoked", + GetId(), GetName(), permissionId, realmId); + return RBAC_CANT_REVOKE_NOT_IN_LIST; + } + + RemoveGrantedPermission(permissionId); + RemoveDeniedPermission(permissionId); + + // Do not save to db when loading data from DB (realmId = 0) + if (realmId) + { + LOG_TRACE("rbac", "RBACData::RevokePermission [Id: {} Name: {}] (Permission {}, RealmId {}). Ok and DB updated", + GetId(), GetName(), permissionId, realmId); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION); + stmt->SetData(0, GetId()); + stmt->SetData(1, permissionId); + stmt->SetData(2, realmId); + LoginDatabase.Execute(stmt); + + CalculateNewPermissions(); + } + else + LOG_TRACE("rbac", "RBACData::RevokePermission [Id: {} Name: {}] (Permission {}, RealmId {}). Ok", + GetId(), GetName(), permissionId, realmId); + + return RBAC_OK; +} + +void RBACData::LoadFromDB() +{ + ClearData(); + + LOG_DEBUG("rbac", "RBACData::LoadFromDB [Id: {} Name: {}]: Loading permissions", GetId(), GetName()); + // Load account permissions (granted and denied) that affect current realm + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS); + stmt->SetData(0, GetId()); + stmt->SetData(1, GetRealmId()); + + LoadFromDBCallback(LoginDatabase.Query(stmt)); +} + +QueryCallback RBACData::LoadFromDBAsync() +{ + ClearData(); + + LOG_DEBUG("rbac", "RBACData::LoadFromDB [Id: {} Name: {}]: Loading permissions", GetId(), GetName()); + // Load account permissions (granted and denied) that affect current realm + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS); + stmt->SetData(0, GetId()); + stmt->SetData(1, GetRealmId()); + + return LoginDatabase.AsyncQuery(stmt); +} + +void RBACData::LoadFromDBCallback(PreparedQueryResult result) +{ + if (result) + { + do + { + Field* fields = result->Fetch(); + if (fields[1].Get()) + GrantPermission(fields[0].Get()); + else + DenyPermission(fields[0].Get()); + } while (result->NextRow()); + } + + // Add default permissions + RBACPermissionContainer const& permissions = sAccountMgr->GetRBACDefaultPermissions(_secLevel); + for (uint32 permission : permissions) + GrantPermission(permission); + + // Force calculation of permissions + CalculateNewPermissions(); +} + +void RBACData::CalculateNewPermissions() +{ + LOG_TRACE("rbac", "RBACData::CalculateNewPermissions [Id: {} Name: {}]", GetId(), GetName()); + + // Get the list of granted permissions + _globalPerms = GetGrantedPermissions(); + ExpandPermissions(_globalPerms); + RBACPermissionContainer revoked = GetDeniedPermissions(); + ExpandPermissions(revoked); + RemovePermissions(_globalPerms, revoked); +} + +void RBACData::AddPermissions(RBACPermissionContainer const& permsFrom, RBACPermissionContainer& permsTo) +{ + for (uint32 permission : permsFrom) + permsTo.insert(permission); +} + +void RBACData::RemovePermissions(RBACPermissionContainer& permsFrom, RBACPermissionContainer const& permsToRemove) +{ + for (uint32 permission: permsToRemove) + permsFrom.erase(permission); +} + +void RBACData::ExpandPermissions(RBACPermissionContainer& permissions) +{ + RBACPermissionContainer toCheck = permissions; + permissions.clear(); + + while (!toCheck.empty()) + { + // remove the permission from original list + uint32 permissionId = *toCheck.begin(); + toCheck.erase(toCheck.begin()); + + RBACPermission const* permission = sAccountMgr->GetRBACPermission(permissionId); + if (!permission) + continue; + + // insert into the final list (expanded list) + permissions.insert(permissionId); + + // add all linked permissions (that are not already expanded) to the list of permissions to be checked + RBACPermissionContainer const& linkedPerms = permission->GetLinkedPermissions(); + for (uint32 linkedPerm : linkedPerms) + if (permissions.find(linkedPerm) == permissions.end()) + toCheck.insert(linkedPerm); + } + + LOG_DEBUG("rbac", "RBACData::ExpandPermissions: Expanded: {}", GetDebugPermissionString(permissions)); +} + +void RBACData::ClearData() +{ + _grantedPerms.clear(); + _deniedPerms.clear(); + _globalPerms.clear(); +} + +} diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h new file mode 100644 index 000000000..c4af7947e --- /dev/null +++ b/src/server/game/Accounts/RBAC.h @@ -0,0 +1,895 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +/** +* @file RBAC.h +* @brief Role Based Access Control related classes definition +* +* This file contains all the classes and enums used to implement +* Role Based Access Control +* +* RBAC Rules: +* - Permission: Defines an authorization to perform certain operation. +* - Role: Set of permissions. +* - An Account can have multiple roles and permissions. +* - Account Roles and Permissions can be granted, denied or revoked +* - Grant: Assignment of the object (role/permission) and allow it +* - Deny: Assignment of the object (role/permission) and deny it +* - Revoke: Removal of the object (role/permission) no matter if it was granted or denied +* - Global Permissions are computed as: +* Role Grants + User Grants - Role Denies - User Denies +* - Roles and Permissions can be assigned by realm +*/ + +#ifndef _RBAC_H +#define _RBAC_H + +#include "Define.h" +#include "DatabaseEnvFwd.h" +#include +#include +#include + +namespace rbac +{ + +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_IGNORE_IDLE_CONNECTION = 7, + RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS = 8, + RBAC_PERM_CANNOT_EARN_REALM_FIRST_ACHIEVEMENTS = 9, + // 10 not on 3.3.5a (character templates) + RBAC_PERM_LOG_GM_TRADE = 11, + // 12 not on 3.3.5a (demon hunter) + 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_DEATH_KNIGHT = 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_TWO_SIDE_WHO_LIST = 28, + RBAC_PERM_TWO_SIDE_ADD_FRIEND = 29, + 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_WHO_SEE_ALL_SEC_LEVELS = 35, + 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_ALLOW_GM_FRIEND = 40, + 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_CAN_IGNORE_LOWER_SECURITY_CHECK = 47, + RBAC_PERM_COMMANDS_PINFO_CHECK_PERSONAL_DATA = 48, + RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE = 49, + RBAC_PERM_MAY_CHECK_OWN_EMAIL = 50, + RBAC_PERM_ALLOW_TWO_SIDE_TRADE = 51, + RBAC_PERM_NO_BATTLEGROUND_DESERTER_DEBUFF = 52, + RBAC_PERM_CAN_AFK_ON_BATTLEGROUND = 53, + + // Roles (Permissions with delegated permissions) use 199 and descending + RBAC_ROLE_ADMINISTRATOR = 196, + RBAC_ROLE_GAMEMASTER = 197, + RBAC_ROLE_MODERATOR = 198, + RBAC_ROLE_PLAYER = 199, + + // Command permissions start at 200 + RBAC_PERM_COMMAND_RBAC = 200, + RBAC_PERM_COMMAND_RBAC_ACC = 201, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_LIST = 202, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_GRANT = 203, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY = 204, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE = 205, + RBAC_PERM_COMMAND_RBAC_LIST = 206, + // 207-216 not on 3.3.5a (bnet) + RBAC_PERM_COMMAND_ACCOUNT = 217, + RBAC_PERM_COMMAND_ACCOUNT_ADDON = 218, + RBAC_PERM_COMMAND_ACCOUNT_CREATE = 219, + RBAC_PERM_COMMAND_ACCOUNT_DELETE = 220, + RBAC_PERM_COMMAND_ACCOUNT_LOCK = 221, + RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY = 222, + RBAC_PERM_COMMAND_ACCOUNT_LOCK_IP = 223, + RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST = 224, + RBAC_PERM_COMMAND_ACCOUNT_PASSWORD = 225, + RBAC_PERM_COMMAND_ACCOUNT_SET = 226, + RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON = 227, + RBAC_PERM_COMMAND_ACCOUNT_SET_SECLEVEL = 228, + RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD = 229, + RBAC_PERM_COMMAND_ACHIEVEMENT_ADD = 231, + RBAC_PERM_COMMAND_ACHIEVEMENT_CHECKALL = 232, + RBAC_PERM_COMMAND_ARENA_CAPTAIN = 233, + RBAC_PERM_COMMAND_ARENA_CREATE = 234, + RBAC_PERM_COMMAND_ARENA_DISBAND = 235, + RBAC_PERM_COMMAND_ARENA_INFO = 236, + RBAC_PERM_COMMAND_ARENA_LOOKUP = 237, + RBAC_PERM_COMMAND_ARENA_RENAME = 238, + RBAC_PERM_COMMAND_BAN_ACCOUNT = 240, + RBAC_PERM_COMMAND_BAN_CHARACTER = 241, + RBAC_PERM_COMMAND_BAN_IP = 242, + RBAC_PERM_COMMAND_BAN_PLAYERACCOUNT = 243, + RBAC_PERM_COMMAND_BANINFO_ACCOUNT = 245, + RBAC_PERM_COMMAND_BANINFO_CHARACTER = 246, + RBAC_PERM_COMMAND_BANINFO_IP = 247, + RBAC_PERM_COMMAND_BANLIST_ACCOUNT = 249, + RBAC_PERM_COMMAND_BANLIST_CHARACTER = 250, + RBAC_PERM_COMMAND_BANLIST_IP = 251, + RBAC_PERM_COMMAND_UNBAN_ACCOUNT = 253, + RBAC_PERM_COMMAND_UNBAN_CHARACTER = 254, + RBAC_PERM_COMMAND_UNBAN_IP = 255, + RBAC_PERM_COMMAND_UNBAN_PLAYERACCOUNT = 256, + RBAC_PERM_COMMAND_BF_START = 258, + RBAC_PERM_COMMAND_BF_STOP = 259, + RBAC_PERM_COMMAND_BF_SWITCH = 260, + RBAC_PERM_COMMAND_BF_TIMER = 261, + RBAC_PERM_COMMAND_BF_ENABLE = 262, + RBAC_PERM_COMMAND_ACCOUNT_EMAIL = 263, + RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_EMAIL = 265, + RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_REGMAIL = 266, + RBAC_PERM_COMMAND_CAST = 267, + RBAC_PERM_COMMAND_CAST_BACK = 268, + RBAC_PERM_COMMAND_CAST_DIST = 269, + RBAC_PERM_COMMAND_CAST_SELF = 270, + RBAC_PERM_COMMAND_CAST_TARGET = 271, + RBAC_PERM_COMMAND_CAST_DEST = 272, + RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE = 274, + RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION = 275, + RBAC_PERM_COMMAND_CHARACTER_CHANGERACE = 276, + RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE = 278, + RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST = 279, + RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE = 280, + RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD = 281, + RBAC_PERM_COMMAND_CHARACTER_ERASE = 282, + RBAC_PERM_COMMAND_CHARACTER_LEVEL = 283, + RBAC_PERM_COMMAND_CHARACTER_RENAME = 284, + RBAC_PERM_COMMAND_CHARACTER_REPUTATION = 285, + RBAC_PERM_COMMAND_CHARACTER_TITLES = 286, + RBAC_PERM_COMMAND_LEVELUP = 287, + RBAC_PERM_COMMAND_PDUMP_LOAD = 289, + RBAC_PERM_COMMAND_PDUMP_WRITE = 290, + RBAC_PERM_COMMAND_CHEAT_CASTTIME = 292, + RBAC_PERM_COMMAND_CHEAT_COOLDOWN = 293, + RBAC_PERM_COMMAND_CHEAT_EXPLORE = 294, + RBAC_PERM_COMMAND_CHEAT_GOD = 295, + RBAC_PERM_COMMAND_CHEAT_POWER = 296, + RBAC_PERM_COMMAND_CHEAT_STATUS = 297, + RBAC_PERM_COMMAND_CHEAT_TAXI = 298, + RBAC_PERM_COMMAND_CHEAT_WATERWALK = 299, + RBAC_PERM_COMMAND_DEBUG = 300, + // 301-342 previously used, do not reuse + RBAC_PERM_COMMAND_DESERTER_BG_ADD = 343, + RBAC_PERM_COMMAND_DESERTER_BG_REMOVE = 344, + RBAC_PERM_COMMAND_DESERTER_INSTANCE_ADD = 346, + RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE = 347, + RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA = 350, + RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND = 351, + RBAC_PERM_COMMAND_DISABLE_ADD_MAP = 352, + RBAC_PERM_COMMAND_DISABLE_ADD_MMAP = 353, + RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP = 354, + RBAC_PERM_COMMAND_DISABLE_ADD_QUEST = 355, + RBAC_PERM_COMMAND_DISABLE_ADD_SPELL = 356, + RBAC_PERM_COMMAND_DISABLE_ADD_VMAP = 357, + RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA = 359, + RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND = 360, + RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP = 361, + RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP = 362, + RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP = 363, + RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST = 364, + RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL = 365, + RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP = 366, + RBAC_PERM_COMMAND_EVENT_INFO = 367, + RBAC_PERM_COMMAND_EVENT_ACTIVELIST = 368, + RBAC_PERM_COMMAND_EVENT_START = 369, + RBAC_PERM_COMMAND_EVENT_STOP = 370, + RBAC_PERM_COMMAND_GM = 371, + RBAC_PERM_COMMAND_GM_CHAT = 372, + RBAC_PERM_COMMAND_GM_FLY = 373, + RBAC_PERM_COMMAND_GM_INGAME = 374, + RBAC_PERM_COMMAND_GM_LIST = 375, + RBAC_PERM_COMMAND_GM_VISIBLE = 376, + RBAC_PERM_COMMAND_GO = 377, + RBAC_PERM_COMMAND_GOBJECT_ACTIVATE = 388, + RBAC_PERM_COMMAND_GOBJECT_ADD = 389, + RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP = 390, + RBAC_PERM_COMMAND_GOBJECT_DELETE = 391, + RBAC_PERM_COMMAND_GOBJECT_INFO = 392, + RBAC_PERM_COMMAND_GOBJECT_MOVE = 393, + RBAC_PERM_COMMAND_GOBJECT_NEAR = 394, + RBAC_PERM_COMMAND_GOBJECT_SET_PHASE = 396, + RBAC_PERM_COMMAND_GOBJECT_SET_STATE = 397, + RBAC_PERM_COMMAND_GOBJECT_TARGET = 398, + RBAC_PERM_COMMAND_GOBJECT_TURN = 399, + RBAC_PERM_COMMAND_GUILD = 401, + RBAC_PERM_COMMAND_GUILD_CREATE = 402, + RBAC_PERM_COMMAND_GUILD_DELETE = 403, + RBAC_PERM_COMMAND_GUILD_INVITE = 404, + RBAC_PERM_COMMAND_GUILD_UNINVITE = 405, + RBAC_PERM_COMMAND_GUILD_RANK = 406, + RBAC_PERM_COMMAND_GUILD_RENAME = 407, + RBAC_PERM_COMMAND_HONOR_ADD = 409, + RBAC_PERM_COMMAND_HONOR_ADD_KILL = 410, + RBAC_PERM_COMMAND_HONOR_UPDATE = 411, + RBAC_PERM_COMMAND_INSTANCE_LISTBINDS = 413, + RBAC_PERM_COMMAND_INSTANCE_UNBIND = 414, + RBAC_PERM_COMMAND_INSTANCE_STATS = 415, + RBAC_PERM_COMMAND_INSTANCE_SAVEDATA = 416, + RBAC_PERM_COMMAND_LEARN = 417, + RBAC_PERM_COMMAND_LEARN_ALL_MY = 419, + RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS = 420, + RBAC_PERM_COMMAND_LEARN_MY_PETTALENTS = 421, + RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS = 422, + RBAC_PERM_COMMAND_LEARN_ALL_TALENTS = 423, + RBAC_PERM_COMMAND_LEARN_ALL_GM = 424, + RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS = 425, + RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT = 426, + RBAC_PERM_COMMAND_LEARN_ALL_LANG = 427, + RBAC_PERM_COMMAND_LEARN_ALL_RECIPES = 428, + RBAC_PERM_COMMAND_UNLEARN = 429, + RBAC_PERM_COMMAND_LFG_PLAYER = 431, + RBAC_PERM_COMMAND_LFG_GROUP = 432, + RBAC_PERM_COMMAND_LFG_QUEUE = 433, + RBAC_PERM_COMMAND_LFG_CLEAN = 434, + RBAC_PERM_COMMAND_LFG_OPTIONS = 435, + RBAC_PERM_COMMAND_LFG_COOLDOWN = 436, + RBAC_PERM_COMMAND_LIST_CREATURE = 437, + RBAC_PERM_COMMAND_LIST_ITEM = 438, + RBAC_PERM_COMMAND_LIST_OBJECT = 439, + RBAC_PERM_COMMAND_LIST_AURAS = 440, + RBAC_PERM_COMMAND_LIST_MAIL = 441, + RBAC_PERM_COMMAND_LOOKUP = 442, + RBAC_PERM_COMMAND_LOOKUP_AREA = 443, + RBAC_PERM_COMMAND_LOOKUP_CREATURE = 444, + RBAC_PERM_COMMAND_LOOKUP_EVENT = 445, + RBAC_PERM_COMMAND_LOOKUP_FACTION = 446, + RBAC_PERM_COMMAND_LOOKUP_ITEM = 447, + RBAC_PERM_COMMAND_LOOKUP_ITEMSET = 448, + RBAC_PERM_COMMAND_LOOKUP_OBJECT = 449, + RBAC_PERM_COMMAND_LOOKUP_QUEST = 450, + RBAC_PERM_COMMAND_LOOKUP_PLAYER = 451, + RBAC_PERM_COMMAND_LOOKUP_PLAYER_IP = 452, + RBAC_PERM_COMMAND_LOOKUP_PLAYER_ACCOUNT = 453, + RBAC_PERM_COMMAND_LOOKUP_PLAYER_EMAIL = 454, + RBAC_PERM_COMMAND_LOOKUP_SKILL = 455, + RBAC_PERM_COMMAND_LOOKUP_SPELL = 456, + RBAC_PERM_COMMAND_LOOKUP_SPELL_ID = 457, + RBAC_PERM_COMMAND_LOOKUP_TAXINODE = 458, + RBAC_PERM_COMMAND_LOOKUP_TELE = 459, + RBAC_PERM_COMMAND_LOOKUP_TITLE = 460, + RBAC_PERM_COMMAND_LOOKUP_MAP = 461, + RBAC_PERM_COMMAND_ANNOUNCE = 462, + RBAC_PERM_COMMAND_CHANNEL = 463, + RBAC_PERM_COMMAND_CHANNEL_SET = 464, + RBAC_PERM_COMMAND_CHANNEL_SET_OWNERSHIP = 465, + RBAC_PERM_COMMAND_GMANNOUNCE = 466, + RBAC_PERM_COMMAND_GMNAMEANNOUNCE = 467, + RBAC_PERM_COMMAND_GMNOTIFY = 468, + RBAC_PERM_COMMAND_NAMEANNOUNCE = 469, + RBAC_PERM_COMMAND_NOTIFY = 470, + RBAC_PERM_COMMAND_WHISPERS = 471, + RBAC_PERM_COMMAND_GROUP = 472, + RBAC_PERM_COMMAND_GROUP_LEADER = 473, + RBAC_PERM_COMMAND_GROUP_DISBAND = 474, + RBAC_PERM_COMMAND_GROUP_REMOVE = 475, + RBAC_PERM_COMMAND_GROUP_JOIN = 476, + RBAC_PERM_COMMAND_GROUP_LIST = 477, + RBAC_PERM_COMMAND_GROUP_SUMMON = 478, + RBAC_PERM_COMMAND_PET = 479, + RBAC_PERM_COMMAND_PET_CREATE = 480, + RBAC_PERM_COMMAND_PET_LEARN = 481, + RBAC_PERM_COMMAND_PET_UNLEARN = 482, + RBAC_PERM_COMMAND_SEND = 483, + RBAC_PERM_COMMAND_SEND_ITEMS = 484, + RBAC_PERM_COMMAND_SEND_MAIL = 485, + RBAC_PERM_COMMAND_SEND_MESSAGE = 486, + RBAC_PERM_COMMAND_SEND_MONEY = 487, + RBAC_PERM_COMMAND_ADDITEM = 488, + RBAC_PERM_COMMAND_ADDITEMSET = 489, + RBAC_PERM_COMMAND_APPEAR = 490, + RBAC_PERM_COMMAND_AURA = 491, + RBAC_PERM_COMMAND_BANK = 492, + RBAC_PERM_COMMAND_BINDSIGHT = 493, + RBAC_PERM_COMMAND_COMBATSTOP = 494, + RBAC_PERM_COMMAND_COMETOME = 495, + RBAC_PERM_COMMAND_COMMANDS = 496, + RBAC_PERM_COMMAND_COOLDOWN = 497, + RBAC_PERM_COMMAND_DAMAGE = 498, + RBAC_PERM_COMMAND_DEV = 499, + RBAC_PERM_COMMAND_DIE = 500, + RBAC_PERM_COMMAND_DISMOUNT = 501, + RBAC_PERM_COMMAND_DISTANCE = 502, + RBAC_PERM_COMMAND_FLUSHARENAPOINTS = 503, + RBAC_PERM_COMMAND_FREEZE = 504, + RBAC_PERM_COMMAND_GPS = 505, + RBAC_PERM_COMMAND_GUID = 506, + RBAC_PERM_COMMAND_HELP = 507, + RBAC_PERM_COMMAND_HIDEAREA = 508, + RBAC_PERM_COMMAND_ITEMMOVE = 509, + RBAC_PERM_COMMAND_KICK = 510, + RBAC_PERM_COMMAND_LINKGRAVE = 511, + RBAC_PERM_COMMAND_LISTFREEZE = 512, + RBAC_PERM_COMMAND_MAXSKILL = 513, + RBAC_PERM_COMMAND_MOVEGENS = 514, + RBAC_PERM_COMMAND_MUTE = 515, + RBAC_PERM_COMMAND_NEARGRAVE = 516, + RBAC_PERM_COMMAND_PINFO = 517, + RBAC_PERM_COMMAND_PLAYALL = 518, + RBAC_PERM_COMMAND_POSSESS = 519, + RBAC_PERM_COMMAND_RECALL = 520, + RBAC_PERM_COMMAND_REPAIRITEMS = 521, + RBAC_PERM_COMMAND_RESPAWN = 522, + RBAC_PERM_COMMAND_REVIVE = 523, + RBAC_PERM_COMMAND_SAVEALL = 524, + RBAC_PERM_COMMAND_SAVE = 525, + RBAC_PERM_COMMAND_SETSKILL = 526, + RBAC_PERM_COMMAND_SHOWAREA = 527, + RBAC_PERM_COMMAND_SUMMON = 528, + RBAC_PERM_COMMAND_UNAURA = 529, + RBAC_PERM_COMMAND_UNBINDSIGHT = 530, + RBAC_PERM_COMMAND_UNFREEZE = 531, + RBAC_PERM_COMMAND_UNMUTE = 532, + RBAC_PERM_COMMAND_UNPOSSESS = 533, + RBAC_PERM_COMMAND_UNSTUCK = 534, + RBAC_PERM_COMMAND_WCHANGE = 535, + RBAC_PERM_COMMAND_MMAP = 536, + RBAC_PERM_COMMAND_MMAP_LOADEDTILES = 537, + RBAC_PERM_COMMAND_MMAP_LOC = 538, + RBAC_PERM_COMMAND_MMAP_PATH = 539, + RBAC_PERM_COMMAND_MMAP_STATS = 540, + RBAC_PERM_COMMAND_MMAP_TESTAREA = 541, + RBAC_PERM_COMMAND_MORPH = 542, + RBAC_PERM_COMMAND_DEMORPH = 543, + RBAC_PERM_COMMAND_MODIFY = 544, + RBAC_PERM_COMMAND_MODIFY_ARENAPOINTS = 545, + RBAC_PERM_COMMAND_MODIFY_BIT = 546, + RBAC_PERM_COMMAND_MODIFY_DRUNK = 547, + RBAC_PERM_COMMAND_MODIFY_ENERGY = 548, + RBAC_PERM_COMMAND_MODIFY_FACTION = 549, + RBAC_PERM_COMMAND_MODIFY_GENDER = 550, + RBAC_PERM_COMMAND_MODIFY_HONOR = 551, + RBAC_PERM_COMMAND_MODIFY_HP = 552, + RBAC_PERM_COMMAND_MODIFY_MANA = 553, + RBAC_PERM_COMMAND_MODIFY_MONEY = 554, + RBAC_PERM_COMMAND_MODIFY_MOUNT = 555, + RBAC_PERM_COMMAND_MODIFY_PHASE = 556, + RBAC_PERM_COMMAND_MODIFY_RAGE = 557, + RBAC_PERM_COMMAND_MODIFY_REPUTATION = 558, + RBAC_PERM_COMMAND_MODIFY_RUNICPOWER = 559, + RBAC_PERM_COMMAND_MODIFY_SCALE = 560, + RBAC_PERM_COMMAND_MODIFY_SPEED = 561, + RBAC_PERM_COMMAND_MODIFY_SPEED_ALL = 562, + RBAC_PERM_COMMAND_MODIFY_SPEED_BACKWALK = 563, + RBAC_PERM_COMMAND_MODIFY_SPEED_FLY = 564, + RBAC_PERM_COMMAND_MODIFY_SPEED_WALK = 565, + RBAC_PERM_COMMAND_MODIFY_SPEED_SWIM = 566, + RBAC_PERM_COMMAND_MODIFY_SPELL = 567, + RBAC_PERM_COMMAND_MODIFY_STANDSTATE = 568, + RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS = 569, + RBAC_PERM_COMMAND_NPC_ADD = 571, + RBAC_PERM_COMMAND_NPC_ADD_FORMATION = 572, + RBAC_PERM_COMMAND_NPC_ADD_ITEM = 573, + RBAC_PERM_COMMAND_NPC_ADD_MOVE = 574, + RBAC_PERM_COMMAND_NPC_ADD_TEMP = 575, + RBAC_PERM_COMMAND_NPC_DELETE = 576, + RBAC_PERM_COMMAND_NPC_DELETE_ITEM = 577, + RBAC_PERM_COMMAND_NPC_FOLLOW = 578, + RBAC_PERM_COMMAND_NPC_FOLLOW_STOP = 579, + RBAC_PERM_COMMAND_NPC_SET = 580, + RBAC_PERM_COMMAND_NPC_SET_ALLOWMOVE = 581, + RBAC_PERM_COMMAND_NPC_SET_ENTRY = 582, + RBAC_PERM_COMMAND_NPC_SET_FACTIONID = 583, + RBAC_PERM_COMMAND_NPC_SET_FLAG = 584, + RBAC_PERM_COMMAND_NPC_SET_LEVEL = 585, + RBAC_PERM_COMMAND_NPC_SET_LINK = 586, + RBAC_PERM_COMMAND_NPC_SET_MODEL = 587, + RBAC_PERM_COMMAND_NPC_SET_MOVETYPE = 588, + RBAC_PERM_COMMAND_NPC_SET_PHASE = 589, + RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST = 590, + RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME = 591, + RBAC_PERM_COMMAND_NPC_SET_DATA = 592, + RBAC_PERM_COMMAND_NPC_INFO = 593, + RBAC_PERM_COMMAND_NPC_NEAR = 594, + RBAC_PERM_COMMAND_NPC_MOVE = 595, + RBAC_PERM_COMMAND_NPC_PLAYEMOTE = 596, + RBAC_PERM_COMMAND_NPC_SAY = 597, + RBAC_PERM_COMMAND_NPC_TEXTEMOTE = 598, + RBAC_PERM_COMMAND_NPC_WHISPER = 599, + RBAC_PERM_COMMAND_NPC_YELL = 600, + RBAC_PERM_COMMAND_NPC_TAME = 601, + RBAC_PERM_COMMAND_QUEST = 602, + RBAC_PERM_COMMAND_QUEST_ADD = 603, + RBAC_PERM_COMMAND_QUEST_COMPLETE = 604, + RBAC_PERM_COMMAND_QUEST_REMOVE = 605, + RBAC_PERM_COMMAND_QUEST_REWARD = 606, + RBAC_PERM_COMMAND_RELOAD = 607, + RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT = 608, + RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_CRITERIA_DATA = 609, + RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD = 610, + RBAC_PERM_COMMAND_RELOAD_ALL = 611, + RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT = 612, + RBAC_PERM_COMMAND_RELOAD_ALL_AREA = 613, + RBAC_PERM_COMMAND_RELOAD_BROADCAST_TEXT = 614, + RBAC_PERM_COMMAND_RELOAD_ALL_GOSSIP = 615, + RBAC_PERM_COMMAND_RELOAD_ALL_ITEM = 616, + RBAC_PERM_COMMAND_RELOAD_ALL_LOCALES = 617, + RBAC_PERM_COMMAND_RELOAD_ALL_LOOT = 618, + RBAC_PERM_COMMAND_RELOAD_ALL_NPC = 619, + RBAC_PERM_COMMAND_RELOAD_ALL_QUEST = 620, + RBAC_PERM_COMMAND_RELOAD_ALL_SCRIPTS = 621, + RBAC_PERM_COMMAND_RELOAD_ALL_SPELL = 622, + RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_INVOLVEDRELATION = 623, + RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TAVERN = 624, + RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TELEPORT = 625, + RBAC_PERM_COMMAND_RELOAD_AUCTIONS = 626, + RBAC_PERM_COMMAND_RELOAD_AUTOBROADCAST = 627, + RBAC_PERM_COMMAND_RELOAD_CONDITIONS = 629, + RBAC_PERM_COMMAND_RELOAD_CONFIG = 630, + RBAC_PERM_COMMAND_RELOAD_BATTLEGROUND_TEMPLATE = 631, + RBAC_PERM_COMMAND_MUTEHISTORY = 632, + RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN = 633, + RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE = 634, + RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION = 635, + RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER = 636, + RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER = 637, + RBAC_PERM_COMMAND_RELOAD_CREATURE_SUMMON_GROUPS = 638, + RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE = 639, + RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT = 640, + RBAC_PERM_COMMAND_RELOAD_DISABLES = 641, + RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE = 642, + RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS = 643, + RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE = 644, + RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE = 645, + RBAC_PERM_COMMAND_RELOAD_GAME_TELE = 646, + RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER = 647, + RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE = 648, + RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTSTARTER = 649, + RBAC_PERM_COMMAND_RELOAD_GM_TICKETS = 650, + RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU = 651, + RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION = 652, + RBAC_PERM_COMMAND_RELOAD_ITEM_ENCHANTMENT_TEMPLATE = 653, + RBAC_PERM_COMMAND_RELOAD_ITEM_LOOT_TEMPLATE = 654, + RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAMES = 655, + RBAC_PERM_COMMAND_RELOAD_LFG_DUNGEON_REWARDS = 656, + RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD_LOCALE = 657, + RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE_LOCALE = 658, + RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT_LOCALE = 659, + RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_TEMPLATE_LOCALE = 660, + RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION_LOCALE = 661, + RBAC_PERM_COMMAND_RELOAD_ITEM_TEMPLATE_LOCALE = 662, + RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAME_LOCALE = 663, + RBAC_PERM_COMMAND_RELOAD_NPC_TEXT_LOCALE = 664, + RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT_LOCALE = 665, + RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST_LOCALE = 666, + RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE_LOCALE = 667, + RBAC_PERM_COMMAND_RELOAD_MAIL_LEVEL_REWARD = 668, + RBAC_PERM_COMMAND_RELOAD_MAIL_LOOT_TEMPLATE = 669, + RBAC_PERM_COMMAND_RELOAD_MILLING_LOOT_TEMPLATE = 670, + RBAC_PERM_COMMAND_RELOAD_NPC_SPELLCLICK_SPELLS = 671, + RBAC_PERM_COMMAND_RELOAD_TRAINER = 672, + RBAC_PERM_COMMAND_RELOAD_NPC_VENDOR = 673, + RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT = 674, + RBAC_PERM_COMMAND_RELOAD_PICKPOCKETING_LOOT_TEMPLATE = 675, + RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST = 676, + RBAC_PERM_COMMAND_RELOAD_PROSPECTING_LOOT_TEMPLATE = 677, + RBAC_PERM_COMMAND_RELOAD_QUEST_POI = 678, + RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE = 679, + RBAC_PERM_COMMAND_RELOAD_RBAC = 680, + RBAC_PERM_COMMAND_RELOAD_REFERENCE_LOOT_TEMPLATE = 681, + RBAC_PERM_COMMAND_RELOAD_RESERVED_NAME = 682, + RBAC_PERM_COMMAND_RELOAD_REPUTATION_REWARD_RATE = 683, + RBAC_PERM_COMMAND_RELOAD_SPILLOVER_TEMPLATE = 684, + RBAC_PERM_COMMAND_RELOAD_SKILL_DISCOVERY_TEMPLATE = 685, + RBAC_PERM_COMMAND_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE = 686, + RBAC_PERM_COMMAND_RELOAD_SKILL_FISHING_BASE_LEVEL = 687, + RBAC_PERM_COMMAND_RELOAD_SKINNING_LOOT_TEMPLATE = 688, + RBAC_PERM_COMMAND_RELOAD_SMART_SCRIPTS = 689, + RBAC_PERM_COMMAND_RELOAD_SPELL_REQUIRED = 690, + RBAC_PERM_COMMAND_RELOAD_SPELL_AREA = 691, + RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA = 692, + RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP = 693, + RBAC_PERM_COMMAND_RELOAD_SPELL_LEARN_SPELL = 694, + RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE = 695, + RBAC_PERM_COMMAND_RELOAD_SPELL_LINKED_SPELL = 696, + RBAC_PERM_COMMAND_RELOAD_SPELL_PET_AURAS = 697, + RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT = 698, + RBAC_PERM_COMMAND_RELOAD_SPELL_PROC = 699, + RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION = 701, + RBAC_PERM_COMMAND_RELOAD_SPELL_THREATS = 702, + RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP_STACK_RULES = 703, + RBAC_PERM_COMMAND_RELOAD_ACORE_STRING = 704, + RBAC_PERM_COMMAND_RELOAD_WAYPOINT_SCRIPTS = 706, + RBAC_PERM_COMMAND_RELOAD_WAYPOINT_DATA = 707, + RBAC_PERM_COMMAND_RELOAD_VEHICLE_ACCESSORY = 708, + RBAC_PERM_COMMAND_RELOAD_VEHICLE_TEMPLATE_ACCESSORY = 709, + RBAC_PERM_COMMAND_RESET = 710, + RBAC_PERM_COMMAND_RESET_ACHIEVEMENTS = 711, + RBAC_PERM_COMMAND_RESET_HONOR = 712, + RBAC_PERM_COMMAND_RESET_LEVEL = 713, + RBAC_PERM_COMMAND_RESET_SPELLS = 714, + RBAC_PERM_COMMAND_RESET_STATS = 715, + RBAC_PERM_COMMAND_RESET_TALENTS = 716, + RBAC_PERM_COMMAND_RESET_ALL = 717, + RBAC_PERM_COMMAND_SERVER = 718, + RBAC_PERM_COMMAND_SERVER_CORPSES = 719, + RBAC_PERM_COMMAND_SERVER_EXIT = 720, + RBAC_PERM_COMMAND_SERVER_IDLERESTART = 721, + RBAC_PERM_COMMAND_SERVER_IDLERESTART_CANCEL = 722, + RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN = 723, + RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN_CANCEL = 724, + RBAC_PERM_COMMAND_SERVER_INFO = 725, + RBAC_PERM_COMMAND_SERVER_PLIMIT = 726, + RBAC_PERM_COMMAND_SERVER_RESTART = 727, + RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL = 728, + RBAC_PERM_COMMAND_SERVER_SET = 729, + RBAC_PERM_COMMAND_SERVER_SET_CLOSED = 730, + RBAC_PERM_COMMAND_SERVER_SET_DIFFTIME = 731, + RBAC_PERM_COMMAND_SERVER_SET_LOGLEVEL = 732, + RBAC_PERM_COMMAND_SERVER_SET_MOTD = 733, + RBAC_PERM_COMMAND_SERVER_SHUTDOWN = 734, + RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL = 735, + RBAC_PERM_COMMAND_SERVER_MOTD = 736, + RBAC_PERM_COMMAND_TELE = 737, + RBAC_PERM_COMMAND_TELE_ADD = 738, + RBAC_PERM_COMMAND_TELE_DEL = 739, + RBAC_PERM_COMMAND_TELE_NAME = 740, + RBAC_PERM_COMMAND_TELE_GROUP = 741, + RBAC_PERM_COMMAND_TICKET = 742, + RBAC_PERM_COMMAND_TICKET_ASSIGN = 743, + RBAC_PERM_COMMAND_TICKET_CLOSE = 744, + RBAC_PERM_COMMAND_TICKET_CLOSEDLIST = 745, + RBAC_PERM_COMMAND_TICKET_COMMENT = 746, + RBAC_PERM_COMMAND_TICKET_COMPLETE = 747, + RBAC_PERM_COMMAND_TICKET_DELETE = 748, + RBAC_PERM_COMMAND_TICKET_ESCALATE = 749, + RBAC_PERM_COMMAND_TICKET_ESCALATEDLIST = 750, + RBAC_PERM_COMMAND_TICKET_LIST = 751, + RBAC_PERM_COMMAND_TICKET_ONLINELIST = 752, + RBAC_PERM_COMMAND_TICKET_RESET = 753, + RBAC_PERM_COMMAND_TICKET_RESPONSE = 754, + RBAC_PERM_COMMAND_TICKET_RESPONSE_APPEND = 755, + RBAC_PERM_COMMAND_TICKET_RESPONSE_APPENDLN = 756, + RBAC_PERM_COMMAND_TICKET_TOGGLESYSTEM = 757, + RBAC_PERM_COMMAND_TICKET_UNASSIGN = 758, + RBAC_PERM_COMMAND_TICKET_VIEWID = 759, + RBAC_PERM_COMMAND_TICKET_VIEWNAME = 760, + RBAC_PERM_COMMAND_TITLES_ADD = 762, + RBAC_PERM_COMMAND_TITLES_CURRENT = 763, + RBAC_PERM_COMMAND_TITLES_REMOVE = 764, + RBAC_PERM_COMMAND_TITLES_SET_MASK = 766, + RBAC_PERM_COMMAND_WP = 767, + RBAC_PERM_COMMAND_WP_ADD = 768, + RBAC_PERM_COMMAND_WP_EVENT = 769, + RBAC_PERM_COMMAND_WP_LOAD = 770, + RBAC_PERM_COMMAND_WP_MODIFY = 771, + RBAC_PERM_COMMAND_WP_UNLOAD = 772, + RBAC_PERM_COMMAND_WP_RELOAD = 773, + RBAC_PERM_COMMAND_WP_SHOW = 774, + RBAC_PERM_COMMAND_MAILBOX = 777, + RBAC_PERM_COMMAND_AHBOT_ITEMS = 779, + RBAC_PERM_COMMAND_AHBOT_ITEMS_GRAY = 780, + RBAC_PERM_COMMAND_AHBOT_ITEMS_WHITE = 781, + RBAC_PERM_COMMAND_AHBOT_ITEMS_GREEN = 782, + RBAC_PERM_COMMAND_AHBOT_ITEMS_BLUE = 783, + RBAC_PERM_COMMAND_AHBOT_ITEMS_PURPLE = 784, + RBAC_PERM_COMMAND_AHBOT_ITEMS_ORANGE = 785, + RBAC_PERM_COMMAND_AHBOT_ITEMS_YELLOW = 786, + RBAC_PERM_COMMAND_AHBOT_RATIO = 787, + RBAC_PERM_COMMAND_AHBOT_RATIO_ALLIANCE = 788, + RBAC_PERM_COMMAND_AHBOT_RATIO_HORDE = 789, + RBAC_PERM_COMMAND_AHBOT_RATIO_NEUTRAL = 790, + RBAC_PERM_COMMAND_AHBOT_REBUILD = 791, + RBAC_PERM_COMMAND_AHBOT_RELOAD = 792, + RBAC_PERM_COMMAND_AHBOT_STATUS = 793, + RBAC_PERM_COMMAND_GUILD_INFO = 794, + RBAC_PERM_COMMAND_INSTANCE_SET_BOSS_STATE = 795, + RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE = 796, + RBAC_PERM_COMMAND_PVPSTATS = 797, + RBAC_PERM_COMMAND_MODIFY_XP = 798, + RBAC_PERM_COMMAND_NPC_EVADE = 837, + RBAC_PERM_COMMAND_PET_LEVEL = 838, + RBAC_PERM_COMMAND_SERVER_SHUTDOWN_FORCE = 839, + RBAC_PERM_COMMAND_SERVER_RESTART_FORCE = 840, + RBAC_PERM_COMMAND_NEARGRAVEYARD = 841, + RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 843, + RBAC_PERM_COMMAND_NPC_SPAWNGROUP = 856, + RBAC_PERM_COMMAND_NPC_DESPAWNGROUP = 857, + RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP = 858, + RBAC_PERM_COMMAND_GOBJECT_DESPAWNGROUP = 859, + RBAC_PERM_COMMAND_LIST_RESPAWNS = 860, + RBAC_PERM_COMMAND_GROUP_SET = 861, + RBAC_PERM_COMMAND_GROUP_ASSISTANT = 862, + RBAC_PERM_COMMAND_GROUP_MAINTANK = 863, + RBAC_PERM_COMMAND_GROUP_MAINASSIST = 864, + RBAC_PERM_COMMAND_GROUP_REVIVE = 868, + RBAC_PERM_COMMAND_NPC_SHOWLOOT = 865, + RBAC_PERM_COMMAND_LIST_SPAWNPOINTS = 866, + RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING_LOCALE = 867, + RBAC_PERM_COMMAND_SERVER_DEBUG = 872, + RBAC_PERM_COMMAND_RELOAD_CREATURE_MOVEMENT_OVERRIDE = 873, + RBAC_PERM_COMMAND_SETTINGS_ANNOUNCER = 874, + RBAC_PERM_COMMAND_LOOKUP_MAP_ID = 875, + RBAC_PERM_COMMAND_LOOKUP_ITEM_ID = 876, + RBAC_PERM_COMMAND_LOOKUP_QUEST_ID = 877, + RBAC_PERM_COMMAND_PDUMP_COPY = 880, + RBAC_PERM_COMMAND_RELOAD_VEHICLE_TEMPLATE = 881, + RBAC_PERM_COMMAND_BG_START = 884, + RBAC_PERM_COMMAND_BG_STOP = 885, + RBAC_PERM_COMMAND_ITEM_RESTORE = 886, + RBAC_PERM_COMMAND_ITEM_RESTORE_LIST = 887, + RBAC_PERM_COMMAND_ITEM_REFUND = 888, + RBAC_PERM_COMMAND_COMMENTATOR = 889, + RBAC_PERM_COMMAND_SKIRMISH = 890, + RBAC_PERM_COMMAND_STRING = 891, + RBAC_PERM_COMMAND_OPENDOOR = 892, + RBAC_PERM_COMMAND_BEASTMASTER = 893, + RBAC_PERM_COMMAND_PACKETLOG = 894, + RBAC_PERM_COMMAND_AURA_STACK = 895, + RBAC_PERM_COMMAND_RESPAWN_ALL = 896, + RBAC_PERM_COMMAND_GEAR_REPAIR = 897, + RBAC_PERM_COMMAND_GEAR_STATS = 898, + RBAC_PERM_COMMAND_SPECT = 899, + RBAC_PERM_COMMAND_SPECT_VERSION = 900, + RBAC_PERM_COMMAND_SPECT_RESET = 901, + RBAC_PERM_COMMAND_SPECT_SPECTATE = 902, + RBAC_PERM_COMMAND_SPECT_WATCH = 903, + RBAC_PERM_COMMAND_SPECT_LEAVE = 904, + RBAC_PERM_COMMAND_ARENA_SEASON = 905, + RBAC_PERM_COMMAND_ARENA_SEASON_REWARD = 906, + RBAC_PERM_COMMAND_ARENA_SEASON_DELETETEAMS = 907, + RBAC_PERM_COMMAND_ARENA_SEASON_START = 908, + RBAC_PERM_COMMAND_CHARACTER_CHECK_BANK = 909, + RBAC_PERM_COMMAND_CHARACTER_CHECK_BAG = 910, + RBAC_PERM_COMMAND_CHARACTER_CHECK_PROFESSION = 911, + RBAC_PERM_COMMAND_GOBJECT_LOAD = 912, + RBAC_PERM_COMMAND_BF_QUEUE = 913, + // custom permissions 1000+ + RBAC_PERM_MAX +}; + +enum RBACCommandResult +{ + RBAC_OK, + RBAC_CANT_ADD_ALREADY_ADDED, + RBAC_CANT_REVOKE_NOT_IN_LIST, + RBAC_IN_GRANTED_LIST, + RBAC_IN_DENIED_LIST, + RBAC_ID_DOES_NOT_EXISTS +}; + +typedef std::set RBACPermissionContainer; + +class AC_GAME_API RBACPermission +{ +public: + RBACPermission(uint32 id = 0, std::string const& name = ""): + _id(id), _name(name), _perms() { } + + /// Gets the Name of the Object + std::string const& GetName() const { return _name; } + /// Gets the Id of the Object + uint32 GetId() const { return _id; } + + /// Gets the Permissions linked to this permission + RBACPermissionContainer const& GetLinkedPermissions() const { return _perms; } + /// Adds a new linked Permission + void AddLinkedPermission(uint32 id) { _perms.insert(id); } + /// Removes a linked Permission + void RemoveLinkedPermission(uint32 id) { _perms.erase(id); } + +private: + uint32 _id; ///> id of the object + std::string _name; ///> name of the object + RBACPermissionContainer _perms; ///> Set of permissions +}; + +/** + * @name RBACData + * @brief Contains all needed information about the account + * + * This class contains all the data needed to calculate the account permissions. + * RBACData is formed by granted and denied permissions and all the inherited permissions + * + * Calculation of current Permissions: Granted permissions - Denied permissions + * - Granted permissions: through linked permissions and directly assigned + * - Denied permissions: through linked permissions and directly assigned + */ +class AC_GAME_API RBACData +{ +public: + RBACData(uint32 id, std::string const& name, int32 realmId, uint8 secLevel = 255): + _id(id), _name(name), _realmId(realmId), _secLevel(secLevel), + _grantedPerms(), _deniedPerms(), _globalPerms() { } + + /// Gets the Name of the Object + std::string const& GetName() const { return _name; } + /// Gets the Id of the Object + uint32 GetId() const { return _id; } + + /** + * @name HasPermission + * @brief Checks if certain action is allowed + * + * @return grant or deny action + */ + bool HasPermission(uint32 permission) const + { + return _globalPerms.find(permission) != _globalPerms.end(); + } + + // Functions enabled to be used by command system + /// Returns all the granted permissions (after computation) + RBACPermissionContainer const& GetPermissions() const { return _globalPerms; } + /// Returns all the granted permissions + RBACPermissionContainer const& GetGrantedPermissions() const { return _grantedPerms; } + /// Returns all the denied permissions + RBACPermissionContainer const& GetDeniedPermissions() const { return _deniedPerms; } + + /** + * @name GrantPermission + * @brief Grants a permission + * + * @param permissionId permission to be granted + * @param realmId realm affected + * + * @return Success or failure (with reason) to grant the permission + */ + RBACCommandResult GrantPermission(uint32 permissionId, int32 realmId = 0); + + /** + * @name DenyPermission + * @brief Denies a permission + * + * @param permissionId permission to be denied + * @param realmId realm affected + * + * @return Success or failure (with reason) to deny the permission + */ + RBACCommandResult DenyPermission(uint32 permissionId, int32 realmId = 0); + + /** + * @name RevokePermission + * @brief Removes a permission + * + * @param permissionId permission to be removed + * @param realmId realm affected + * + * @return Success or failure (with reason) to remove the permission + */ + RBACCommandResult RevokePermission(uint32 permissionId, int32 realmId = 0); + + /// Loads all permissions assigned to current account + void LoadFromDB(); + QueryCallback LoadFromDBAsync(); + void LoadFromDBCallback(PreparedQueryResult result); + + /// Sets security level + void SetSecurityLevel(uint8 id) + { + _secLevel = id; + LoadFromDB(); + } + + /// Returns the security level assigned + uint8 GetSecurityLevel() const { return _secLevel; } + + /// For unit testing - forces permission recalculation without database + void RecalculatePermissions() { CalculateNewPermissions(); } + + /// For unit testing - sets security level without database reload + void SetSecurityLevelForTest(uint8 id) { _secLevel = id; } + +private: + /// Saves a permission to DB, Granted or Denied + void SavePermission(uint32 role, bool granted, int32 realm); + /// Clears roles, groups and permissions - Used for reload + void ClearData(); + + /** + * @name CalculateNewPermissions + * @brief Calculates new permissions + * + * Calculates new permissions after some change + * The calculation is done Granted - Denied: + * - Granted permissions: through linked permissions and directly assigned + * - Denied permissions: through linked permissions and directly assigned + */ + void CalculateNewPermissions(); + + int32 GetRealmId() const { return _realmId; } + + /// Checks if a permission is granted + bool HasGrantedPermission(uint32 permissionId) const + { + return _grantedPerms.find(permissionId) != _grantedPerms.end(); + } + + /// Checks if a permission is denied + bool HasDeniedPermission(uint32 permissionId) const + { + return _deniedPerms.find(permissionId) != _deniedPerms.end(); + } + + /// Adds a new granted permission + void AddGrantedPermission(uint32 permissionId) + { + _grantedPerms.insert(permissionId); + } + + /// Removes a granted permission + void RemoveGrantedPermission(uint32 permissionId) + { + _grantedPerms.erase(permissionId); + } + + /// Adds a new denied permission + void AddDeniedPermission(uint32 permissionId) + { + _deniedPerms.insert(permissionId); + } + + /// Removes a denied permission + void RemoveDeniedPermission(uint32 permissionId) + { + _deniedPerms.erase(permissionId); + } + + /// Adds a list of permissions to another list + void AddPermissions(RBACPermissionContainer const& permsFrom, RBACPermissionContainer& permsTo); + + /// Removes a list of permissions from another list + void RemovePermissions(RBACPermissionContainer& permsFrom, RBACPermissionContainer const& permsToRemove); + + /** + * @name ExpandPermissions + * @brief Adds the list of linked permissions to the original list + * + * @param permissions The list of permissions to expand + */ + void ExpandPermissions(RBACPermissionContainer& permissions); + + uint32 _id; ///> Account id + std::string _name; ///> Account name + int32 _realmId; ///> RealmId Affected + uint8 _secLevel; ///> Account SecurityLevel + RBACPermissionContainer _grantedPerms; ///> Granted permissions + RBACPermissionContainer _deniedPerms; ///> Denied permissions + RBACPermissionContainer _globalPerms; ///> Calculated permissions +}; + +} + +#endif diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 29628f1f8..f0aa9da38 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -40,6 +40,7 @@ #include "MapMgr.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "RaceMgr.h" #include "ReputationMgr.h" #include "ScriptMgr.h" @@ -520,6 +521,8 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaCondition condi // disable for gamemasters with GM-mode enabled if (_player->IsGameMaster()) return; + if (_player->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS)) + return; LOG_DEBUG("achievement", "AchievementMgr::ResetAchievementCriteria({}, {}, {})", condition, value, evenIfCriteriaComplete); @@ -821,6 +824,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // disable for gamemasters with GM-mode enabled if (_player->IsGameMaster()) return; + if (_player->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS)) + return; if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL) { @@ -2282,6 +2287,8 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) ChatHandler(_player->GetSession()).PSendSysMessage("Not available in GM mode"); return; } + if (_player->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS)) + return; if (!sScriptMgr->OnPlayerBeforeAchievementComplete(GetPlayer(), achievement)) { @@ -2323,7 +2330,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) } } - if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL) && AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity())) + if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL) && !_player->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_REALM_FIRST_ACHIEVEMENTS)) sAchievementMgr->SetRealmCompleted(achievement); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, achievement->ID); diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index c72f94394..ad6d74523 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -39,6 +39,7 @@ #include "ObjectMgr.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "ReputationMgr.h" #include "ScriptMgr.h" #include "SpellAuras.h" @@ -1110,7 +1111,7 @@ void Battleground::RemovePlayerAtLeave(Player* player) SendPacketToTeam(teamId, &data, player, false); // cast deserter - if (isBattleground() && !player->IsGameMaster() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_CAST_DESERTER)) + if (isBattleground() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_NO_BATTLEGROUND_DESERTER_DEBUFF) && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_CAST_DESERTER)) if (status == STATUS_IN_PROGRESS || status == STATUS_WAIT_JOIN) player->ScheduleDelayedOperation(DELAYED_SPELL_CAST_DESERTER); diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp index 05e887a6b..ad7b9dfc9 100644 --- a/src/server/game/Chat/Channels/Channel.cpp +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -23,6 +23,7 @@ #include "GameTime.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "SocialMgr.h" #include "World.h" @@ -218,7 +219,7 @@ void Channel::JoinChannel(Player* player, std::string const& pass) JoinNotify(player); - playersStore[guid].SetOwnerGM(player->GetSession()->IsGMAccount()); + playersStore[guid].SetOwnerGM(player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)); // Custom channel handling if (!IsConstant()) @@ -296,11 +297,11 @@ void Channel::LeaveChannel(Player* player, bool send) for (Channel::PlayerContainer::const_iterator itr = playersStore.begin(); itr != playersStore.end(); ++itr) { newowner = itr->second.player; - if (itr->second.plrPtr->GetSession()->IsGMAccount()) + if (itr->second.plrPtr->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) _isOwnerGM = true; else _isOwnerGM = false; - if (!itr->second.plrPtr->GetSession()->GetSecurity()) + if (!itr->second.plrPtr->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) break; } SetOwner(newowner); @@ -324,7 +325,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b return; } - if (!playersStore[good].IsModerator() && !player->GetSession()->IsGMAccount()) + if (!playersStore[good].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { WorldPacket data; MakeNotModerator(&data); @@ -347,7 +348,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b bool isOnChannel = victim && IsOn(victim); if (!isOnChannel) { - if (ban && (player->GetSession()->IsGMAccount() || isGoodConstantModerator)) + if (ban && (player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) || isGoodConstantModerator)) { if (ObjectGuid guid = sCharacterCache->GetCharacterGuidByName(badname)) { @@ -387,7 +388,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b bool changeowner = _ownerGUID == victim; bool isBadConstantModerator = _channelRights.moderators.find(badAccId) != _channelRights.moderators.end(); - if (!player->GetSession()->IsGMAccount() && !isGoodConstantModerator) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && !isGoodConstantModerator) { if (changeowner && good != _ownerGUID) { @@ -405,7 +406,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b return; } - if (isBadConstantModerator || bad->GetSession()->IsGMAccount()) + if (isBadConstantModerator || bad->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { WorldPacket data; MakeNotModerator(&data); @@ -454,7 +455,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b for (Channel::PlayerContainer::const_iterator itr = playersStore.begin(); itr != playersStore.end(); ++itr) { newowner = itr->second.player; - if (!itr->second.plrPtr->GetSession()->GetSecurity()) + if (!itr->second.plrPtr->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) break; } SetOwner(newowner); @@ -476,7 +477,7 @@ void Channel::UnBan(Player const* player, std::string const& badname) return; } - if (!playersStore[good].IsModerator() && !player->GetSession()->IsGMAccount()) + if (!playersStore[good].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { WorldPacket data; MakeNotModerator(&data); @@ -499,7 +500,7 @@ void Channel::UnBan(Player const* player, std::string const& badname) } bool isConstantModerator = _channelRights.moderators.find(player->GetSession()->GetAccountId()) != _channelRights.moderators.end(); - if (!player->GetSession()->IsGMAccount() && !isConstantModerator) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && !isConstantModerator) { if (_channelRights.flags & CHANNEL_RIGHT_CANT_BAN) { @@ -544,7 +545,7 @@ void Channel::Password(Player const* player, std::string const& pass) return; } - if (!playersStore[guid].IsModerator() && !player->GetSession()->IsGMAccount()) + if (!playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { WorldPacket data; MakeNotModerator(&data); @@ -581,7 +582,7 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo return; } - if (!playersStore[guid].IsModerator() && !player->GetSession()->IsGMAccount()) + if (!playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { WorldPacket data; MakeNotModerator(&data); @@ -598,7 +599,7 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo if (!victim || !IsOn(victim) || // allow make moderator from another team only if both is GMs // at this moment this only way to show channel post for GM from another team - ((!player->GetSession()->IsGMAccount() || !newp->GetSession()->IsGMAccount()) && player->GetTeamId() != newp->GetTeamId() && + ((!player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL) || !newp->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL)) && player->GetTeamId() != newp->GetTeamId() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL))) { WorldPacket data; @@ -624,7 +625,7 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo else { bool isGoodConstantModerator = _channelRights.moderators.find(player->GetSession()->GetAccountId()) != _channelRights.moderators.end(); - if (!player->GetSession()->IsGMAccount() && !isGoodConstantModerator) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && !isGoodConstantModerator) { if (_channelRights.flags & CHANNEL_RIGHT_CANT_MUTE) { @@ -652,7 +653,7 @@ void Channel::SetOwner(Player const* player, std::string const& newname) } bool isGoodConstantModerator = _channelRights.moderators.find(player->GetSession()->GetAccountId()) != _channelRights.moderators.end(); - if (!player->GetSession()->IsGMAccount() && guid != _ownerGUID && !isGoodConstantModerator) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && guid != _ownerGUID && !isGoodConstantModerator) { WorldPacket data; MakeNotOwner(&data); @@ -706,15 +707,20 @@ void Channel::List(Player const* player) std::size_t pos = data.wpos(); data << uint32(0); // size of list, placeholder + uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); + uint32 count = 0; if (!(_channelRights.flags & CHANNEL_RIGHT_CANT_SPEAK)) for (PlayerContainer::const_iterator i = playersStore.begin(); i != playersStore.end(); ++i) - if (AccountMgr::IsPlayerAccount(i->second.plrPtr->GetSession()->GetSecurity())) - { - data << i->first; - data << uint8(i->second.flags); // flags seems to be changed... - ++count; - } + if (Player* member = i->second.plrPtr) + if ((player->GetSession()->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) || + member->GetSession()->GetSecurity() <= AccountTypes(gmLevelInWhoList)) && + member->IsVisibleGloballyFor(player)) + { + data << i->first; + data << uint8(i->second.flags); // flags seems to be changed... + ++count; + } data.put(pos, count); @@ -733,7 +739,7 @@ void Channel::Announce(Player const* player) return; } - if (!playersStore[guid].IsModerator() && !player->GetSession()->IsGMAccount()) + if (!playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { WorldPacket data; MakeNotModerator(&data); @@ -932,7 +938,7 @@ void Channel::SendToAllWatching(WorldPacket* data) bool Channel::ShouldAnnouncePlayer(Player const* player) const { - return !(player->GetSession()->IsGMAccount() && sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL)); + return !(player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL) && sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL)); } void Channel::Voice(ObjectGuid /*guid1*/, ObjectGuid /*guid2*/) @@ -1158,7 +1164,7 @@ void Channel::JoinNotify(Player* p) { if (_channelRights.flags & CHANNEL_RIGHT_CANT_SPEAK) return; - if (!AccountMgr::IsPlayerAccount(p->GetSession()->GetSecurity())) + if (p->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) return; WorldPacket data(SMSG_USERLIST_ADD, 8 + 1 + 1 + 4 + GetName().size()); @@ -1175,7 +1181,7 @@ void Channel::LeaveNotify(Player* p) { if (_channelRights.flags & CHANNEL_RIGHT_CANT_SPEAK) return; - if (!AccountMgr::IsPlayerAccount(p->GetSession()->GetSecurity())) + if (p->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) return; WorldPacket data(SMSG_USERLIST_REMOVE, 8 + 1 + 4 + GetName().size()); @@ -1191,7 +1197,7 @@ void Channel::FlagsNotify(Player* p) { if (_channelRights.flags & CHANNEL_RIGHT_CANT_SPEAK) return; - if (!AccountMgr::IsPlayerAccount(p->GetSession()->GetSecurity())) + if (p->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) return; WorldPacket data(SMSG_USERLIST_UPDATE, 8 + 1 + 1 + 4 + GetName().size()); @@ -1230,8 +1236,7 @@ void Channel::ToggleModeration(Player* player) return; } - const AccountTypes level = static_cast(sWorld->getIntConfig(CONFIG_GM_LEVEL_CHANNEL_MODERATION)); - const bool gm = (player->GetSession()->GetSecurity() >= level); + const bool gm = player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR); if (!playersStore[guid].IsModerator() && !gm) { diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index a0dc7f090..69b969eef 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -24,6 +24,7 @@ #include "ObjectMgr.h" #include "Opcodes.h" #include "Player.h" +#include "RBAC.h" #include "Realm.h" #include "ScriptMgr.h" #include "Tokenize.h" @@ -54,6 +55,13 @@ bool ChatHandler::IsAvailable(uint32 securityLevel) const return IsConsole() ? true : m_session->GetSecurity() >= AccountTypes(securityLevel); } +bool ChatHandler::HasPermission(uint32 permissionId) const +{ + if (IsConsole()) + return true; + return m_session && m_session->HasPermission(permissionId); +} + bool ChatHandler::HasLowerSecurity(Player* target, ObjectGuid guid, bool strong) { WorldSession* target_session = nullptr; @@ -82,7 +90,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac return false; // ignore only for non-players for non strong checks (when allow apply command at least to same sec level) - if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !strong && sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY)) + if (m_session->HasPermission(rbac::RBAC_PERM_CAN_IGNORE_LOWER_SECURITY_CHECK) && !strong && sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY)) return false; if (target) @@ -117,7 +125,7 @@ void ChatHandler::SendGMText(std::string_view str) { std::vector lines = Acore::Tokenize(str, '\n', true); // Session should have permissions to receive global gm messages - if (AccountMgr::IsPlayerAccount(m_session->GetSecurity())) + if (!m_session->HasPermission(rbac::RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE)) return; for (std::string_view line : lines) @@ -231,7 +239,7 @@ bool ChatHandler::_ParseCommands(std::string_view text) return true; // Pretend commands don't exist for regular players - if (m_session && AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !sWorld->getBoolConfig(CONFIG_ALLOW_PLAYER_COMMANDS)) + if (m_session && !m_session->HasPermission(rbac::RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR) && !sWorld->getBoolConfig(CONFIG_ALLOW_PLAYER_COMMANDS)) return false; // Send error message for GMs @@ -358,7 +366,7 @@ std::size_t ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg chatType, La if (Player const* playerSender = sender->ToPlayer()) { chatTag = playerSender->GetChatTag(); - gmMessage = playerSender->IsGameMaster(); + gmMessage = playerSender->GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_GM_CHAT); } } diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index e2891a3b8..7bc8f0e80 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -241,6 +241,7 @@ public: Player* GetPlayer() const; WorldSession* GetSession() { return m_session; } bool IsAvailable(uint32 securityLevel) const; + bool HasPermission(uint32 permissionId) const; protected: explicit ChatHandler() : m_session(nullptr), sentErrorMessage(false) {} // for CLI subclass diff --git a/src/server/game/Chat/ChatCommands/ChatCommand.cpp b/src/server/game/Chat/ChatCommands/ChatCommand.cpp index 0e763f1b3..6e72f54aa 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommand.cpp +++ b/src/server/game/Chat/ChatCommands/ChatCommand.cpp @@ -22,6 +22,7 @@ #include "DatabaseEnv.h" #include "Log.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "StringFormat.h" #include "Tokenize.h" @@ -515,6 +516,10 @@ bool Acore::Impl::ChatCommands::ChatCommandNode::IsInvokerVisible(ChatHandler co if (who.IsConsole() && (_permission.AllowConsole == Acore::ChatCommands::Console::Yes)) return true; + // RBAC permissions start at 200, SEC_* levels are 0-4 + if (_permission.RequiredLevel >= rbac::RBAC_PERM_COMMAND_RBAC) + return who.HasPermission(_permission.RequiredLevel); + return !who.IsConsole() && who.IsAvailable(_permission.RequiredLevel); } diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 9da1f9199..5422da2ec 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -34,6 +34,7 @@ #include "ObjectMgr.h" #include "Opcodes.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "SharedDefines.h" #include "SocialMgr.h" @@ -493,7 +494,9 @@ namespace lfg uint32 lockData = 0; - if (dungeon->expansion > expansion || (onlySeasonalBosses && !dungeon->seasonal)) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER)) + lockData = LFG_LOCKSTATUS_RAID_LOCKED; + else if (dungeon->expansion > expansion || (onlySeasonalBosses && !dungeon->seasonal)) lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; else if (IsDungeonDisabled(dungeon->map, dungeon->difficulty)) lockData = LFG_LOCKSTATUS_RAID_LOCKED; @@ -698,7 +701,11 @@ namespace lfg if (!isRaid && joinData.result == LFG_JOIN_OK) { // Check player or group member restrictions - if (player->InBattleground() || (player->InBattlegroundQueue() && !sWorld->getBoolConfig(CONFIG_ALLOW_JOIN_BG_AND_LFG))) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER)) + { + joinData.result = LFG_JOIN_NOT_MEET_REQS; + } + else if (player->InBattleground() || (player->InBattlegroundQueue() && !sWorld->getBoolConfig(CONFIG_ALLOW_JOIN_BG_AND_LFG))) { joinData.result = LFG_JOIN_USING_BG_SYSTEM; } @@ -721,7 +728,11 @@ namespace lfg { if (Player* plrg = itr->GetSource()) { - if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER)) + if (!plrg->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER)) + { + joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS; + } + else if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER)) { joinData.result = LFG_JOIN_PARTY_DESERTER; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0739c1d3b..37d347b5e 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -66,6 +66,7 @@ #include "Pet.h" #include "PetitionMgr.h" #include "QuestDef.h" +#include "RBAC.h" #include "Realm.h" #include "ReputationMgr.h" #include "ScriptMgr.h" @@ -175,7 +176,7 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), _cinematicMgr(*thi //m_pad = 0; // players always accept - if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity())) + if (!GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS)) SetAcceptWhispers(true); m_usedTalentCount = 0; @@ -573,7 +574,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo ? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL) : sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); - if (!AccountMgr::IsPlayerAccount(GetSession()->GetSecurity())) + if (GetSession()->HasPermission(rbac::RBAC_PERM_USE_START_GM_LEVEL)) { uint32 gm_level = sWorld->getIntConfig(CONFIG_START_GM_LEVEL); if (gm_level > start_level) @@ -1312,7 +1313,7 @@ void Player::ToggleAFK() ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); // afk player not allowed in battleground - if (!IsGameMaster() && isAFK() && InBattleground()) + if (!GetSession()->HasPermission(rbac::RBAC_PERM_CAN_AFK_ON_BATTLEGROUND) && isAFK() && InBattleground() && !InArena()) LeaveBattleground(); } @@ -1358,7 +1359,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati return false; } - if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, mapid, this)) + if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_DISABLE_MAP) && sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, mapid, this)) { LOG_ERROR("entities.player", "Player ({}, name: {}) tried to enter a forbidden map {}", GetGUID().ToString(), GetName(), mapid); SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED); @@ -2188,6 +2189,11 @@ bool Player::IsInAreaTriggerRadius(AreaTrigger const* trigger, float delta) cons return true; } +bool Player::CanBeGameMaster() const +{ + return GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_GM); +} + void Player::SetGameMaster(bool on) { if (on) @@ -2540,10 +2546,15 @@ void Player::InitTalentForLevel() { uint32 talentPointsForLevel = CalculateTalentsPoints(); - // xinef: more talent points that we have are used, reset + // if used more than have then reset if (m_usedTalentCount > talentPointsForLevel) - resetTalents(true); - // xinef: else, recalculate free talent points count + { + if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED)) + resetTalents(true); + else + SetFreeTalentPoints(0); + } + // else update amount of free points else SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); @@ -9427,7 +9438,7 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/, SendDirectMessage(&data); // Special handling for messages, do not use visibility map for stealthed units - Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE), nullptr, true); + Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT), nullptr, true); Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); } @@ -11293,13 +11304,17 @@ void Player::LeaveBattleground(Battleground* bg) TeleportToEntryPoint(); } -bool Player::CanJoinToBattleground() const +bool Player::CanJoinToBattleground(Battleground const* bg) const { // check Deserter debuff if (HasAura(26013)) return false; - return true; + if (bg->isArena()) + return GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_ARENAS); + if (bg->GetBgTypeID() == BATTLEGROUND_RB) + return GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_RANDOM_BG); + return GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_NORMAL_BG); } bool Player::CanReportAfkDueToLimit() diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 2eb10a110..1b1ca057f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1172,6 +1172,7 @@ public: [[nodiscard]] bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; } void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; } [[nodiscard]] bool IsGameMaster() const { return m_ExtraFlags & PLAYER_EXTRA_GM_ON; } + [[nodiscard]] bool CanBeGameMaster() const; void SetGameMaster(bool on); [[nodiscard]] bool isGMChat() const { return m_ExtraFlags & PLAYER_EXTRA_GM_CHAT; } void SetGMChat(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; } @@ -2313,7 +2314,7 @@ public: [[nodiscard]] TeamId GetBgTeamId() const { return m_bgData.bgTeamId != TEAM_NEUTRAL ? m_bgData.bgTeamId : GetTeamId(); } void LeaveBattleground(Battleground* bg = nullptr); - [[nodiscard]] bool CanJoinToBattleground() const; + [[nodiscard]] bool CanJoinToBattleground(Battleground const* bg) const; bool CanReportAfkDueToLimit(); void ReportedAfkBy(Player* reporter); void ClearAfkReports() { m_bgData.bgAfkReporter.clear(); } diff --git a/src/server/game/Entities/Player/PlayerMisc.cpp b/src/server/game/Entities/Player/PlayerMisc.cpp index 91459d848..91a3fa93c 100644 --- a/src/server/game/Entities/Player/PlayerMisc.cpp +++ b/src/server/game/Entities/Player/PlayerMisc.cpp @@ -20,6 +20,7 @@ #include "InstancePackets.h" #include "MapMgr.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "WorldSession.h" @@ -30,7 +31,7 @@ void Player::UpdateSpeakTime(ChatFloodThrottle::Index index) { // ignore chat spam protection for GMs in any mode - if (!AccountMgr::IsPlayerAccount(GetSession()->GetSecurity())) + if (GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHAT_SPAM)) return; uint32 limit, delay; diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 843d1118e..51ff08982 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -49,6 +49,7 @@ #include "Player.h" #include "QueryHolder.h" #include "QuestDef.h" +#include "RBAC.h" #include "ReputationMgr.h" #include "ScriptMgr.h" #include "ScriptObjectFwd.h" @@ -5024,7 +5025,9 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons m_name = fields[2].Get(); // check name limitations - if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS) + uint8 nameResult = ObjectMgr::CheckPlayerName(m_name); + if (nameResult != CHAR_NAME_SUCCESS && + !(nameResult == CHAR_NAME_RESERVED && GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME))) { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->SetData(0, uint16(AT_LOGIN_RENAME)); @@ -5568,7 +5571,7 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons outDebugValues(); // GM state - if (!AccountMgr::IsPlayerAccount(GetSession()->GetSecurity())) + if (GetSession()->HasPermission(rbac::RBAC_PERM_RESTORE_SAVED_GM_STATE)) { switch (sWorld->getIntConfig(CONFIG_GM_LOGIN_STATE)) { diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp index ed59470dd..46fc3a416 100644 --- a/src/server/game/Entities/Player/SocialMgr.cpp +++ b/src/server/game/Entities/Player/SocialMgr.cpp @@ -20,6 +20,7 @@ #include "DatabaseEnv.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" @@ -224,8 +225,6 @@ void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, Frie return; TeamId teamId = player->GetTeamId(); - AccountTypes security = player->GetSession()->GetSecurity(); - bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)); auto const& itr = player->GetSocial()->m_playerSocialMap.find(friendGUID); @@ -234,7 +233,14 @@ void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, Frie // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all - if ((!AccountMgr::IsPlayerAccount(security) || ((pFriend->GetTeamId() == teamId || allowTwoSideWhoList) && pFriend->GetSession()->GetSecurity() <= gmLevelInWhoList)) && pFriend->IsVisibleGloballyFor(player)) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && + pFriend->GetSession()->GetSecurity() > gmLevelInWhoList) + return; + + if (pFriend->GetTeamId() != teamId && !player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST)) + return; + + if (pFriend->IsVisibleGloballyFor(player)) { friendInfo.Status = FRIEND_STATUS_ONLINE; if (pFriend->isAFK()) @@ -297,8 +303,6 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet) return; TeamId teamId = player->GetTeamId(); - AccountTypes security = player->GetSession()->GetSecurity(); - bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)); for (auto const& itr : m_socialMap) @@ -307,10 +311,19 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet) if (itr2 != itr.second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND)) { Player* pFriend = ObjectAccessor::FindPlayer(itr.first); + if (!pFriend) + continue; + WorldSession* session = pFriend->GetSession(); // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters // MODERATOR, GAME MASTER, ADMINISTRATOR can see all - if (pFriend && (!AccountMgr::IsPlayerAccount(pFriend->GetSession()->GetSecurity()) || ((pFriend->GetTeamId() == teamId || allowTwoSideWhoList) && security <= gmLevelInWhoList)) && player->IsVisibleGloballyFor(pFriend)) + if (!session->HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && player->GetSession()->GetSecurity() > gmLevelInWhoList) + continue; + + if (pFriend->GetTeamId() != teamId && !session->HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST)) + continue; + + if (player->IsVisibleGloballyFor(pFriend)) pFriend->SendDirectMessage(packet); } } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index efb0a28e0..25ecb1cd2 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1985,7 +1985,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const* return ERR_BATTLEGROUND_JOIN_RANGE_INDEX; // check for deserter debuff in case not arena queue - if (bgTemplate->GetBgTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground()) + if (bgTemplate->GetBgTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground(bgTemplate)) return ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS; // check if someone in party is using dungeon system diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 7ca122b9d..abd12702d 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -31,6 +31,7 @@ #include "ObjectMgr.h" #include "Opcodes.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "SocialMgr.h" #include "World.h" @@ -903,6 +904,13 @@ void Guild::BankMoveItemData::LogBankEvent(CharacterDatabaseTransaction trans, M void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const { MoveItemData::LogAction(pFrom); + if (!pFrom->IsBank() && m_pPlayer->GetSession()->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) + { + LOG_GM(m_pPlayer->GetSession()->GetAccountId(), "GM {} (Account: {}) deposit item: {} (Entry: {} Count: {}) to guild bank named: {} (Guild ID: {})", + m_pPlayer->GetName(), m_pPlayer->GetSession()->GetAccountId(), + pFrom->GetItem()->GetTemplate()->Name1, pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(), + m_pGuild->GetName(), m_pGuild->GetId()); + } } Item* Guild::BankMoveItemData::_StoreItem(CharacterDatabaseTransaction trans, BankTab* pTab, Item* pItem, ItemPosCount& pos, bool clone) const @@ -1683,6 +1691,12 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount) CharacterDatabase.CommitTransaction(trans); + if (session->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) + { + LOG_GM(session->GetAccountId(), "GM {} (Account: {}) deposited {} to guild bank (Guild: {} GuildId: {})", + player->GetName(), session->GetAccountId(), amount, GetName(), GetId()); + } + std::string aux = Acore::Impl::ByteArrayToHexStr(reinterpret_cast(&m_bankMoney), 8, true); _BroadcastEvent(GE_BANK_MONEY_SET, ObjectGuid::Empty, aux.c_str()); @@ -1737,6 +1751,12 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool _LogBankEvent(trans, repair ? GUILD_BANK_LOG_REPAIR_MONEY : GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), player->GetGUID(), amount); CharacterDatabase.CommitTransaction(trans); + if (session->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) + { + LOG_GM(session->GetAccountId(), "GM {} (Account: {}) withdrew {} from guild bank (Guild: {} GuildId: {})", + player->GetName(), session->GetAccountId(), amount, GetName(), GetId()); + } + if (amount > 10 * GOLD) // sender_acc = 0 (guild has no account), sender_guid = Guild id, sender_name = Guild name CharacterDatabase.Execute("INSERT INTO log_money VALUES({}, {}, \"{}\", \"{}\", {}, \"{}\", {}, \"(guild, members: {}, new amount: {}, leader guid low: {}, withdrawer level: {})\", NOW(), {})", 0, GetId(), GetName(), session->GetRemoteAddress(), session->GetAccountId(), player->GetName(), amount, GetMemberCount(), GetTotalBankMoney(), GetLeaderGUID().GetCounter(), player->GetLevel(), 4); diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 5c0329186..78cf20cbd 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -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()); diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 499bae1e6..f9cbfac32 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -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); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 40942b333..b700205fa 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -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 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(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_ptrgetIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK); if ((1 << (factionChangeInfo->Race - 1)) & raceMaskDisabled) @@ -2104,8 +2117,11 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr(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_ptrDeleteMember(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); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index f191dc05a..6b120f925 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -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)) { diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 387a69238..b7083c0fa 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -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; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 56047089f..30886a778 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -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; diff --git a/src/server/game/Handlers/Socialhandler.cpp b/src/server/game/Handlers/Socialhandler.cpp index 6fccfa1d3..23038746e 100644 --- a/src/server/game/Handlers/Socialhandler.cpp +++ b/src/server/game/Handlers/Socialhandler.cpp @@ -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; diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 8fbe3018e..8266d13d1 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -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); diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 94b367e61..f4dec4454 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -28,6 +28,7 @@ #include "Opcodes.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "Spell.h" #include "WorldSession.h" @@ -387,6 +388,11 @@ void InstanceScript::SetSummoner(Creature* creature) summoner->AI()->JustSummoned(creature); } +bool InstanceScript::_SkipCheckRequiredBosses(Player const* player /*= nullptr*/) const +{ + return player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES); +} + bool InstanceScript::SetBossState(uint32 id, EncounterState state) { if (id < bosses.size()) diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index ba05588ee..8b9c1e677 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -264,6 +264,8 @@ public: // Checks boss requirements (one boss required to kill other) virtual bool CheckRequiredBosses(uint32 /*bossId*/, Player const* /*player*/ = nullptr) const { return true; } + bool _SkipCheckRequiredBosses(Player const* player = nullptr) const; + void SetCompletedEncountersMask(uint32 newMask, bool save); // Returns completed encounters mask for packets diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 8ecc58b47..de55d37cd 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -112,7 +112,10 @@ enum AcoreStrings LANG_PVPSTATS = 80, LANG_PVPSTATS_DISABLED = 81, LANG_GENERIC_TWO_CURLIES_WITH_COLON = 82, - // Free 83 - 86 + LANG_RBAC_HELP_ACC_LIST = 83, + LANG_RBAC_HELP_ACC_GRANT = 84, + LANG_RBAC_HELP_ACC_DENY = 85, + LANG_RBAC_HELP_ACC_REVOKE = 86, LANG_UNKNOWN_ERROR = 87, LANG_2FA_COMMANDS_NOT_SETUP = 88, diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 131e39a30..408c89736 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -41,6 +41,7 @@ #include "PacketUtilities.h" #include "Pet.h" #include "Player.h" +#include "Realm.h" #include "QueryHolder.h" #include "ScriptMgr.h" #include "SocialMgr.h" @@ -115,6 +116,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 accountFlags, s _security(sec), _skipQueue(skipQueue), _accountId(id), + _RBACData(nullptr), _accountName(std::move(name)), _accountFlags(accountFlags), m_expansion(expansion), @@ -171,6 +173,8 @@ WorldSession::~WorldSession() m_Socket = nullptr; } + delete _RBACData; + ///- empty incoming packet queue WorldPacket* packet = nullptr; while (_recvQueue.next(packet)) @@ -360,7 +364,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) ///- Before we process anything: /// If necessary, kick the player because the client didn't send anything for too long /// (or they've been idling in character select) - if (sWorld->getBoolConfig(CONFIG_CLOSE_IDLE_CONNECTIONS) && IsConnectionIdle() && m_Socket) + if (IsConnectionIdle() && !HasPermission(rbac::RBAC_PERM_IGNORE_IDLE_CONNECTION)) m_Socket->CloseSocket(); if (updater.ProcessUnsafe()) @@ -1519,3 +1523,54 @@ void WorldSession::SetPacketLogging(bool state) if (m_Socket) m_Socket->SetPacketLogging(state); } + +void WorldSession::LoadPermissions() +{ + uint32 id = GetAccountId(); + uint8 secLevel = GetSecurity(); + + LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: {}, Name: {}, realmId: {}, secLevel: {}]", + id, _accountName, realm.Id.Realm, secLevel); + + _RBACData = new rbac::RBACData(id, _accountName, realm.Id.Realm, secLevel); + _RBACData->LoadFromDB(); +} + +QueryCallback WorldSession::LoadPermissionsAsync() +{ + uint32 id = GetAccountId(); + uint8 secLevel = GetSecurity(); + + LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: {}, Name: {}, realmId: {}, secLevel: {}]", + id, _accountName, realm.Id.Realm, secLevel); + + _RBACData = new rbac::RBACData(id, _accountName, realm.Id.Realm, secLevel); + return _RBACData->LoadFromDBAsync(); +} + +bool WorldSession::HasPermission(uint32 permission) +{ + if (!_RBACData) + LoadPermissions(); + + bool hasPermission = _RBACData->HasPermission(permission); + LOG_DEBUG("rbac", "WorldSession::HasPermission [AccountId: {}, Name: {}, realmId: {}]", + _RBACData->GetId(), _RBACData->GetName(), realm.Id.Realm); + + return hasPermission; +} + +void WorldSession::InvalidateRBACData() +{ + LOG_DEBUG("rbac", "WorldSession::InvalidateRBACData [AccountId: {}, Name: {}, realmId: {}]", + _RBACData->GetId(), _RBACData->GetName(), realm.Id.Realm); + delete _RBACData; + _RBACData = nullptr; +} + +void WorldSession::InitRBACDataForTest() +{ + delete _RBACData; + _RBACData = new rbac::RBACData(_accountId, _accountName, realm.Id.Realm, _security); + _RBACData->LoadFromDBCallback(nullptr); +} diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index b7f33931c..0904312c9 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -440,6 +440,16 @@ public: AccountTypes GetSecurity() const { return _security; } bool CanSkipQueue() const { return _skipQueue; } + + // RBAC + rbac::RBACData* GetRBACData() const { return _RBACData; } + bool HasPermission(uint32 permissionId); + void LoadPermissions(); + QueryCallback LoadPermissionsAsync(); + void InvalidateRBACData(); + + /// For unit testing - initializes RBAC data without database access + void InitRBACDataForTest(); uint32 GetAccountId() const { return _accountId; } Player* GetPlayer() const { return _player; } std::string const& GetPlayerName() const; @@ -1224,6 +1234,7 @@ private: AccountTypes _security; bool _skipQueue; uint32 _accountId; + rbac::RBACData* _RBACData; std::string _accountName; uint32 _accountFlags; uint8 m_expansion; diff --git a/src/server/game/Server/WorldSessionMgr.cpp b/src/server/game/Server/WorldSessionMgr.cpp index b43099669..8f5d40325 100644 --- a/src/server/game/Server/WorldSessionMgr.cpp +++ b/src/server/game/Server/WorldSessionMgr.cpp @@ -17,6 +17,7 @@ #include "Chat.h" #include "ChatPackets.h" +#include "RBAC.h" #include "GameTime.h" #include "Metric.h" #include "Player.h" @@ -323,7 +324,7 @@ void WorldSessionMgr::AddSession_(WorldSession* session) // don't count this session when checking player limit --Sessions; - if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(session->GetSecurity()) && !session->CanSkipQueue() && !HasRecentlyDisconnected(session)) + if (pLimit > 0 && Sessions >= pLimit && !session->HasPermission(rbac::RBAC_PERM_SKIP_QUEUE) && !session->CanSkipQueue() && !HasRecentlyDisconnected(session)) { AddQueuedPlayer(session); UpdateMaxSessionCounters(); @@ -390,7 +391,7 @@ void WorldSessionMgr::SendGlobalGMMessage(WorldPacket const* packet, WorldSessio itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld() && itr->second != self && - !AccountMgr::IsPlayerAccount(itr->second->GetSecurity()) && + itr->second->HasPermission(rbac::RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE) && (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) { itr->second->SendPacket(packet); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index cf809ba0a..e4ca47d10 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -31,6 +31,7 @@ #include "World.h" #include "WorldSession.h" #include "WorldSessionMgr.h" +#include "RBAC.h" #include "zlib.h" #include @@ -763,7 +764,7 @@ bool WorldSocket::HandlePing(WorldPacket& recvPacket) { std::unique_lock sessionGuard(_worldSessionLock); - if (_worldSession && AccountMgr::IsPlayerAccount(_worldSession->GetSecurity())) + if (_worldSession && !_worldSession->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_OVERSPEED_PING)) { LOG_ERROR("network", "WorldSocket::HandlePing: {} kicked for over-speed pings (address: {})", _worldSession->GetPlayerInfo(), GetRemoteIpAddress().to_string()); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 1113d6c90..b36c34d45 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -42,6 +42,7 @@ #include "OutdoorPvPMgr.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "ReputationMgr.h" #include "ScriptMgr.h" #include "SharedDefines.h" @@ -2900,6 +2901,14 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, true); + if (item_owner != p_caster && p_caster->GetSession()->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) + { + LOG_GM(p_caster->GetSession()->GetAccountId(), "GM {} (Account: {}) enchanting(perm): {} (SpellID: {} EncID: {}) on {}'s item: {} (Entry: {})", + p_caster->GetName(), p_caster->GetSession()->GetAccountId(), + m_spellInfo->SpellName[0], m_spellInfo->Id, enchant_id, + item_owner->GetName(), itemTarget->GetTemplate()->Name1, itemTarget->GetEntry()); + } + item_owner->RemoveTradeableItem(itemTarget); itemTarget->ClearSoulboundTradeable(item_owner); } @@ -2947,6 +2956,15 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex) if (!item_owner) return; + Player* p_caster = m_caster->ToPlayer(); + if (item_owner != p_caster && p_caster->GetSession()->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) + { + LOG_GM(p_caster->GetSession()->GetAccountId(), "GM {} (Account: {}) enchanting(prismatic): {} (SpellID: {} EncID: {}) on {}'s item: {} (Entry: {})", + p_caster->GetName(), p_caster->GetSession()->GetAccountId(), + m_spellInfo->SpellName[0], m_spellInfo->Id, enchant_id, + item_owner->GetName(), itemTarget->GetTemplate()->Name1, itemTarget->GetEntry()); + } + // remove old enchanting before applying new if equipped item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, false); @@ -3096,6 +3114,14 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true); + if (item_owner != p_caster && p_caster->GetSession()->HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) + { + LOG_GM(p_caster->GetSession()->GetAccountId(), "GM {} (Account: {}) enchanting(temp): {} (SpellID: {} EncID: {}) on {}'s item: {} (Entry: {})", + p_caster->GetName(), p_caster->GetSession()->GetAccountId(), + m_spellInfo->SpellName[0], m_spellInfo->Id, enchant_id, + item_owner->GetName(), itemTarget->GetTemplate()->Name1, itemTarget->GetEntry()); + } + item_owner->RemoveTradeableItem(itemTarget); itemTarget->ClearSoulboundTradeable(item_owner); } diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 03e70e55c..b0c808785 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -110,6 +110,7 @@ public: virtual void ResetEventSeasonalQuests(uint16 event_id) = 0; [[nodiscard]] virtual std::string const& GetRealmName() const = 0; virtual void SetRealmName(std::string name) = 0; + virtual void ReloadRBAC() = 0; }; #endif //AZEROTHCORE_IWORLD_H diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 72b8004e0..85b3871a3 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -469,6 +469,9 @@ void World::SetInitialWorldSettings() LOG_INFO("server.loading", ">> Localization Strings loaded in {} ms", GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); + LOG_INFO("server.loading", "Loading Account Roles and Permissions..."); + sAccountMgr->LoadRBAC(); + LOG_INFO("server.loading", "Loading Page Texts..."); sObjectMgr->LoadPageTexts(); @@ -1741,6 +1744,16 @@ void World::ResetEventSeasonalQuests(uint16 event_id) itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id); } +void World::ReloadRBAC() +{ + // Passive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded + LOG_INFO("rbac", "World::ReloadRBAC()"); + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) + if (WorldSession* session = itr->second) + session->InvalidateRBACData(); +} + void World::ResetRandomBG() { LOG_DEBUG("server.worldserver", "Random BG status reset for all characters."); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index d792b4d8c..b0499a741 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -235,6 +235,7 @@ public: [[nodiscard]] uint32 GetCleaningFlags() const override { return _cleaningFlags; } void SetCleaningFlags(uint32 flags) override { _cleaningFlags = flags; } void ResetEventSeasonalQuests(uint16 event_id) override; + void ReloadRBAC() override; [[nodiscard]] std::string const& GetRealmName() const override { return _realmName; } // pussywizard void SetRealmName(std::string name) override { _realmName = name; } // pussywizard diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index ad9f1f66e..9c37eff54 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -23,6 +23,7 @@ #include "CryptoGenerics.h" #include "IPLocation.h" #include "Player.h" +#include "RBAC.h" #include "Realm.h" #include "ScriptMgr.h" #include "SecretMgr.h" @@ -45,42 +46,42 @@ public: { static ChatCommandTable accountSetCommandTable = { - { "addon", HandleAccountSetAddonCommand, SEC_GAMEMASTER, Console::Yes }, - { "gmlevel", HandleAccountSetGmLevelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "password", HandleAccountSetPasswordCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "2fa", HandleAccountSet2FACommand, SEC_PLAYER, Console::Yes }, - { "email", HandleAccountSetEmailCommand, SEC_ADMINISTRATOR, Console::Yes } + { "addon", HandleAccountSetAddonCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON, Console::Yes }, + { "gmlevel", HandleAccountSetGmLevelCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SECLEVEL, Console::Yes }, + { "password", HandleAccountSetPasswordCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD, Console::Yes }, + { "2fa", HandleAccountSet2FACommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_SET, Console::Yes }, + { "email", HandleAccountSetEmailCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_EMAIL, Console::Yes } }; static ChatCommandTable accountLockCommandTable { - { "country", HandleAccountLockCountryCommand, SEC_PLAYER, Console::Yes }, - { "ip", HandleAccountLockIpCommand, SEC_PLAYER, Console::Yes } + { "country", HandleAccountLockCountryCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY, Console::Yes }, + { "ip", HandleAccountLockIpCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_IP, Console::Yes } }; static ChatCommandTable account2faCommandTable { - { "setup", HandleAccount2FASetupCommand, SEC_PLAYER, Console::No }, - { "remove", HandleAccount2FARemoveCommand, SEC_PLAYER, Console::No } + { "setup", HandleAccount2FASetupCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT, Console::No }, + { "remove", HandleAccount2FARemoveCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT, Console::No } }; static ChatCommandTable accountRemoveCommandTable { - { "country", HandleAccountRemoveLockCountryCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "country", HandleAccountRemoveLockCountryCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY, Console::Yes }, }; static ChatCommandTable accountCommandTable = { { "2fa", account2faCommandTable }, - { "addon", HandleAccountAddonCommand, SEC_MODERATOR, Console::No }, - { "create", HandleAccountCreateCommand, SEC_CONSOLE, Console::Yes }, - { "delete", HandleAccountDeleteCommand, SEC_CONSOLE, Console::Yes }, - { "onlinelist", HandleAccountOnlineListCommand, SEC_CONSOLE, Console::Yes }, + { "addon", HandleAccountAddonCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_ADDON, Console::No }, + { "create", HandleAccountCreateCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_CREATE, Console::Yes }, + { "delete", HandleAccountDeleteCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_DELETE, Console::Yes }, + { "onlinelist", HandleAccountOnlineListCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST, Console::Yes }, { "lock", accountLockCommandTable }, { "set", accountSetCommandTable }, - { "password", HandleAccountPasswordCommand, SEC_PLAYER, Console::No }, + { "password", HandleAccountPasswordCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_PASSWORD, Console::No }, { "remove", accountRemoveCommandTable }, - { "", HandleAccountCommand, SEC_PLAYER, Console::No } + { "", HandleAccountCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT, Console::No } }; static ChatCommandTable commandTable = @@ -279,7 +280,7 @@ public: // if email is not specified, use empty string std::string emailStr = email ? email : ""; - AccountOpResult result = AccountMgr::CreateAccount(std::string(accountName), std::string(password), emailStr); + AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password), emailStr); switch (result) { case AOR_OK: @@ -658,6 +659,16 @@ public: { AccountTypes gmLevel = handler->GetSession()->GetSecurity(); handler->PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmLevel)); + + if (handler->GetSession()->HasPermission(rbac::RBAC_PERM_MAY_CHECK_OWN_EMAIL)) + { + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_EMAIL_BY_ID); + stmt->SetData(0, handler->GetSession()->GetAccountId()); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (result) + handler->PSendSysMessage(LANG_COMMAND_EMAIL_OUTPUT, (*result)[0].Get()); + } + return true; } diff --git a/src/server/scripts/Commands/cs_achievement.cpp b/src/server/scripts/Commands/cs_achievement.cpp index 8557f46ae..37963f8aa 100644 --- a/src/server/scripts/Commands/cs_achievement.cpp +++ b/src/server/scripts/Commands/cs_achievement.cpp @@ -20,6 +20,7 @@ #include "CommandScript.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -32,8 +33,8 @@ public: { static ChatCommandTable achievementCommandTable = { - { "add", HandleAchievementAddCommand, SEC_GAMEMASTER, Console::Yes }, - { "checkall", HandleAchievementCheckAllCommand, SEC_ADMINISTRATOR, Console::Yes } + { "add", HandleAchievementAddCommand, rbac::RBAC_PERM_COMMAND_ACHIEVEMENT_ADD, Console::Yes }, + { "checkall", HandleAchievementCheckAllCommand, rbac::RBAC_PERM_COMMAND_ACHIEVEMENT_CHECKALL, Console::Yes } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_arena.cpp b/src/server/scripts/Commands/cs_arena.cpp index 4adb0f736..a2a8f92cf 100644 --- a/src/server/scripts/Commands/cs_arena.cpp +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -15,12 +15,13 @@ * with this program. If not, see . */ -#include "ArenaTeamMgr.h" #include "ArenaSeasonMgr.h" #include "ArenaTeamFilter.h" +#include "ArenaTeamMgr.h" #include "Chat.h" #include "CommandScript.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -33,25 +34,25 @@ public: { static ChatCommandTable arenaSeasonSetCommandTable = { - { "state", HandleArenaSeasonSetStateCommand, SEC_ADMINISTRATOR, Console::Yes } + { "state", HandleArenaSeasonSetStateCommand, rbac::RBAC_PERM_COMMAND_ARENA_SEASON, Console::Yes } }; static ChatCommandTable arenaSeasonCommandTable = { - { "reward", HandleArenaSeasonRewardCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "deleteteams", HandleArenaSeasonDeleteTeamsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "start", HandleArenaSeasonStartCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "reward", HandleArenaSeasonRewardCommand, rbac::RBAC_PERM_COMMAND_ARENA_SEASON_REWARD, Console::Yes }, + { "deleteteams", HandleArenaSeasonDeleteTeamsCommand, rbac::RBAC_PERM_COMMAND_ARENA_SEASON_DELETETEAMS, Console::Yes }, + { "start", HandleArenaSeasonStartCommand, rbac::RBAC_PERM_COMMAND_ARENA_SEASON_START, Console::Yes }, { "set", arenaSeasonSetCommandTable } }; static ChatCommandTable arenaCommandTable = { - { "create", HandleArenaCreateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "disband", HandleArenaDisbandCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "rename", HandleArenaRenameCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "captain", HandleArenaCaptainCommand, SEC_ADMINISTRATOR, Console::No }, - { "info", HandleArenaInfoCommand, SEC_GAMEMASTER, Console::Yes }, - { "lookup", HandleArenaLookupCommand, SEC_GAMEMASTER, Console::Yes }, + { "create", HandleArenaCreateCommand, rbac::RBAC_PERM_COMMAND_ARENA_CREATE, Console::Yes }, + { "disband", HandleArenaDisbandCommand, rbac::RBAC_PERM_COMMAND_ARENA_DISBAND, Console::Yes }, + { "rename", HandleArenaRenameCommand, rbac::RBAC_PERM_COMMAND_ARENA_RENAME, Console::Yes }, + { "captain", HandleArenaCaptainCommand, rbac::RBAC_PERM_COMMAND_ARENA_CAPTAIN, Console::No }, + { "info", HandleArenaInfoCommand, rbac::RBAC_PERM_COMMAND_ARENA_INFO, Console::Yes }, + { "lookup", HandleArenaLookupCommand, rbac::RBAC_PERM_COMMAND_ARENA_LOOKUP, Console::Yes }, { "season", arenaSeasonCommandTable } }; diff --git a/src/server/scripts/Commands/cs_bag.cpp b/src/server/scripts/Commands/cs_bag.cpp index fd365b875..a0567e49c 100644 --- a/src/server/scripts/Commands/cs_bag.cpp +++ b/src/server/scripts/Commands/cs_bag.cpp @@ -19,6 +19,7 @@ #include "CommandScript.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" constexpr std::array itemQualityToString = { @@ -43,7 +44,7 @@ public: { static ChatCommandTable commandTable = { - { "bags clear", HandleBagsClearCommand, SEC_GAMEMASTER, Console::No }, + { "bags clear", HandleBagsClearCommand, rbac::RBAC_PERM_COMMAND_ADDITEM, Console::No }, }; return commandTable; diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index 466364be8..539b60e06 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -25,6 +25,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" /// Ban function modes enum BanMode @@ -49,32 +50,32 @@ public: { static ChatCommandTable unbanCommandTable = { - { "account", HandleUnBanAccountCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "character", HandleUnBanCharacterCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "playeraccount", HandleUnBanAccountByCharCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "ip", HandleUnBanIPCommand, SEC_ADMINISTRATOR, Console::Yes } + { "account", HandleUnBanAccountCommand, rbac::RBAC_PERM_COMMAND_UNBAN_ACCOUNT, Console::Yes }, + { "character", HandleUnBanCharacterCommand, rbac::RBAC_PERM_COMMAND_UNBAN_CHARACTER, Console::Yes }, + { "playeraccount", HandleUnBanAccountByCharCommand, rbac::RBAC_PERM_COMMAND_UNBAN_PLAYERACCOUNT, Console::Yes }, + { "ip", HandleUnBanIPCommand, rbac::RBAC_PERM_COMMAND_UNBAN_IP, Console::Yes } }; static ChatCommandTable banlistCommandTable = { - { "account", HandleBanListAccountCommand, SEC_GAMEMASTER, Console::Yes }, - { "character", HandleBanListCharacterCommand, SEC_GAMEMASTER, Console::Yes }, - { "ip", HandleBanListIPCommand, SEC_GAMEMASTER, Console::Yes } + { "account", HandleBanListAccountCommand, rbac::RBAC_PERM_COMMAND_BANLIST_ACCOUNT, Console::Yes }, + { "character", HandleBanListCharacterCommand, rbac::RBAC_PERM_COMMAND_BANLIST_CHARACTER, Console::Yes }, + { "ip", HandleBanListIPCommand, rbac::RBAC_PERM_COMMAND_BANLIST_IP, Console::Yes } }; static ChatCommandTable baninfoCommandTable = { - { "account", HandleBanInfoAccountCommand, SEC_GAMEMASTER, Console::Yes }, - { "character", HandleBanInfoCharacterCommand, SEC_GAMEMASTER, Console::Yes }, - { "ip", HandleBanInfoIPCommand, SEC_GAMEMASTER, Console::Yes } + { "account", HandleBanInfoAccountCommand, rbac::RBAC_PERM_COMMAND_BANINFO_ACCOUNT, Console::Yes }, + { "character", HandleBanInfoCharacterCommand, rbac::RBAC_PERM_COMMAND_BANINFO_CHARACTER, Console::Yes }, + { "ip", HandleBanInfoIPCommand, rbac::RBAC_PERM_COMMAND_BANINFO_IP, Console::Yes } }; static ChatCommandTable banCommandTable = { - { "account", HandleBanAccountCommand, SEC_GAMEMASTER, Console::Yes }, - { "character", HandleBanCharacterCommand, SEC_GAMEMASTER, Console::Yes }, - { "playeraccount",HandleBanAccountByCharCommand, SEC_GAMEMASTER, Console::Yes }, - { "ip", HandleBanIPCommand, SEC_GAMEMASTER, Console::Yes } + { "account", HandleBanAccountCommand, rbac::RBAC_PERM_COMMAND_BAN_ACCOUNT, Console::Yes }, + { "character", HandleBanCharacterCommand, rbac::RBAC_PERM_COMMAND_BAN_CHARACTER, Console::Yes }, + { "playeraccount",HandleBanAccountByCharCommand, rbac::RBAC_PERM_COMMAND_BAN_PLAYERACCOUNT, Console::Yes }, + { "ip", HandleBanIPCommand, rbac::RBAC_PERM_COMMAND_BAN_IP, Console::Yes } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_bf.cpp b/src/server/scripts/Commands/cs_bf.cpp index 815f1fb20..3e8d0502b 100644 --- a/src/server/scripts/Commands/cs_bf.cpp +++ b/src/server/scripts/Commands/cs_bf.cpp @@ -18,10 +18,11 @@ #include "BattlefieldMgr.h" #include "Chat.h" #include "CommandScript.h" -#include "Language.h" #include "GameTime.h" +#include "Language.h" #include "ObjectAccessor.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -34,12 +35,12 @@ public: { static ChatCommandTable battlefieldcommandTable = { - { "start", HandleBattlefieldStart, SEC_ADMINISTRATOR, Console::Yes }, - { "stop", HandleBattlefieldEnd, SEC_ADMINISTRATOR, Console::Yes }, - { "switch", HandleBattlefieldSwitch, SEC_ADMINISTRATOR, Console::Yes }, - { "timer", HandleBattlefieldTimer, SEC_ADMINISTRATOR, Console::Yes }, - { "enable", HandleBattlefieldEnable, SEC_ADMINISTRATOR, Console::Yes }, - { "queue", HandleBattlefieldQueue, SEC_GAMEMASTER, Console::Yes } + { "start", HandleBattlefieldStart, rbac::RBAC_PERM_COMMAND_BF_START, Console::Yes }, + { "stop", HandleBattlefieldEnd, rbac::RBAC_PERM_COMMAND_BF_STOP, Console::Yes }, + { "switch", HandleBattlefieldSwitch, rbac::RBAC_PERM_COMMAND_BF_SWITCH, Console::Yes }, + { "timer", HandleBattlefieldTimer, rbac::RBAC_PERM_COMMAND_BF_TIMER, Console::Yes }, + { "enable", HandleBattlefieldEnable, rbac::RBAC_PERM_COMMAND_BF_ENABLE, Console::Yes }, + { "queue", HandleBattlefieldQueue, rbac::RBAC_PERM_COMMAND_BF_QUEUE, Console::Yes } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_cache.cpp b/src/server/scripts/Commands/cs_cache.cpp index 2e05f5472..6f7899824 100644 --- a/src/server/scripts/Commands/cs_cache.cpp +++ b/src/server/scripts/Commands/cs_cache.cpp @@ -20,6 +20,7 @@ #include "Group.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -32,9 +33,9 @@ public: { static ChatCommandTable cacheCommandTable = { - { "info", HandleCacheInfoCommand, SEC_GAMEMASTER, Console::Yes }, - { "delete", HandleCacheDeleteCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "refresh", HandleCacheRefreshCommand, SEC_GAMEMASTER, Console::Yes } + { "info", HandleCacheInfoCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "delete", HandleCacheDeleteCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "refresh", HandleCacheRefreshCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp index 654e2cf00..56c604a72 100644 --- a/src/server/scripts/Commands/cs_cast.cpp +++ b/src/server/scripts/Commands/cs_cast.cpp @@ -20,6 +20,7 @@ #include "Creature.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" #include "SpellInfo.h" #include "SpellMgr.h" @@ -34,12 +35,12 @@ public: { static ChatCommandTable castCommandTable = { - { "back", HandleCastBackCommand, SEC_GAMEMASTER, Console::No }, - { "dist", HandleCastDistCommand, SEC_GAMEMASTER, Console::No }, - { "self", HandleCastSelfCommand, SEC_GAMEMASTER, Console::No }, - { "target", HandleCastTargetCommad, SEC_GAMEMASTER, Console::No }, - { "dest", HandleCastDestCommand, SEC_GAMEMASTER, Console::No }, - { "", HandleCastCommand, SEC_GAMEMASTER, Console::No } + { "back", HandleCastBackCommand, rbac::RBAC_PERM_COMMAND_CAST_BACK, Console::No }, + { "dist", HandleCastDistCommand, rbac::RBAC_PERM_COMMAND_CAST_DIST, Console::No }, + { "self", HandleCastSelfCommand, rbac::RBAC_PERM_COMMAND_CAST_SELF, Console::No }, + { "target", HandleCastTargetCommad, rbac::RBAC_PERM_COMMAND_CAST_TARGET, Console::No }, + { "dest", HandleCastDestCommand, rbac::RBAC_PERM_COMMAND_CAST_DEST, Console::No }, + { "", HandleCastCommand, rbac::RBAC_PERM_COMMAND_CAST, Console::No } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 11fc6d312..464b70512 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -25,6 +25,7 @@ #include "ObjectMgr.h" #include "Player.h" #include "PlayerDump.h" +#include "RBAC.h" #include "ReputationMgr.h" #include "Timer.h" #include "World.h" @@ -41,44 +42,45 @@ public: { static ChatCommandTable pdumpCommandTable = { - { "load", HandlePDumpLoadCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "write", HandlePDumpWriteCommand, SEC_ADMINISTRATOR, Console::Yes } + { "copy", HandlePDumpCopyCommand, rbac::RBAC_PERM_COMMAND_PDUMP_COPY, Console::Yes }, + { "load", HandlePDumpLoadCommand, rbac::RBAC_PERM_COMMAND_PDUMP_LOAD, Console::Yes }, + { "write", HandlePDumpWriteCommand, rbac::RBAC_PERM_COMMAND_PDUMP_WRITE, Console::Yes } }; static ChatCommandTable characterDeletedCommandTable = { - { "delete", HandleCharacterDeletedDeleteCommand, SEC_CONSOLE, Console::Yes }, - { "list", HandleCharacterDeletedListCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "restore", HandleCharacterDeletedRestoreCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "purge", HandleCharacterDeletedPurgeCommand, SEC_CONSOLE, Console::Yes } + { "delete", HandleCharacterDeletedDeleteCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE, Console::Yes }, + { "list", HandleCharacterDeletedListCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST, Console::Yes }, + { "restore", HandleCharacterDeletedRestoreCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE, Console::Yes }, + { "purge", HandleCharacterDeletedPurgeCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD, Console::Yes } }; static ChatCommandTable characterCheckCommandTable = { - { "bank", HandleCharacterCheckBankCommand, SEC_GAMEMASTER, Console::Yes }, - { "bag", HandleCharacterCheckBagCommand, SEC_GAMEMASTER, Console::Yes }, - { "profession", HandleCharacterCheckProfessionCommand, SEC_GAMEMASTER, Console::Yes } + { "bank", HandleCharacterCheckBankCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CHECK_BANK, Console::Yes }, + { "bag", HandleCharacterCheckBagCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CHECK_BAG, Console::Yes }, + { "profession", HandleCharacterCheckProfessionCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CHECK_PROFESSION, Console::Yes } }; static ChatCommandTable characterCommandTable = { - { "customize", HandleCharacterCustomizeCommand, SEC_GAMEMASTER, Console::Yes }, - { "changefaction", HandleCharacterChangeFactionCommand, SEC_GAMEMASTER, Console::Yes }, - { "changerace", HandleCharacterChangeRaceCommand, SEC_GAMEMASTER, Console::Yes }, - { "changeaccount", HandleCharacterChangeAccountCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "customize", HandleCharacterCustomizeCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE, Console::Yes }, + { "changefaction", HandleCharacterChangeFactionCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION, Console::Yes }, + { "changerace", HandleCharacterChangeRaceCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGERACE, Console::Yes }, + { "changeaccount", HandleCharacterChangeAccountCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT, Console::Yes }, { "check", characterCheckCommandTable }, - { "erase", HandleCharacterEraseCommand, SEC_CONSOLE, Console::Yes }, + { "erase", HandleCharacterEraseCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_ERASE, Console::Yes }, { "deleted", characterDeletedCommandTable }, - { "level", HandleCharacterLevelCommand, SEC_GAMEMASTER, Console::Yes }, - { "rename", HandleCharacterRenameCommand, SEC_GAMEMASTER, Console::Yes }, - { "reputation", HandleCharacterReputationCommand, SEC_GAMEMASTER, Console::Yes }, - { "titles", HandleCharacterTitlesCommand, SEC_GAMEMASTER, Console::Yes } + { "level", HandleCharacterLevelCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_LEVEL, Console::Yes }, + { "rename", HandleCharacterRenameCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_RENAME, Console::Yes }, + { "reputation", HandleCharacterReputationCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_REPUTATION, Console::Yes }, + { "titles", HandleCharacterTitlesCommand, rbac::RBAC_PERM_COMMAND_CHARACTER_TITLES, Console::Yes } }; static ChatCommandTable commandTable = { { "character", characterCommandTable }, - { "levelup", HandleLevelUpCommand, SEC_GAMEMASTER, Console::No }, + { "levelup", HandleLevelUpCommand, rbac::RBAC_PERM_COMMAND_LEVELUP, Console::No }, { "pdump", pdumpCommandTable } }; diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp index 2b067ab78..880dc772c 100644 --- a/src/server/scripts/Commands/cs_cheat.cpp +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -19,6 +19,8 @@ #include "CommandScript.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" +#include "WorldSession.h" using namespace Acore::ChatCommands; @@ -31,14 +33,14 @@ public: { static ChatCommandTable cheatCommandTable = { - { "god", HandleGodModeCheatCommand, SEC_GAMEMASTER, Console::No }, - { "casttime", HandleCasttimeCheatCommand, SEC_GAMEMASTER, Console::No }, - { "cooldown", HandleCoolDownCheatCommand, SEC_GAMEMASTER, Console::No }, - { "power", HandlePowerCheatCommand, SEC_GAMEMASTER, Console::No }, - { "waterwalk", HandleWaterWalkCheatCommand, SEC_GAMEMASTER, Console::No }, - { "status", HandleCheatStatusCommand, SEC_GAMEMASTER, Console::No }, - { "taxi", HandleTaxiCheatCommand, SEC_GAMEMASTER, Console::No }, - { "explore", HandleExploreCheatCommand, SEC_GAMEMASTER, Console::No } + { "god", HandleGodModeCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_GOD, Console::No }, + { "casttime", HandleCasttimeCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_CASTTIME, Console::No }, + { "cooldown", HandleCoolDownCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_COOLDOWN, Console::No }, + { "power", HandlePowerCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_POWER, Console::No }, + { "waterwalk", HandleWaterWalkCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_WATERWALK, Console::No }, + { "status", HandleCheatStatusCommand, rbac::RBAC_PERM_COMMAND_CHEAT_STATUS, Console::No }, + { "taxi", HandleTaxiCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_TAXI, Console::No }, + { "explore", HandleExploreCheatCommand, rbac::RBAC_PERM_COMMAND_CHEAT_EXPLORE, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 8c80529d9..401446077 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -37,6 +37,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "PoolMgr.h" +#include "RBAC.h" #include "RaceMgr.h" #include "ScriptMgr.h" #include "Transport.h" @@ -57,71 +58,71 @@ public: { static ChatCommandTable debugPlayCommandTable = { - { "cinematic", HandleDebugPlayCinematicCommand, SEC_ADMINISTRATOR, Console::No }, - { "movie", HandleDebugPlayMovieCommand, SEC_ADMINISTRATOR, Console::No }, - { "sound", HandleDebugPlaySoundCommand, SEC_ADMINISTRATOR, Console::No }, - { "music", HandleDebugPlayMusicCommand, SEC_ADMINISTRATOR, Console::No }, - { "visual", HandleDebugVisualCommand, SEC_ADMINISTRATOR, Console::No } + { "cinematic", HandleDebugPlayCinematicCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "movie", HandleDebugPlayMovieCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "sound", HandleDebugPlaySoundCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "music", HandleDebugPlayMusicCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "visual", HandleDebugVisualCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No } }; static ChatCommandTable debugSendCommandTable = { - { "buyerror", HandleDebugSendBuyErrorCommand, SEC_ADMINISTRATOR, Console::No }, - { "channelnotify", HandleDebugSendChannelNotifyCommand, SEC_ADMINISTRATOR, Console::No }, - { "chatmessage", HandleDebugSendChatMsgCommand, SEC_ADMINISTRATOR, Console::No }, - { "equiperror", HandleDebugSendEquipErrorCommand, SEC_ADMINISTRATOR, Console::No }, - { "largepacket", HandleDebugSendLargePacketCommand, SEC_ADMINISTRATOR, Console::No }, - { "opcode", HandleDebugSendOpcodeCommand, SEC_ADMINISTRATOR, Console::No }, - { "qpartymsg", HandleDebugSendQuestPartyMsgCommand, SEC_ADMINISTRATOR, Console::No }, - { "qinvalidmsg", HandleDebugSendQuestInvalidMsgCommand, SEC_ADMINISTRATOR, Console::No }, - { "sellerror", HandleDebugSendSellErrorCommand, SEC_ADMINISTRATOR, Console::No }, - { "setphaseshift", HandleDebugSendSetPhaseShiftCommand, SEC_ADMINISTRATOR, Console::No }, - { "spellfail", HandleDebugSendSpellFailCommand, SEC_ADMINISTRATOR, Console::No } + { "buyerror", HandleDebugSendBuyErrorCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "channelnotify", HandleDebugSendChannelNotifyCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "chatmessage", HandleDebugSendChatMsgCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "equiperror", HandleDebugSendEquipErrorCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "largepacket", HandleDebugSendLargePacketCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "opcode", HandleDebugSendOpcodeCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "qpartymsg", HandleDebugSendQuestPartyMsgCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "qinvalidmsg", HandleDebugSendQuestInvalidMsgCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "sellerror", HandleDebugSendSellErrorCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "setphaseshift", HandleDebugSendSetPhaseShiftCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "spellfail", HandleDebugSendSpellFailCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No } }; static ChatCommandTable debugCommandTable = { - { "setbit", HandleDebugSet32BitCommand, SEC_ADMINISTRATOR, Console::No }, - { "threat", HandleDebugThreatListCommand, SEC_ADMINISTRATOR, Console::No }, - { "threatinfo", HandleDebugThreatInfoCommand, SEC_ADMINISTRATOR, Console::No }, - { "combat", HandleDebugCombatListCommand, SEC_ADMINISTRATOR, Console::No }, - { "hostile", HandleDebugHostileRefListCommand, SEC_ADMINISTRATOR, Console::No }, - { "anim", HandleDebugAnimCommand, SEC_ADMINISTRATOR, Console::No }, - { "arena", HandleDebugArenaCommand, SEC_ADMINISTRATOR, Console::No }, - { "bg", HandleDebugBattlegroundCommand, SEC_ADMINISTRATOR, Console::Yes}, - { "cooldown", HandleDebugCooldownCommand, SEC_ADMINISTRATOR, Console::No }, - { "getitemstate", HandleDebugGetItemStateCommand, SEC_ADMINISTRATOR, Console::No }, - { "lootrecipient", HandleDebugGetLootRecipientCommand, SEC_ADMINISTRATOR, Console::No }, - { "getvalue", HandleDebugGetValueCommand, SEC_ADMINISTRATOR, Console::No }, - { "getitemvalue", HandleDebugGetItemValueCommand, SEC_ADMINISTRATOR, Console::No }, - { "Mod32Value", HandleDebugMod32ValueCommand, SEC_ADMINISTRATOR, Console::No }, + { "setbit", HandleDebugSet32BitCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "threat", HandleDebugThreatListCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "threatinfo", HandleDebugThreatInfoCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "combat", HandleDebugCombatListCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "hostile", HandleDebugHostileRefListCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "anim", HandleDebugAnimCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "arena", HandleDebugArenaCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "bg", HandleDebugBattlegroundCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes}, + { "cooldown", HandleDebugCooldownCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "getitemstate", HandleDebugGetItemStateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "lootrecipient", HandleDebugGetLootRecipientCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "getvalue", HandleDebugGetValueCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "getitemvalue", HandleDebugGetItemValueCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "Mod32Value", HandleDebugMod32ValueCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, { "play", debugPlayCommandTable }, { "send", debugSendCommandTable }, - { "setaurastate", HandleDebugSetAuraStateCommand, SEC_ADMINISTRATOR, Console::No }, - { "setitemvalue", HandleDebugSetItemValueCommand, SEC_ADMINISTRATOR, Console::No }, - { "setvalue", HandleDebugSetValueCommand, SEC_ADMINISTRATOR, Console::No }, - { "spawnvehicle", HandleDebugSpawnVehicleCommand, SEC_ADMINISTRATOR, Console::No }, - { "setvid", HandleDebugSetVehicleIdCommand, SEC_ADMINISTRATOR, Console::No }, - { "entervehicle", HandleDebugEnterVehicleCommand, SEC_ADMINISTRATOR, Console::No }, - { "uws", HandleDebugUpdateWorldStateCommand, SEC_ADMINISTRATOR, Console::No }, - { "update", HandleDebugUpdateCommand, SEC_ADMINISTRATOR, Console::No }, - { "itemexpire", HandleDebugItemExpireCommand, SEC_ADMINISTRATOR, Console::No }, - { "areatriggers", HandleDebugAreaTriggersCommand, SEC_ADMINISTRATOR, Console::No }, - { "lfg", HandleDebugDungeonFinderCommand, SEC_ADMINISTRATOR, Console::Yes}, - { "loot", HandleDebugLootCommand, SEC_GAMEMASTER, Console::Yes}, - { "los", HandleDebugLoSCommand, SEC_ADMINISTRATOR, Console::No }, - { "moveflags", HandleDebugMoveflagsCommand, SEC_ADMINISTRATOR, Console::No }, - { "unitstate", HandleDebugUnitStateCommand, SEC_ADMINISTRATOR, Console::No }, - { "objectcount", HandleDebugObjectCountCommand, SEC_ADMINISTRATOR, Console::Yes}, - { "dummy", HandleDebugDummyCommand, SEC_ADMINISTRATOR, Console::No }, - { "mapdata", HandleDebugMapDataCommand, SEC_ADMINISTRATOR, Console::No }, - { "boundary", HandleDebugBoundaryCommand, SEC_ADMINISTRATOR, Console::No }, - { "visibilitydata", HandleDebugVisibilityDataCommand, SEC_ADMINISTRATOR, Console::No }, - { "factionchange", HandleDebugFactionChangeCommand, SEC_ADMINISTRATOR, Console::Yes}, - { "zonestats", HandleDebugZoneStatsCommand, SEC_MODERATOR, Console::Yes} + { "setaurastate", HandleDebugSetAuraStateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "setitemvalue", HandleDebugSetItemValueCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "setvalue", HandleDebugSetValueCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "spawnvehicle", HandleDebugSpawnVehicleCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "setvid", HandleDebugSetVehicleIdCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "entervehicle", HandleDebugEnterVehicleCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "uws", HandleDebugUpdateWorldStateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "update", HandleDebugUpdateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "itemexpire", HandleDebugItemExpireCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "areatriggers", HandleDebugAreaTriggersCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "lfg", HandleDebugDungeonFinderCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes}, + { "loot", HandleDebugLootCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes}, + { "los", HandleDebugLoSCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "moveflags", HandleDebugMoveflagsCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "unitstate", HandleDebugUnitStateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "objectcount", HandleDebugObjectCountCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes}, + { "dummy", HandleDebugDummyCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "mapdata", HandleDebugMapDataCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "boundary", HandleDebugBoundaryCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "visibilitydata", HandleDebugVisibilityDataCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "factionchange", HandleDebugFactionChangeCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes}, + { "zonestats", HandleDebugZoneStatsCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes} }; static ChatCommandTable commandTable = { { "debug", debugCommandTable }, - { "wpgps", HandleWPGPSCommand, SEC_ADMINISTRATOR, Console::No } + { "wpgps", HandleWPGPSCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_deserter.cpp b/src/server/scripts/Commands/cs_deserter.cpp index 860046d10..1e2e64066 100644 --- a/src/server/scripts/Commands/cs_deserter.cpp +++ b/src/server/scripts/Commands/cs_deserter.cpp @@ -27,6 +27,7 @@ #include "GroupMgr.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" #include "SpellAuras.h" using namespace Acore::ChatCommands; @@ -50,15 +51,15 @@ public: { static ChatCommandTable deserterInstanceCommandTable = { - { "add", HandleDeserterInstanceAdd, SEC_ADMINISTRATOR, Console::Yes }, - { "remove all", HandleDeserterInstanceRemoveAll, SEC_ADMINISTRATOR, Console::Yes }, - { "remove", HandleDeserterInstanceRemove, SEC_ADMINISTRATOR, Console::Yes } + { "add", HandleDeserterInstanceAdd, rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_ADD, Console::Yes }, + { "remove all", HandleDeserterInstanceRemoveAll, rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE, Console::Yes }, + { "remove", HandleDeserterInstanceRemove, rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE, Console::Yes } }; static ChatCommandTable deserterBGCommandTable = { - { "add", HandleDeserterBGAdd, SEC_ADMINISTRATOR, Console::Yes }, - { "remove all", HandleDeserterBGRemoveAll, SEC_ADMINISTRATOR, Console::Yes }, - { "remove", HandleDeserterBGRemove, SEC_ADMINISTRATOR, Console::Yes } + { "add", HandleDeserterBGAdd, rbac::RBAC_PERM_COMMAND_DESERTER_BG_ADD, Console::Yes }, + { "remove all", HandleDeserterBGRemoveAll, rbac::RBAC_PERM_COMMAND_DESERTER_BG_REMOVE, Console::Yes }, + { "remove", HandleDeserterBGRemove, rbac::RBAC_PERM_COMMAND_DESERTER_BG_REMOVE, Console::Yes } }; static ChatCommandTable deserterCommandTable = diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp index 2846f59a4..c0e35098d 100644 --- a/src/server/scripts/Commands/cs_disable.cpp +++ b/src/server/scripts/Commands/cs_disable.cpp @@ -21,6 +21,8 @@ #include "Language.h" #include "ObjectMgr.h" #include "OutdoorPvP.h" +#include "Player.h" +#include "RBAC.h" #include "SpellMgr.h" using namespace Acore::ChatCommands; @@ -34,21 +36,21 @@ public: { static ChatCommandTable removeDisableCommandTable = { - { "spell", HandleRemoveDisableSpellCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest", HandleRemoveDisableQuestCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "map", HandleRemoveDisableMapCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "battleground", HandleRemoveDisableBattlegroundCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "outdoorpvp", HandleRemoveDisableOutdoorPvPCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "vmap", HandleRemoveDisableVmapCommand, SEC_ADMINISTRATOR, Console::Yes } + { "spell", HandleRemoveDisableSpellCommand, rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL, Console::Yes }, + { "quest", HandleRemoveDisableQuestCommand, rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST, Console::Yes }, + { "map", HandleRemoveDisableMapCommand, rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP, Console::Yes }, + { "battleground", HandleRemoveDisableBattlegroundCommand, rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND, Console::Yes }, + { "outdoorpvp", HandleRemoveDisableOutdoorPvPCommand, rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP, Console::Yes }, + { "vmap", HandleRemoveDisableVmapCommand, rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP, Console::Yes } }; static ChatCommandTable addDisableCommandTable = { - { "spell", HandleAddDisableSpellCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest", HandleAddDisableQuestCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "map", HandleAddDisableMapCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "battleground", HandleAddDisableBattlegroundCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "outdoorpvp", HandleAddDisableOutdoorPvPCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "vmap", HandleAddDisableVmapCommand, SEC_ADMINISTRATOR, Console::Yes } + { "spell", HandleAddDisableSpellCommand, rbac::RBAC_PERM_COMMAND_DISABLE_ADD_SPELL, Console::Yes }, + { "quest", HandleAddDisableQuestCommand, rbac::RBAC_PERM_COMMAND_DISABLE_ADD_QUEST, Console::Yes }, + { "map", HandleAddDisableMapCommand, rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MAP, Console::Yes }, + { "battleground", HandleAddDisableBattlegroundCommand, rbac::RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND, Console::Yes }, + { "outdoorpvp", HandleAddDisableOutdoorPvPCommand, rbac::RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP, Console::Yes }, + { "vmap", HandleAddDisableVmapCommand, rbac::RBAC_PERM_COMMAND_DISABLE_ADD_VMAP, Console::Yes } }; static ChatCommandTable disableCommandTable = { diff --git a/src/server/scripts/Commands/cs_event.cpp b/src/server/scripts/Commands/cs_event.cpp index 1b101e086..97d44cb60 100644 --- a/src/server/scripts/Commands/cs_event.cpp +++ b/src/server/scripts/Commands/cs_event.cpp @@ -20,6 +20,7 @@ #include "GameEventMgr.h" #include "GameTime.h" #include "Language.h" +#include "RBAC.h" #include "Timer.h" using namespace Acore::ChatCommands; @@ -35,10 +36,10 @@ public: { static ChatCommandTable eventCommandTable = { - { "activelist", HandleEventActiveListCommand, SEC_GAMEMASTER, Console::Yes }, - { "start", HandleEventStartCommand, SEC_GAMEMASTER, Console::Yes }, - { "stop", HandleEventStopCommand, SEC_GAMEMASTER, Console::Yes }, - { "info", HandleEventInfoCommand, SEC_GAMEMASTER, Console::Yes } + { "activelist", HandleEventActiveListCommand, rbac::RBAC_PERM_COMMAND_EVENT_ACTIVELIST, Console::Yes }, + { "start", HandleEventStartCommand, rbac::RBAC_PERM_COMMAND_EVENT_START, Console::Yes }, + { "stop", HandleEventStopCommand, rbac::RBAC_PERM_COMMAND_EVENT_STOP, Console::Yes }, + { "info", HandleEventInfoCommand, rbac::RBAC_PERM_COMMAND_EVENT_INFO, Console::Yes } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_gear.cpp b/src/server/scripts/Commands/cs_gear.cpp index b67fc456d..c2ba986e2 100644 --- a/src/server/scripts/Commands/cs_gear.cpp +++ b/src/server/scripts/Commands/cs_gear.cpp @@ -19,6 +19,8 @@ #include "CommandScript.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" +#include "WorldSession.h" using namespace Acore::ChatCommands; @@ -31,8 +33,8 @@ public: { static ChatCommandTable gearCommandTable = { - { "repair", HandleGearRepairCommand, SEC_GAMEMASTER, Console::No }, - { "stats", HandleGearStatsCommand, SEC_PLAYER, Console::No } + { "repair", HandleGearRepairCommand, rbac::RBAC_PERM_COMMAND_GEAR_REPAIR, Console::No }, + { "stats", HandleGearStatsCommand, rbac::RBAC_PERM_COMMAND_GEAR_STATS, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index b1379ff24..0138f65c1 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -23,6 +23,7 @@ #include "ObjectAccessor.h" #include "Opcodes.h" #include "Player.h" +#include "RBAC.h" #include "Realm.h" #include "World.h" #include "WorldSession.h" @@ -38,14 +39,14 @@ public: { static ChatCommandTable gmCommandTable = { - { "chat", HandleGMChatCommand, SEC_GAMEMASTER, Console::No }, - { "fly", HandleGMFlyCommand, SEC_GAMEMASTER, Console::No }, - { "ingame", HandleGMListIngameCommand, SEC_PLAYER, Console::Yes }, - { "list", HandleGMListFullCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "visible", HandleGMVisibleCommand, SEC_GAMEMASTER, Console::No }, - { "on", HandleGMOnCommand, SEC_MODERATOR, Console::No }, - { "off", HandleGMOffCommand, SEC_MODERATOR, Console::No }, - { "spectator", HandleGMSpectatorCommand, SEC_GAMEMASTER, Console::No }, + { "chat", HandleGMChatCommand, rbac::RBAC_PERM_COMMAND_GM_CHAT, Console::No }, + { "fly", HandleGMFlyCommand, rbac::RBAC_PERM_COMMAND_GM_FLY, Console::No }, + { "ingame", HandleGMListIngameCommand, rbac::RBAC_PERM_COMMAND_GM_INGAME, Console::Yes }, + { "list", HandleGMListFullCommand, rbac::RBAC_PERM_COMMAND_GM_LIST, Console::Yes }, + { "visible", HandleGMVisibleCommand, rbac::RBAC_PERM_COMMAND_GM_VISIBLE, Console::No }, + { "on", HandleGMOnCommand, rbac::RBAC_PERM_COMMAND_GM, Console::No }, + { "off", HandleGMOffCommand, rbac::RBAC_PERM_COMMAND_GM, Console::No }, + { "spectator", HandleGMSpectatorCommand, rbac::RBAC_PERM_COMMAND_GM, Console::No }, }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 88a7df172..7f575ac17 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -22,6 +22,7 @@ #include "MapMgr.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "TicketMgr.h" #include "Transport.h" @@ -39,19 +40,19 @@ public: { static ChatCommandTable goCommandTable = { - { "creature", HandleGoCreatureSpawnIdCommand, SEC_MODERATOR, Console::No }, - { "creature id", HandleGoCreatureCIdCommand, SEC_MODERATOR, Console::No }, - { "creature name", HandleGoCreatureNameCommand, SEC_MODERATOR, Console::No }, - { "gameobject", HandleGoGameObjectSpawnIdCommand, SEC_MODERATOR, Console::No }, - { "gameobject id", HandleGoGameObjectGOIdCommand, SEC_MODERATOR, Console::No }, - { "graveyard", HandleGoGraveyardCommand, SEC_MODERATOR, Console::No }, - { "grid", HandleGoGridCommand, SEC_MODERATOR, Console::No }, - { "taxinode", HandleGoTaxinodeCommand, SEC_MODERATOR, Console::No }, - { "trigger", HandleGoTriggerCommand, SEC_MODERATOR, Console::No }, - { "zonexy", HandleGoZoneXYCommand, SEC_MODERATOR, Console::No }, - { "xyz", HandleGoXYZCommand, SEC_MODERATOR, Console::No }, - { "ticket", HandleGoTicketCommand, SEC_GAMEMASTER, Console::No }, - { "quest", HandleGoQuestCommand, SEC_MODERATOR, Console::No }, + { "creature", HandleGoCreatureSpawnIdCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "creature id", HandleGoCreatureCIdCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "creature name", HandleGoCreatureNameCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "gameobject", HandleGoGameObjectSpawnIdCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "gameobject id", HandleGoGameObjectGOIdCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "graveyard", HandleGoGraveyardCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "grid", HandleGoGridCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "taxinode", HandleGoTaxinodeCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "trigger", HandleGoTriggerCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "zonexy", HandleGoZoneXYCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "xyz", HandleGoXYZCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "ticket", HandleGoTicketCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, + { "quest", HandleGoQuestCommand, rbac::RBAC_PERM_COMMAND_GO, Console::No }, }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 79ce132bd..1bfed4f58 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -28,6 +28,7 @@ #include "ObjectMgr.h" #include "Player.h" #include "PoolMgr.h" +#include "RBAC.h" #include "Transport.h" #include @@ -45,21 +46,21 @@ public: { static ChatCommandTable gobjectCommandTable = { - { "activate", HandleGameObjectActivateCommand, SEC_GAMEMASTER, Console::No }, - { "delete", HandleGameObjectDeleteCommand, SEC_ADMINISTRATOR, Console::No }, - { "info", HandleGameObjectInfoCommand, SEC_MODERATOR, Console::No }, - { "move", HandleGameObjectMoveCommand, SEC_ADMINISTRATOR, Console::No }, - { "near", HandleGameObjectNearCommand, SEC_MODERATOR, Console::No }, - { "target", HandleGameObjectTargetCommand, SEC_MODERATOR, Console::No }, - { "turn", HandleGameObjectTurnCommand, SEC_ADMINISTRATOR, Console::No }, - { "add temp", HandleGameObjectAddTempCommand, SEC_GAMEMASTER, Console::No }, - { "add", HandleGameObjectAddCommand, SEC_ADMINISTRATOR, Console::No }, - { "load", HandleGameObjectLoadCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "set phase", HandleGameObjectSetPhaseCommand, SEC_ADMINISTRATOR, Console::No }, - { "set state", HandleGameObjectSetStateCommand, SEC_ADMINISTRATOR, Console::No }, - { "respawn", HandleGameObjectRespawn, SEC_GAMEMASTER, Console::No }, - { "spawngroup", HandleGameObjectSpawnGroupCommand, SEC_ADMINISTRATOR, Console::No }, - { "despawngroup", HandleGameObjectDespawnGroupCommand, SEC_ADMINISTRATOR, Console::No } + { "activate", HandleGameObjectActivateCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, Console::No }, + { "delete", HandleGameObjectDeleteCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, Console::No }, + { "info", HandleGameObjectInfoCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, Console::No }, + { "move", HandleGameObjectMoveCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, Console::No }, + { "near", HandleGameObjectNearCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, Console::No }, + { "target", HandleGameObjectTargetCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, Console::No }, + { "turn", HandleGameObjectTurnCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, Console::No }, + { "add temp", HandleGameObjectAddTempCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP, Console::No }, + { "add", HandleGameObjectAddCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, Console::No }, + { "load", HandleGameObjectLoadCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_LOAD, Console::Yes }, + { "set phase", HandleGameObjectSetPhaseCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_SET_PHASE, Console::No }, + { "set state", HandleGameObjectSetStateCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_SET_STATE, Console::No }, + { "respawn", HandleGameObjectRespawn, rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, Console::No }, + { "spawngroup", HandleGameObjectSpawnGroupCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, Console::No }, + { "despawngroup", HandleGameObjectDespawnGroupCommand, rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, Console::No } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index 7be8d6674..83b4e001a 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -20,6 +20,7 @@ #include "GroupMgr.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -32,12 +33,12 @@ public: { static ChatCommandTable groupCommandTable = { - { "list", HandleGroupListCommand, SEC_GAMEMASTER, Console::Yes }, - { "join", HandleGroupJoinCommand, SEC_GAMEMASTER, Console::No }, - { "remove", HandleGroupRemoveCommand, SEC_GAMEMASTER, Console::No }, - { "disband", HandleGroupDisbandCommand, SEC_GAMEMASTER, Console::No }, - { "revive", HandleGroupReviveCommand, SEC_GAMEMASTER, Console::No }, - { "leader", HandleGroupLeaderCommand, SEC_GAMEMASTER, Console::No } + { "list", HandleGroupListCommand, rbac::RBAC_PERM_COMMAND_GROUP_LIST, Console::Yes }, + { "join", HandleGroupJoinCommand, rbac::RBAC_PERM_COMMAND_GROUP_JOIN, Console::No }, + { "remove", HandleGroupRemoveCommand, rbac::RBAC_PERM_COMMAND_GROUP_REMOVE, Console::No }, + { "disband", HandleGroupDisbandCommand, rbac::RBAC_PERM_COMMAND_GROUP_DISBAND, Console::No }, + { "revive", HandleGroupReviveCommand, rbac::RBAC_PERM_COMMAND_GROUP_REVIVE, Console::No }, + { "leader", HandleGroupLeaderCommand, rbac::RBAC_PERM_COMMAND_GROUP_LEADER, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp index 45c55ddf0..1980344de 100644 --- a/src/server/scripts/Commands/cs_guild.cpp +++ b/src/server/scripts/Commands/cs_guild.cpp @@ -19,6 +19,7 @@ #include "CommandScript.h" #include "Guild.h" #include "GuildMgr.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -31,13 +32,13 @@ public: { static ChatCommandTable guildCommandTable = { - { "create", HandleGuildCreateCommand, SEC_GAMEMASTER, Console::Yes }, - { "delete", HandleGuildDeleteCommand, SEC_GAMEMASTER, Console::Yes }, - { "invite", HandleGuildInviteCommand, SEC_GAMEMASTER, Console::Yes }, - { "uninvite", HandleGuildUninviteCommand, SEC_GAMEMASTER, Console::Yes }, - { "rank", HandleGuildRankCommand, SEC_GAMEMASTER, Console::Yes }, - { "rename", HandleGuildRenameCommand, SEC_GAMEMASTER, Console::Yes }, - { "info", HandleGuildInfoCommand, SEC_GAMEMASTER, Console::Yes } + { "create", HandleGuildCreateCommand, rbac::RBAC_PERM_COMMAND_GUILD_CREATE, Console::Yes }, + { "delete", HandleGuildDeleteCommand, rbac::RBAC_PERM_COMMAND_GUILD_DELETE, Console::Yes }, + { "invite", HandleGuildInviteCommand, rbac::RBAC_PERM_COMMAND_GUILD_INVITE, Console::Yes }, + { "uninvite", HandleGuildUninviteCommand, rbac::RBAC_PERM_COMMAND_GUILD_UNINVITE, Console::Yes }, + { "rank", HandleGuildRankCommand, rbac::RBAC_PERM_COMMAND_GUILD_RANK, Console::Yes }, + { "rename", HandleGuildRenameCommand, rbac::RBAC_PERM_COMMAND_GUILD_RENAME, Console::Yes }, + { "info", HandleGuildInfoCommand, rbac::RBAC_PERM_COMMAND_GUILD_INFO, Console::Yes } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_honor.cpp b/src/server/scripts/Commands/cs_honor.cpp index af83d0b9f..f96f0c92d 100644 --- a/src/server/scripts/Commands/cs_honor.cpp +++ b/src/server/scripts/Commands/cs_honor.cpp @@ -19,6 +19,8 @@ #include "CommandScript.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" +#include "WorldSession.h" using namespace Acore::ChatCommands; @@ -31,14 +33,14 @@ public: { static ChatCommandTable honorAddCommandTable = { - { "kill", HandleHonorAddKillCommand, SEC_GAMEMASTER, Console::No }, - { "", HandleHonorAddCommand, SEC_GAMEMASTER, Console::No } + { "kill", HandleHonorAddKillCommand, rbac::RBAC_PERM_COMMAND_HONOR_ADD_KILL, Console::No }, + { "", HandleHonorAddCommand, rbac::RBAC_PERM_COMMAND_HONOR_ADD, Console::No } }; static ChatCommandTable honorCommandTable = { { "add", honorAddCommandTable }, - { "update", HandleHonorUpdateCommand, SEC_GAMEMASTER, Console::No } + { "update", HandleHonorUpdateCommand, rbac::RBAC_PERM_COMMAND_HONOR_UPDATE, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp index 078594a8a..009624f79 100644 --- a/src/server/scripts/Commands/cs_instance.cpp +++ b/src/server/scripts/Commands/cs_instance.cpp @@ -25,6 +25,7 @@ #include "MapMgr.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -37,12 +38,12 @@ public: { static ChatCommandTable instanceCommandTable = { - { "listbinds", HandleInstanceListBindsCommand, SEC_MODERATOR, Console::No }, - { "unbind", HandleInstanceUnbindCommand, SEC_GAMEMASTER, Console::No }, - { "stats", HandleInstanceStatsCommand, SEC_MODERATOR, Console::Yes }, - { "savedata", HandleInstanceSaveDataCommand, SEC_ADMINISTRATOR, Console::No }, - { "setbossstate", HandleInstanceSetBossStateCommand, SEC_GAMEMASTER, Console::Yes }, - { "getbossstate", HandleInstanceGetBossStateCommand, SEC_MODERATOR, Console::Yes }, + { "listbinds", HandleInstanceListBindsCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_LISTBINDS, Console::No }, + { "unbind", HandleInstanceUnbindCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, Console::No }, + { "stats", HandleInstanceStatsCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_STATS, Console::Yes }, + { "savedata", HandleInstanceSaveDataCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_SAVEDATA, Console::No }, + { "setbossstate", HandleInstanceSetBossStateCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_SET_BOSS_STATE, Console::Yes }, + { "getbossstate", HandleInstanceGetBossStateCommand, rbac::RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE, Console::Yes }, }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_inventory.cpp b/src/server/scripts/Commands/cs_inventory.cpp index 43fae2e91..80ece0d0d 100644 --- a/src/server/scripts/Commands/cs_inventory.cpp +++ b/src/server/scripts/Commands/cs_inventory.cpp @@ -19,6 +19,8 @@ #include "CommandScript.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" +#include "WorldSession.h" constexpr std::array bagSpecsToString = { @@ -70,7 +72,7 @@ public: { static ChatCommandTable inventoryCommandTable = { - { "count", HandleInventoryCountCommand, SEC_MODERATOR, Console::No } + { "count", HandleInventoryCountCommand, rbac::RBAC_PERM_COMMAND_ADDITEM, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_item.cpp b/src/server/scripts/Commands/cs_item.cpp index 711f2532e..e866443fc 100644 --- a/src/server/scripts/Commands/cs_item.cpp +++ b/src/server/scripts/Commands/cs_item.cpp @@ -22,6 +22,7 @@ #include "Language.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -34,14 +35,14 @@ public: { static ChatCommandTable HandleItemRestoreCommandTable = { - { "list", HandleItemRestoreListCommand, SEC_GAMEMASTER, Console::Yes }, - { "", HandleItemRestoreCommand, SEC_GAMEMASTER, Console::Yes }, + { "list", HandleItemRestoreListCommand, rbac::RBAC_PERM_COMMAND_ITEM_RESTORE_LIST, Console::Yes }, + { "", HandleItemRestoreCommand, rbac::RBAC_PERM_COMMAND_ITEM_RESTORE, Console::Yes }, }; static ChatCommandTable itemCommandTable = { { "restore", HandleItemRestoreCommandTable }, - { "move", HandleItemMoveCommand, SEC_GAMEMASTER, Console::Yes }, - { "refund", HandleItemRefundCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "move", HandleItemMoveCommand, rbac::RBAC_PERM_COMMAND_ITEMMOVE, Console::Yes }, + { "refund", HandleItemRefundCommand, rbac::RBAC_PERM_COMMAND_ITEM_REFUND, Console::Yes }, }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 1b5cc4b89..b86e56662 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -21,6 +21,7 @@ #include "Pet.h" #include "Player.h" #include "PlayerCommand.h" +#include "RBAC.h" #include "SpellInfo.h" #include "SpellMgr.h" @@ -35,33 +36,33 @@ public: { static ChatCommandTable learnAllMyCommandTable = { - { "class", HandleLearnAllMyClassCommand, SEC_GAMEMASTER, Console::No }, - { "pettalents", HandleLearnAllMyPetTalentsCommand, SEC_GAMEMASTER, Console::No }, - { "trainer", HandleLearnAllMyTrainerSpellsCommand, SEC_GAMEMASTER, Console::No }, - { "talents", HandleLearnAllMyTalentsCommand, SEC_GAMEMASTER, Console::No }, - { "quest", HandleLearnAllMyQuestSpells, SEC_GAMEMASTER, Console::No } + { "class", HandleLearnAllMyClassCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS, Console::No }, + { "pettalents", HandleLearnAllMyPetTalentsCommand, rbac::RBAC_PERM_COMMAND_LEARN_MY_PETTALENTS, Console::No }, + { "trainer", HandleLearnAllMyTrainerSpellsCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS, Console::No }, + { "talents", HandleLearnAllMyTalentsCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_TALENTS, Console::No }, + { "quest", HandleLearnAllMyQuestSpells, rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS, Console::No } }; static ChatCommandTable learnAllCommandTable = { { "my", learnAllMyCommandTable }, - { "gm", HandleLearnAllGMCommand, SEC_GAMEMASTER, Console::No }, - { "crafts", HandleLearnAllCraftsCommand, SEC_GAMEMASTER, Console::No }, - { "default", HandleLearnAllDefaultCommand, SEC_GAMEMASTER, Console::No }, - { "lang", HandleLearnAllLangCommand, SEC_GAMEMASTER, Console::No }, - { "recipes", HandleLearnAllRecipesCommand, SEC_GAMEMASTER, Console::No }, + { "gm", HandleLearnAllGMCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_GM, Console::No }, + { "crafts", HandleLearnAllCraftsCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS, Console::No }, + { "default", HandleLearnAllDefaultCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT, Console::No }, + { "lang", HandleLearnAllLangCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_LANG, Console::No }, + { "recipes", HandleLearnAllRecipesCommand, rbac::RBAC_PERM_COMMAND_LEARN_ALL_RECIPES, Console::No }, }; static ChatCommandTable learnCommandTable = { { "all", learnAllCommandTable }, - { "", HandleLearnCommand, SEC_GAMEMASTER, Console::No } + { "", HandleLearnCommand, rbac::RBAC_PERM_COMMAND_LEARN, Console::No } }; static ChatCommandTable commandTable = { { "learn", learnCommandTable }, - { "unlearn", HandleUnLearnCommand, SEC_GAMEMASTER, Console::No } + { "unlearn", HandleUnLearnCommand, rbac::RBAC_PERM_COMMAND_UNLEARN, Console::No } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_lfg.cpp b/src/server/scripts/Commands/cs_lfg.cpp index 693ab1585..c147d64f0 100644 --- a/src/server/scripts/Commands/cs_lfg.cpp +++ b/src/server/scripts/Commands/cs_lfg.cpp @@ -21,6 +21,7 @@ #include "LFGMgr.h" #include "Language.h" #include "Player.h" +#include "RBAC.h" void GetPlayerInfo(ChatHandler* handler, Player* player) { @@ -47,12 +48,12 @@ public: { static ChatCommandTable lfgCommandTable = { - { "player", HandleLfgPlayerInfoCommand, SEC_MODERATOR, Console::No }, - { "group", HandleLfgGroupInfoCommand, SEC_MODERATOR, Console::No }, - { "queue", HandleLfgQueueInfoCommand, SEC_MODERATOR, Console::Yes }, - { "clean", HandleLfgCleanCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "options", HandleLfgOptionsCommand, SEC_GAMEMASTER, Console::Yes }, - { "cooldown", HandleLfgCooldownClearCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "player", HandleLfgPlayerInfoCommand, rbac::RBAC_PERM_COMMAND_LFG_PLAYER, Console::No }, + { "group", HandleLfgGroupInfoCommand, rbac::RBAC_PERM_COMMAND_LFG_GROUP, Console::No }, + { "queue", HandleLfgQueueInfoCommand, rbac::RBAC_PERM_COMMAND_LFG_QUEUE, Console::Yes }, + { "clean", HandleLfgCleanCommand, rbac::RBAC_PERM_COMMAND_LFG_CLEAN, Console::Yes }, + { "options", HandleLfgOptionsCommand, rbac::RBAC_PERM_COMMAND_LFG_OPTIONS, Console::Yes }, + { "cooldown", HandleLfgCooldownClearCommand, rbac::RBAC_PERM_COMMAND_LFG_COOLDOWN, Console::Yes }, }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index 84b75bd1a..c098a7e30 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -26,6 +26,7 @@ #include "MapMgr.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "SpellAuraEffects.h" using namespace Acore::ChatCommands; @@ -39,18 +40,18 @@ public: { static ChatCommandTable listAurasCommandTable = { - { "", HandleListAllAurasCommand, SEC_MODERATOR, Console::No }, - { "id", HandleListAurasByIdCommand, SEC_MODERATOR, Console::No }, - { "name", HandleListAurasByNameCommand, SEC_MODERATOR, Console::No }, + { "", HandleListAllAurasCommand, rbac::RBAC_PERM_COMMAND_LIST_AURAS, Console::No }, + { "id", HandleListAurasByIdCommand, rbac::RBAC_PERM_COMMAND_LIST_AURAS, Console::No }, + { "name", HandleListAurasByNameCommand, rbac::RBAC_PERM_COMMAND_LIST_AURAS, Console::No }, }; static ChatCommandTable listCommandTable = { - { "creature", HandleListCreatureCommand, SEC_MODERATOR, Console::Yes }, - { "item", HandleListItemCommand, SEC_MODERATOR, Console::Yes }, - { "object", HandleListObjectCommand, SEC_MODERATOR, Console::Yes }, - { "auras", listAurasCommandTable }, - { "respawns", HandleListRespawnsCommand, SEC_GAMEMASTER, Console::No }, + { "creature", HandleListCreatureCommand, rbac::RBAC_PERM_COMMAND_LIST_CREATURE, Console::Yes }, + { "item", HandleListItemCommand, rbac::RBAC_PERM_COMMAND_LIST_ITEM, Console::Yes }, + { "object", HandleListObjectCommand, rbac::RBAC_PERM_COMMAND_LIST_OBJECT, Console::Yes }, + { "auras", listAurasCommandTable }, + { "respawns", HandleListRespawnsCommand, rbac::RBAC_PERM_COMMAND_LIST_CREATURE, Console::No }, }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 5dd54c3eb..4fb3c66ab 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -22,6 +22,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "ReputationMgr.h" #include "SharedDefines.h" #include "SpellInfo.h" @@ -38,29 +39,29 @@ public: { static ChatCommandTable lookupPlayerCommandTable = { - { "ip", HandleLookupPlayerIpCommand, SEC_GAMEMASTER, Console::Yes }, - { "account", HandleLookupPlayerAccountCommand, SEC_GAMEMASTER, Console::Yes }, - { "email", HandleLookupPlayerEmailCommand, SEC_GAMEMASTER, Console::Yes } + { "ip", HandleLookupPlayerIpCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_IP, Console::Yes }, + { "account", HandleLookupPlayerAccountCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_ACCOUNT, Console::Yes }, + { "email", HandleLookupPlayerEmailCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_EMAIL, Console::Yes } }; static ChatCommandTable lookupCommandTable = { - { "area", HandleLookupAreaCommand, SEC_MODERATOR, Console::Yes }, - { "creature", HandleLookupCreatureCommand, SEC_MODERATOR, Console::Yes }, - { "event", HandleLookupEventCommand, SEC_MODERATOR, Console::Yes }, - { "faction", HandleLookupFactionCommand, SEC_MODERATOR, Console::Yes }, - { "item", HandleLookupItemCommand, SEC_MODERATOR, Console::Yes }, - { "item set", HandleLookupItemSetCommand, SEC_MODERATOR, Console::Yes }, - { "map", HandleLookupMapCommand, SEC_MODERATOR, Console::Yes }, - { "object", HandleLookupObjectCommand, SEC_MODERATOR, Console::Yes }, - { "gobject", HandleLookupObjectCommand, SEC_MODERATOR, Console::Yes }, - { "quest", HandleLookupQuestCommand, SEC_MODERATOR, Console::Yes }, - { "skill", HandleLookupSkillCommand, SEC_MODERATOR, Console::Yes }, - { "taxinode", HandleLookupTaxiNodeCommand, SEC_MODERATOR, Console::Yes }, - { "teleport", HandleLookupTeleCommand, SEC_MODERATOR, Console::Yes }, - { "title", HandleLookupTitleCommand, SEC_MODERATOR, Console::Yes }, - { "spell", HandleLookupSpellCommand, SEC_MODERATOR, Console::Yes }, - { "spell id", HandleLookupSpellIdCommand, SEC_MODERATOR, Console::Yes }, + { "area", HandleLookupAreaCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_AREA, Console::Yes }, + { "creature", HandleLookupCreatureCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_CREATURE, Console::Yes }, + { "event", HandleLookupEventCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_EVENT, Console::Yes }, + { "faction", HandleLookupFactionCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_FACTION, Console::Yes }, + { "item", HandleLookupItemCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_ITEM, Console::Yes }, + { "item set", HandleLookupItemSetCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_ITEMSET, Console::Yes }, + { "map", HandleLookupMapCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_MAP, Console::Yes }, + { "object", HandleLookupObjectCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_OBJECT, Console::Yes }, + { "gobject", HandleLookupObjectCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_OBJECT, Console::Yes }, + { "quest", HandleLookupQuestCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_QUEST, Console::Yes }, + { "skill", HandleLookupSkillCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_SKILL, Console::Yes }, + { "taxinode", HandleLookupTaxiNodeCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_TAXINODE, Console::Yes }, + { "teleport", HandleLookupTeleCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_TELE, Console::Yes }, + { "title", HandleLookupTitleCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_TITLE, Console::Yes }, + { "spell", HandleLookupSpellCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL, Console::Yes }, + { "spell id", HandleLookupSpellIdCommand, rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL_ID, Console::Yes }, { "player", lookupPlayerCommandTable }, }; diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index b6f051ee8..d03d72e20 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -23,6 +23,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "World.h" #include "WorldSession.h" #include "WorldSessionMgr.h" @@ -38,13 +39,13 @@ public: { static ChatCommandTable commandTable = { - { "nameannounce", HandleNameAnnounceCommand, SEC_GAMEMASTER, Console::Yes }, - { "gmnameannounce", HandleGMNameAnnounceCommand, SEC_GAMEMASTER, Console::Yes }, - { "announce", HandleAnnounceCommand, SEC_GAMEMASTER, Console::Yes }, - { "gmannounce", HandleGMAnnounceCommand, SEC_GAMEMASTER, Console::Yes }, - { "notify", HandleNotifyCommand, SEC_GAMEMASTER, Console::Yes }, - { "gmnotify", HandleGMNotifyCommand, SEC_GAMEMASTER, Console::Yes }, - { "whispers", HandleWhispersCommand, SEC_MODERATOR, Console::No }, + { "nameannounce", HandleNameAnnounceCommand, rbac::RBAC_PERM_COMMAND_NAMEANNOUNCE, Console::Yes }, + { "gmnameannounce", HandleGMNameAnnounceCommand, rbac::RBAC_PERM_COMMAND_GMNAMEANNOUNCE, Console::Yes }, + { "announce", HandleAnnounceCommand, rbac::RBAC_PERM_COMMAND_ANNOUNCE, Console::Yes }, + { "gmannounce", HandleGMAnnounceCommand, rbac::RBAC_PERM_COMMAND_GMANNOUNCE, Console::Yes }, + { "notify", HandleNotifyCommand, rbac::RBAC_PERM_COMMAND_NOTIFY, Console::Yes }, + { "gmnotify", HandleGMNotifyCommand, rbac::RBAC_PERM_COMMAND_GMNOTIFY, Console::Yes }, + { "whispers", HandleWhispersCommand, rbac::RBAC_PERM_COMMAND_WHISPERS, Console::No }, }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index c28a5de5c..961e9a5b9 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -41,6 +41,7 @@ #include "Pet.h" #include "Player.h" #include "PoolMgr.h" +#include "RBAC.h" #include "Realm.h" #include "ScriptMgr.h" #include "SpellAuras.h" @@ -137,66 +138,66 @@ public: { static ChatCommandTable auraCommandTable = { - { "stack", HandleAuraStacksCommand, SEC_GAMEMASTER, Console::No }, - { "", HandleAuraCommand, SEC_GAMEMASTER, Console::No } + { "stack", HandleAuraStacksCommand, rbac::RBAC_PERM_COMMAND_AURA_STACK, Console::No }, + { "", HandleAuraCommand, rbac::RBAC_PERM_COMMAND_AURA, Console::No } }; static ChatCommandTable commandTable = { - { "commentator", HandleCommentatorCommand, SEC_MODERATOR, Console::No }, - { "dev", HandleDevCommand, SEC_ADMINISTRATOR, Console::No }, - { "gps", HandleGPSCommand, SEC_MODERATOR, Console::No }, - { "aura", auraCommandTable }, - { "unaura", HandleUnAuraCommand, SEC_GAMEMASTER, Console::No }, - { "appear", HandleAppearCommand, SEC_MODERATOR, Console::No }, - { "summon", HandleSummonCommand, SEC_GAMEMASTER, Console::No }, - { "groupsummon", HandleGroupSummonCommand, SEC_GAMEMASTER, Console::No }, - { "commands", HandleCommandsCommand, SEC_PLAYER, Console::Yes }, - { "die", HandleDieCommand, SEC_GAMEMASTER, Console::No }, - { "revive", HandleReviveCommand, SEC_GAMEMASTER, Console::Yes }, - { "dismount", HandleDismountCommand, SEC_PLAYER, Console::No }, - { "guid", HandleGUIDCommand, SEC_GAMEMASTER, Console::No }, - { "help", HandleHelpCommand, SEC_PLAYER, Console::Yes }, - { "cooldown", HandleCooldownCommand, SEC_GAMEMASTER, Console::No }, - { "distance", HandleGetDistanceCommand, SEC_ADMINISTRATOR, Console::No }, - { "recall", HandleRecallCommand, SEC_GAMEMASTER, Console::No }, - { "save", HandleSaveCommand, SEC_PLAYER, Console::No }, - { "saveall", HandleSaveAllCommand, SEC_GAMEMASTER, Console::Yes }, - { "kick", HandleKickPlayerCommand, SEC_GAMEMASTER, Console::Yes }, - { "unstuck", HandleUnstuckCommand, SEC_GAMEMASTER, Console::Yes }, - { "linkgrave", HandleLinkGraveCommand, SEC_ADMINISTRATOR, Console::No }, - { "neargrave", HandleNearGraveCommand, SEC_GAMEMASTER, Console::No }, - { "showarea", HandleShowAreaCommand, SEC_GAMEMASTER, Console::No }, - { "hidearea", HandleHideAreaCommand, SEC_ADMINISTRATOR, Console::No }, - { "additem", HandleAddItemCommand, SEC_GAMEMASTER, Console::Yes }, - { "additem set", HandleAddItemSetCommand, SEC_GAMEMASTER, Console::No }, - { "wchange", HandleChangeWeather, SEC_ADMINISTRATOR, Console::No }, - { "maxskill", HandleMaxSkillCommand, SEC_GAMEMASTER, Console::No }, - { "setskill", HandleSetSkillCommand, SEC_GAMEMASTER, Console::No }, - { "pinfo", HandlePInfoCommand, SEC_GAMEMASTER, Console::Yes }, - { "respawn", HandleRespawnCommand, SEC_GAMEMASTER, Console::No }, - { "respawn all", HandleRespawnAllCommand, SEC_GAMEMASTER, Console::No }, - { "mute", HandleMuteCommand, SEC_GAMEMASTER, Console::Yes }, - { "mutehistory", HandleMuteInfoCommand, SEC_GAMEMASTER, Console::Yes }, - { "unmute", HandleUnmuteCommand, SEC_GAMEMASTER, Console::Yes }, - { "movegens", HandleMovegensCommand, SEC_ADMINISTRATOR, Console::No }, - { "cometome", HandleComeToMeCommand, SEC_ADMINISTRATOR, Console::No }, - { "damage", HandleDamageCommand, SEC_GAMEMASTER, Console::No }, - { "combatstop", HandleCombatStopCommand, SEC_GAMEMASTER, Console::Yes }, - { "flusharenapoints", HandleFlushArenaPointsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "freeze", HandleFreezeCommand, SEC_GAMEMASTER, Console::No }, - { "unfreeze", HandleUnFreezeCommand, SEC_GAMEMASTER, Console::No }, - { "possess", HandlePossessCommand, SEC_GAMEMASTER, Console::No }, - { "unpossess", HandleUnPossessCommand, SEC_GAMEMASTER, Console::No }, - { "bindsight", HandleBindSightCommand, SEC_ADMINISTRATOR, Console::No }, - { "unbindsight", HandleUnbindSightCommand, SEC_ADMINISTRATOR, Console::No }, - { "playall", HandlePlayAllCommand, SEC_GAMEMASTER, Console::No }, - { "skirmish", HandleSkirmishCommand, SEC_ADMINISTRATOR, Console::No }, - { "mailbox", HandleMailBoxCommand, SEC_MODERATOR, Console::No }, - { "string", HandleStringCommand, SEC_GAMEMASTER, Console::No }, - { "opendoor", HandleOpenDoorCommand, SEC_GAMEMASTER, Console::No }, - { "bm", HandleBMCommand, SEC_GAMEMASTER, Console::No }, - { "packetlog", HandlePacketLog, SEC_GAMEMASTER, Console::Yes } + { "commentator", HandleCommentatorCommand, rbac::RBAC_PERM_COMMAND_COMMENTATOR, Console::No }, + { "dev", HandleDevCommand, rbac::RBAC_PERM_COMMAND_DEV, Console::No }, + { "gps", HandleGPSCommand, rbac::RBAC_PERM_COMMAND_GPS, Console::No }, + { "aura", auraCommandTable }, + { "unaura", HandleUnAuraCommand, rbac::RBAC_PERM_COMMAND_UNAURA, Console::No }, + { "appear", HandleAppearCommand, rbac::RBAC_PERM_COMMAND_APPEAR, Console::No }, + { "summon", HandleSummonCommand, rbac::RBAC_PERM_COMMAND_SUMMON, Console::No }, + { "groupsummon", HandleGroupSummonCommand, rbac::RBAC_PERM_COMMAND_GROUP_SUMMON, Console::No }, + { "commands", HandleCommandsCommand, rbac::RBAC_PERM_COMMAND_COMMANDS, Console::Yes }, + { "die", HandleDieCommand, rbac::RBAC_PERM_COMMAND_DIE, Console::No }, + { "revive", HandleReviveCommand, rbac::RBAC_PERM_COMMAND_REVIVE, Console::Yes }, + { "dismount", HandleDismountCommand, rbac::RBAC_PERM_COMMAND_DISMOUNT, Console::No }, + { "guid", HandleGUIDCommand, rbac::RBAC_PERM_COMMAND_GUID, Console::No }, + { "help", HandleHelpCommand, rbac::RBAC_PERM_COMMAND_HELP, Console::Yes }, + { "cooldown", HandleCooldownCommand, rbac::RBAC_PERM_COMMAND_COOLDOWN, Console::No }, + { "distance", HandleGetDistanceCommand, rbac::RBAC_PERM_COMMAND_DISTANCE, Console::No }, + { "recall", HandleRecallCommand, rbac::RBAC_PERM_COMMAND_RECALL, Console::No }, + { "save", HandleSaveCommand, rbac::RBAC_PERM_COMMAND_SAVE, Console::No }, + { "saveall", HandleSaveAllCommand, rbac::RBAC_PERM_COMMAND_SAVEALL, Console::Yes }, + { "kick", HandleKickPlayerCommand, rbac::RBAC_PERM_COMMAND_KICK, Console::Yes }, + { "unstuck", HandleUnstuckCommand, rbac::RBAC_PERM_COMMAND_UNSTUCK, Console::Yes }, + { "linkgrave", HandleLinkGraveCommand, rbac::RBAC_PERM_COMMAND_LINKGRAVE, Console::No }, + { "neargrave", HandleNearGraveCommand, rbac::RBAC_PERM_COMMAND_NEARGRAVE, Console::No }, + { "showarea", HandleShowAreaCommand, rbac::RBAC_PERM_COMMAND_SHOWAREA, Console::No }, + { "hidearea", HandleHideAreaCommand, rbac::RBAC_PERM_COMMAND_HIDEAREA, Console::No }, + { "additem", HandleAddItemCommand, rbac::RBAC_PERM_COMMAND_ADDITEM, Console::Yes }, + { "additem set", HandleAddItemSetCommand, rbac::RBAC_PERM_COMMAND_ADDITEMSET, Console::No }, + { "wchange", HandleChangeWeather, rbac::RBAC_PERM_COMMAND_WCHANGE, Console::No }, + { "maxskill", HandleMaxSkillCommand, rbac::RBAC_PERM_COMMAND_MAXSKILL, Console::No }, + { "setskill", HandleSetSkillCommand, rbac::RBAC_PERM_COMMAND_SETSKILL, Console::No }, + { "pinfo", HandlePInfoCommand, rbac::RBAC_PERM_COMMAND_PINFO, Console::Yes }, + { "respawn", HandleRespawnCommand, rbac::RBAC_PERM_COMMAND_RESPAWN, Console::No }, + { "respawn all", HandleRespawnAllCommand, rbac::RBAC_PERM_COMMAND_RESPAWN_ALL, Console::No }, + { "mute", HandleMuteCommand, rbac::RBAC_PERM_COMMAND_MUTE, Console::Yes }, + { "mutehistory", HandleMuteInfoCommand, rbac::RBAC_PERM_COMMAND_MUTEHISTORY, Console::Yes }, + { "unmute", HandleUnmuteCommand, rbac::RBAC_PERM_COMMAND_UNMUTE, Console::Yes }, + { "movegens", HandleMovegensCommand, rbac::RBAC_PERM_COMMAND_MOVEGENS, Console::No }, + { "cometome", HandleComeToMeCommand, rbac::RBAC_PERM_COMMAND_COMETOME, Console::No }, + { "damage", HandleDamageCommand, rbac::RBAC_PERM_COMMAND_DAMAGE, Console::No }, + { "combatstop", HandleCombatStopCommand, rbac::RBAC_PERM_COMMAND_COMBATSTOP, Console::Yes }, + { "flusharenapoints", HandleFlushArenaPointsCommand, rbac::RBAC_PERM_COMMAND_FLUSHARENAPOINTS, Console::Yes }, + { "freeze", HandleFreezeCommand, rbac::RBAC_PERM_COMMAND_FREEZE, Console::No }, + { "unfreeze", HandleUnFreezeCommand, rbac::RBAC_PERM_COMMAND_UNFREEZE, Console::No }, + { "possess", HandlePossessCommand, rbac::RBAC_PERM_COMMAND_POSSESS, Console::No }, + { "unpossess", HandleUnPossessCommand, rbac::RBAC_PERM_COMMAND_UNPOSSESS, Console::No }, + { "bindsight", HandleBindSightCommand, rbac::RBAC_PERM_COMMAND_BINDSIGHT, Console::No }, + { "unbindsight", HandleUnbindSightCommand, rbac::RBAC_PERM_COMMAND_UNBINDSIGHT, Console::No }, + { "playall", HandlePlayAllCommand, rbac::RBAC_PERM_COMMAND_PLAYALL, Console::No }, + { "skirmish", HandleSkirmishCommand, rbac::RBAC_PERM_COMMAND_SKIRMISH, Console::No }, + { "mailbox", HandleMailBoxCommand, rbac::RBAC_PERM_COMMAND_MAILBOX, Console::No }, + { "string", HandleStringCommand, rbac::RBAC_PERM_COMMAND_STRING, Console::No }, + { "opendoor", HandleOpenDoorCommand, rbac::RBAC_PERM_COMMAND_OPENDOOR, Console::No }, + { "bm", HandleBMCommand, rbac::RBAC_PERM_COMMAND_BEASTMASTER, Console::No }, + { "packetlog", HandlePacketLog, rbac::RBAC_PERM_COMMAND_PACKETLOG, Console::Yes } }; return commandTable; @@ -1397,7 +1398,7 @@ public: Player* player = handler->GetSession()->GetPlayer(); // save GM account without delay and output message - if (handler->GetSession()->GetSecurity() >= SEC_GAMEMASTER) + if (handler->GetSession()->HasPermission(rbac::RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY)) { if (Player* target = handler->getSelectedPlayer()) { diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 91a164a11..88cd0cd51 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -32,6 +32,7 @@ #include "Map.h" #include "PathGenerator.h" #include "Player.h" +#include "RBAC.h" #include "TargetedMovementGenerator.h" using namespace Acore::ChatCommands; @@ -45,11 +46,11 @@ public: { static ChatCommandTable mmapCommandTable = { - { "loadedtiles", HandleMmapLoadedTilesCommand, SEC_ADMINISTRATOR, Console::No }, - { "loc", HandleMmapLocCommand, SEC_ADMINISTRATOR, Console::No }, - { "path", HandleMmapPathCommand, SEC_ADMINISTRATOR, Console::No }, - { "stats", HandleMmapStatsCommand, SEC_ADMINISTRATOR, Console::No }, - { "testarea", HandleMmapTestArea, SEC_ADMINISTRATOR, Console::No } + { "loadedtiles", HandleMmapLoadedTilesCommand, rbac::RBAC_PERM_COMMAND_MMAP_LOADEDTILES, Console::No }, + { "loc", HandleMmapLocCommand, rbac::RBAC_PERM_COMMAND_MMAP_LOC, Console::No }, + { "path", HandleMmapPathCommand, rbac::RBAC_PERM_COMMAND_MMAP_PATH, Console::No }, + { "stats", HandleMmapStatsCommand, rbac::RBAC_PERM_COMMAND_MMAP_STATS, Console::No }, + { "testarea", HandleMmapTestArea, rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index c2b2f6d80..058ca793e 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -21,6 +21,7 @@ #include "Opcodes.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "ReputationMgr.h" #include "StringConvert.h" @@ -35,43 +36,43 @@ public: { static ChatCommandTable modifyspeedCommandTable = { - { "fly", HandleModifyFlyCommand, SEC_GAMEMASTER, Console::No }, - { "all", HandleModifyASpeedCommand, SEC_GAMEMASTER, Console::No }, - { "walk", HandleModifySpeedCommand, SEC_GAMEMASTER, Console::No }, - { "backwalk", HandleModifyBWalkCommand, SEC_GAMEMASTER, Console::No }, - { "swim", HandleModifySwimCommand, SEC_GAMEMASTER, Console::No }, - { "", HandleModifyASpeedCommand, SEC_GAMEMASTER, Console::No } + { "fly", HandleModifyFlyCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_FLY, Console::No }, + { "all", HandleModifyASpeedCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_ALL, Console::No }, + { "walk", HandleModifySpeedCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_WALK, Console::No }, + { "backwalk", HandleModifyBWalkCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_BACKWALK, Console::No }, + { "swim", HandleModifySwimCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_SWIM, Console::No }, + { "", HandleModifyASpeedCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPEED, Console::No } }; static ChatCommandTable modifyCommandTable = { - { "hp", HandleModifyHPCommand, SEC_GAMEMASTER, Console::No }, - { "mana", HandleModifyManaCommand, SEC_GAMEMASTER, Console::No }, - { "rage", HandleModifyRageCommand, SEC_GAMEMASTER, Console::No }, - { "runicpower", HandleModifyRunicPowerCommand, SEC_GAMEMASTER, Console::No }, - { "energy", HandleModifyEnergyCommand, SEC_GAMEMASTER, Console::No }, - { "money", HandleModifyMoneyCommand, SEC_GAMEMASTER, Console::No }, - { "scale", HandleModifyScaleCommand, SEC_GAMEMASTER, Console::No }, - { "bit", HandleModifyBitCommand, SEC_GAMEMASTER, Console::No }, - { "faction", HandleModifyFactionCommand, SEC_ADMINISTRATOR, Console::No }, - { "spell", HandleModifySpellCommand, SEC_CONSOLE, Console::No }, - { "talentpoints", HandleModifyTalentCommand, SEC_GAMEMASTER, Console::No }, - { "mount", HandleModifyMountCommand, SEC_GAMEMASTER, Console::No }, - { "honor", HandleModifyHonorCommand, SEC_GAMEMASTER, Console::No }, - { "reputation", HandleModifyRepCommand, SEC_GAMEMASTER, Console::No }, - { "arenapoints", HandleModifyArenaCommand, SEC_GAMEMASTER, Console::No }, - { "drunk", HandleModifyDrunkCommand, SEC_GAMEMASTER, Console::No }, - { "standstate", HandleModifyStandStateCommand, SEC_GAMEMASTER, Console::No }, - { "phase", HandleModifyPhaseCommand, SEC_GAMEMASTER, Console::No }, - { "gender", HandleModifyGenderCommand, SEC_GAMEMASTER, Console::No }, + { "hp", HandleModifyHPCommand, rbac::RBAC_PERM_COMMAND_MODIFY_HP, Console::No }, + { "mana", HandleModifyManaCommand, rbac::RBAC_PERM_COMMAND_MODIFY_MANA, Console::No }, + { "rage", HandleModifyRageCommand, rbac::RBAC_PERM_COMMAND_MODIFY_RAGE, Console::No }, + { "runicpower", HandleModifyRunicPowerCommand, rbac::RBAC_PERM_COMMAND_MODIFY_RUNICPOWER, Console::No }, + { "energy", HandleModifyEnergyCommand, rbac::RBAC_PERM_COMMAND_MODIFY_ENERGY, Console::No }, + { "money", HandleModifyMoneyCommand, rbac::RBAC_PERM_COMMAND_MODIFY_MONEY, Console::No }, + { "scale", HandleModifyScaleCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SCALE, Console::No }, + { "bit", HandleModifyBitCommand, rbac::RBAC_PERM_COMMAND_MODIFY_BIT, Console::No }, + { "faction", HandleModifyFactionCommand, rbac::RBAC_PERM_COMMAND_MODIFY_FACTION, Console::No }, + { "spell", HandleModifySpellCommand, rbac::RBAC_PERM_COMMAND_MODIFY_SPELL, Console::No }, + { "talentpoints", HandleModifyTalentCommand, rbac::RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS, Console::No }, + { "mount", HandleModifyMountCommand, rbac::RBAC_PERM_COMMAND_MODIFY_MOUNT, Console::No }, + { "honor", HandleModifyHonorCommand, rbac::RBAC_PERM_COMMAND_MODIFY_HONOR, Console::No }, + { "reputation", HandleModifyRepCommand, rbac::RBAC_PERM_COMMAND_MODIFY_REPUTATION, Console::No }, + { "arenapoints", HandleModifyArenaCommand, rbac::RBAC_PERM_COMMAND_MODIFY_ARENAPOINTS, Console::No }, + { "drunk", HandleModifyDrunkCommand, rbac::RBAC_PERM_COMMAND_MODIFY_DRUNK, Console::No }, + { "standstate", HandleModifyStandStateCommand, rbac::RBAC_PERM_COMMAND_MODIFY_STANDSTATE, Console::No }, + { "phase", HandleModifyPhaseCommand, rbac::RBAC_PERM_COMMAND_MODIFY_PHASE, Console::No }, + { "gender", HandleModifyGenderCommand, rbac::RBAC_PERM_COMMAND_MODIFY_GENDER, Console::No }, { "speed", modifyspeedCommandTable } }; static ChatCommandTable morphCommandTable = { - { "reset", HandleMorphResetCommand, SEC_MODERATOR, Console::No }, - { "target", HandleMorphTargetCommand, SEC_MODERATOR, Console::No }, - { "mount", HandleMorphMountCommand, SEC_MODERATOR, Console::No } + { "reset", HandleMorphResetCommand, rbac::RBAC_PERM_COMMAND_DEMORPH, Console::No }, + { "target", HandleMorphTargetCommand, rbac::RBAC_PERM_COMMAND_MORPH, Console::No }, + { "mount", HandleMorphMountCommand, rbac::RBAC_PERM_COMMAND_MORPH, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 84b5f430b..594c447c0 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -29,6 +29,7 @@ #include "Pet.h" #include "Player.h" #include "PoolMgr.h" +#include "RBAC.h" #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand #include "Transport.h" #include @@ -143,58 +144,58 @@ public: { static ChatCommandTable npcAddCommandTable = { - { "formation", HandleNpcAddFormationCommand, SEC_ADMINISTRATOR, Console::No }, - { "item", HandleNpcAddVendorItemCommand, SEC_ADMINISTRATOR, Console::No }, - { "move", HandleNpcAddMoveCommand, SEC_ADMINISTRATOR, Console::No }, - { "temp", HandleNpcAddTempSpawnCommand, SEC_ADMINISTRATOR, Console::No }, - { "", HandleNpcAddCommand, SEC_ADMINISTRATOR, Console::No } + { "formation", HandleNpcAddFormationCommand, rbac::RBAC_PERM_COMMAND_NPC_ADD_FORMATION, Console::No }, + { "item", HandleNpcAddVendorItemCommand, rbac::RBAC_PERM_COMMAND_NPC_ADD_ITEM, Console::No }, + { "move", HandleNpcAddMoveCommand, rbac::RBAC_PERM_COMMAND_NPC_ADD_MOVE, Console::No }, + { "temp", HandleNpcAddTempSpawnCommand, rbac::RBAC_PERM_COMMAND_NPC_ADD_TEMP, Console::No }, + { "", HandleNpcAddCommand, rbac::RBAC_PERM_COMMAND_NPC_ADD, Console::No } }; static ChatCommandTable npcDeleteCommandTable = { - { "item", HandleNpcDeleteVendorItemCommand, SEC_ADMINISTRATOR, Console::No }, - { "", HandleNpcDeleteCommand, SEC_ADMINISTRATOR, Console::No } + { "item", HandleNpcDeleteVendorItemCommand, rbac::RBAC_PERM_COMMAND_NPC_DELETE_ITEM, Console::No }, + { "", HandleNpcDeleteCommand, rbac::RBAC_PERM_COMMAND_NPC_DELETE, Console::No } }; static ChatCommandTable npcFollowCommandTable = { - { "stop", HandleNpcUnFollowCommand, SEC_GAMEMASTER, Console::No }, - { "", HandleNpcFollowCommand, SEC_GAMEMASTER, Console::No } + { "stop", HandleNpcUnFollowCommand, rbac::RBAC_PERM_COMMAND_NPC_FOLLOW_STOP, Console::No }, + { "", HandleNpcFollowCommand, rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, Console::No } }; static ChatCommandTable npcFactionCommandTable = { - { "permanent", HandleNpcSetFactionIdCommand, SEC_ADMINISTRATOR, Console::No }, - { "temp", HandleNpcSetFactionTempIdCommand, SEC_ADMINISTRATOR, Console::No }, - { "original", HandleNpcSetOriginalFaction, SEC_ADMINISTRATOR, Console::No } + { "permanent", HandleNpcSetFactionIdCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_FACTIONID, Console::No }, + { "temp", HandleNpcSetFactionTempIdCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_FACTIONID, Console::No }, + { "original", HandleNpcSetOriginalFaction, rbac::RBAC_PERM_COMMAND_NPC_SET_FACTIONID, Console::No } }; static ChatCommandTable npcSetCommandTable = { - { "allowmove", HandleNpcSetAllowMovementCommand, SEC_ADMINISTRATOR, Console::No }, - { "entry", HandleNpcSetEntryCommand, SEC_ADMINISTRATOR, Console::No }, + { "allowmove", HandleNpcSetAllowMovementCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_ALLOWMOVE, Console::No }, + { "entry", HandleNpcSetEntryCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_ENTRY, Console::No }, { "faction", npcFactionCommandTable}, - { "flag", HandleNpcSetFlagCommand, SEC_ADMINISTRATOR, Console::No }, - { "level", HandleNpcSetLevelCommand, SEC_ADMINISTRATOR, Console::No }, - { "link", HandleNpcSetLinkCommand, SEC_ADMINISTRATOR, Console::No }, - { "model", HandleNpcSetModelCommand, SEC_ADMINISTRATOR, Console::No }, - { "movetype", HandleNpcSetMoveTypeCommand, SEC_ADMINISTRATOR, Console::No }, - { "phase", HandleNpcSetPhaseCommand, SEC_ADMINISTRATOR, Console::No }, - { "wanderdistance", HandleNpcSetWanderDistanceCommand, SEC_ADMINISTRATOR, Console::No }, - { "spawntime", HandleNpcSetSpawnTimeCommand, SEC_ADMINISTRATOR, Console::No }, - { "data", HandleNpcSetDataCommand, SEC_ADMINISTRATOR, Console::No } + { "flag", HandleNpcSetFlagCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_FLAG, Console::No }, + { "level", HandleNpcSetLevelCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_LEVEL, Console::No }, + { "link", HandleNpcSetLinkCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_LINK, Console::No }, + { "model", HandleNpcSetModelCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_MODEL, Console::No }, + { "movetype", HandleNpcSetMoveTypeCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_MOVETYPE, Console::No }, + { "phase", HandleNpcSetPhaseCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_PHASE, Console::No }, + { "wanderdistance", HandleNpcSetWanderDistanceCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST, Console::No }, + { "spawntime", HandleNpcSetSpawnTimeCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME, Console::No }, + { "data", HandleNpcSetDataCommand, rbac::RBAC_PERM_COMMAND_NPC_SET_DATA, Console::No } }; static ChatCommandTable npcCommandTable = { - { "info", HandleNpcInfoCommand, SEC_GAMEMASTER, Console::No }, - { "guid", HandleNpcGuidCommand, SEC_GAMEMASTER, Console::No }, - { "near", HandleNpcNearCommand, SEC_GAMEMASTER, Console::No }, - { "move", HandleNpcMoveCommand, SEC_GAMEMASTER, Console::No }, - { "playemote", HandleNpcPlayEmoteCommand, SEC_GAMEMASTER, Console::No }, - { "say", HandleNpcSayCommand, SEC_GAMEMASTER, Console::No }, - { "textemote", HandleNpcTextEmoteCommand, SEC_GAMEMASTER, Console::No }, - { "whisper", HandleNpcWhisperCommand, SEC_GAMEMASTER, Console::No }, - { "yell", HandleNpcYellCommand, SEC_GAMEMASTER, Console::No }, - { "tame", HandleNpcTameCommand, SEC_GAMEMASTER, Console::No }, - { "do", HandleNpcDoActionCommand, SEC_GAMEMASTER, Console::No }, + { "info", HandleNpcInfoCommand, rbac::RBAC_PERM_COMMAND_NPC_INFO, Console::No }, + { "guid", HandleNpcGuidCommand, rbac::RBAC_PERM_COMMAND_NPC_INFO, Console::No }, + { "near", HandleNpcNearCommand, rbac::RBAC_PERM_COMMAND_NPC_NEAR, Console::No }, + { "move", HandleNpcMoveCommand, rbac::RBAC_PERM_COMMAND_NPC_MOVE, Console::No }, + { "playemote", HandleNpcPlayEmoteCommand, rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, Console::No }, + { "say", HandleNpcSayCommand, rbac::RBAC_PERM_COMMAND_NPC_SAY, Console::No }, + { "textemote", HandleNpcTextEmoteCommand, rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, Console::No }, + { "whisper", HandleNpcWhisperCommand, rbac::RBAC_PERM_COMMAND_NPC_WHISPER, Console::No }, + { "yell", HandleNpcYellCommand, rbac::RBAC_PERM_COMMAND_NPC_YELL, Console::No }, + { "tame", HandleNpcTameCommand, rbac::RBAC_PERM_COMMAND_NPC_TAME, Console::No }, + { "do", HandleNpcDoActionCommand, rbac::RBAC_PERM_COMMAND_NPC_EVADE, Console::No }, { "add", npcAddCommandTable }, { "delete", npcDeleteCommandTable }, { "follow", npcFollowCommandTable }, diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index d2c8d5b1d..42137e367 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -22,6 +22,7 @@ #include "ObjectMgr.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "SpellInfo.h" #include "SpellMgr.h" @@ -36,9 +37,9 @@ public: { static ChatCommandTable petCommandTable = { - { "create", HandlePetCreateCommand, SEC_GAMEMASTER, Console::No }, - { "learn", HandlePetLearnCommand, SEC_GAMEMASTER, Console::No }, - { "unlearn", HandlePetUnlearnCommand, SEC_GAMEMASTER, Console::No } + { "create", HandlePetCreateCommand, rbac::RBAC_PERM_COMMAND_PET_CREATE, Console::No }, + { "learn", HandlePetLearnCommand, rbac::RBAC_PERM_COMMAND_PET_LEARN, Console::No }, + { "unlearn", HandlePetUnlearnCommand, rbac::RBAC_PERM_COMMAND_PET_UNLEARN, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_player.cpp b/src/server/scripts/Commands/cs_player.cpp index 240db01a0..a0eb7e9ec 100644 --- a/src/server/scripts/Commands/cs_player.cpp +++ b/src/server/scripts/Commands/cs_player.cpp @@ -17,6 +17,7 @@ #include "CommandScript.h" #include "PlayerCommand.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -29,8 +30,8 @@ public: { static ChatCommandTable playerCommandTable = { - { "learn", HandlePlayerLearnCommand, SEC_GAMEMASTER, Console::Yes }, - { "unlearn", HandlePlayerUnLearnCommand, SEC_GAMEMASTER, Console::Yes } + { "learn", HandlePlayerLearnCommand, rbac::RBAC_PERM_COMMAND_LEARN, Console::Yes }, + { "unlearn", HandlePlayerUnLearnCommand, rbac::RBAC_PERM_COMMAND_UNLEARN, Console::Yes } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_player_settings.cpp b/src/server/scripts/Commands/cs_player_settings.cpp index 06f038b91..30aadef1b 100644 --- a/src/server/scripts/Commands/cs_player_settings.cpp +++ b/src/server/scripts/Commands/cs_player_settings.cpp @@ -19,6 +19,7 @@ #include "CommandScript.h" #include "Player.h" #include "PlayerSettings.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -31,7 +32,7 @@ public: { static ChatCommandTable playerSettingsCommandTable = { - { "announcer", HandleSettingsAnnouncerFlags, SEC_MODERATOR, Console::No }, + { "announcer", HandleSettingsAnnouncerFlags, rbac::RBAC_PERM_COMMAND_SETTINGS_ANNOUNCER, Console::No }, }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_pooltools.cpp b/src/server/scripts/Commands/cs_pooltools.cpp index a915d8156..db641a76a 100644 --- a/src/server/scripts/Commands/cs_pooltools.cpp +++ b/src/server/scripts/Commands/cs_pooltools.cpp @@ -25,6 +25,7 @@ #include "GridNotifiersImpl.h" #include "MapMgr.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "Tokenize.h" @@ -63,12 +64,12 @@ public: { static ChatCommandTable poolToolsCommandTable = { - { "start", HandlePoolStart, SEC_ADMINISTRATOR, Console::No }, - { "def", HandlePoolDef, SEC_ADMINISTRATOR, Console::No }, - { "add", HandlePoolAdd, SEC_ADMINISTRATOR, Console::No }, - { "remove", HandlePoolRemove, SEC_ADMINISTRATOR, Console::No }, - { "end", HandlePoolEnd, SEC_ADMINISTRATOR, Console::No }, - { "clear", HandlePoolClear, SEC_ADMINISTRATOR, Console::No } + { "start", HandlePoolStart, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "def", HandlePoolDef, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "add", HandlePoolAdd, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "remove", HandlePoolRemove, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "end", HandlePoolEnd, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No }, + { "clear", HandlePoolClear, rbac::RBAC_PERM_COMMAND_DEBUG, Console::No } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index daee0c91c..bc1faf49b 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -22,6 +22,7 @@ #include "GameTime.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "ReputationMgr.h" using namespace Acore::ChatCommands; @@ -35,11 +36,11 @@ public: { static ChatCommandTable questCommandTable = { - { "add", HandleQuestAdd, SEC_GAMEMASTER, Console::Yes }, - { "complete", HandleQuestComplete, SEC_GAMEMASTER, Console::Yes }, - { "remove", HandleQuestRemove, SEC_GAMEMASTER, Console::Yes }, - { "reward", HandleQuestReward, SEC_GAMEMASTER, Console::Yes }, - { "status", HandleQuestStatus, SEC_GAMEMASTER, Console::Yes }, + { "add", HandleQuestAdd, rbac::RBAC_PERM_COMMAND_QUEST_ADD, Console::Yes }, + { "complete", HandleQuestComplete, rbac::RBAC_PERM_COMMAND_QUEST_COMPLETE, Console::Yes }, + { "remove", HandleQuestRemove, rbac::RBAC_PERM_COMMAND_QUEST_REMOVE, Console::Yes }, + { "reward", HandleQuestReward, rbac::RBAC_PERM_COMMAND_QUEST_REWARD, Console::Yes }, + { "status", HandleQuestStatus, rbac::RBAC_PERM_COMMAND_QUEST, Console::Yes }, }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp new file mode 100644 index 000000000..7d80a33a7 --- /dev/null +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -0,0 +1,289 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "AccountMgr.h" +#include "Chat.h" +#include "CommandScript.h" +#include "Language.h" +#include "Player.h" +#include "RBAC.h" +#include "Realm.h" +#include "ScriptMgr.h" +#include "World.h" +#include "WorldSession.h" +#include "WorldSessionMgr.h" + +struct RBACCommandData +{ + RBACCommandData(rbac::RBACData* rbac_, bool needDelete_) : rbac(rbac_), needDelete(needDelete_) { } + RBACCommandData(RBACCommandData const&) = delete; + ~RBACCommandData() + { + if (needDelete) + delete rbac; + } + + rbac::RBACData* rbac = nullptr; + bool needDelete = false; +}; + +using namespace Acore::ChatCommands; + +class rbac_commandscript : public CommandScript +{ +public: + rbac_commandscript() : CommandScript("rbac_commandscript") { } + + ChatCommandTable GetCommands() const override + { + static ChatCommandTable rbacAccountCommandTable = + { + { "list", HandleRBACPermListCommand, LANG_RBAC_HELP_ACC_LIST, rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_LIST, Console::Yes }, + { "grant", HandleRBACPermGrantCommand, LANG_RBAC_HELP_ACC_GRANT, rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_GRANT, Console::Yes }, + { "deny", HandleRBACPermDenyCommand, LANG_RBAC_HELP_ACC_DENY, rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY, Console::Yes }, + { "revoke", HandleRBACPermRevokeCommand, LANG_RBAC_HELP_ACC_REVOKE, rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE, Console::Yes }, + }; + + static ChatCommandTable rbacCommandTable = + { + { "account", rbacAccountCommandTable }, + { "list", HandleRBACListPermissionsCommand, rbac::RBAC_PERM_COMMAND_RBAC_LIST, Console::Yes }, + }; + + static ChatCommandTable commandTable = + { + { "rbac", rbacCommandTable }, + }; + + return commandTable; + } + + static RBACCommandData GetRBACData(uint32 accountId, std::string const& accountName) + { + if (WorldSession* session = sWorldSessionMgr->FindSession(accountId)) + return { session->GetRBACData(), false }; + + rbac::RBACData* rbac = new rbac::RBACData(accountId, accountName, realm.Id.Realm, AccountMgr::GetSecurity(accountId, realm.Id.Realm)); + rbac->LoadFromDB(); + + return { rbac, true }; + } + + static bool HandleRBACPermGrantCommand(ChatHandler* handler, AccountIdentifier account, uint32 permId, Optional realmId) + { + if (handler->HasLowerSecurityAccount(nullptr, account.GetID(), true)) + return false; + + if (!realmId) + realmId = -1; + + RBACCommandData data = GetRBACData(account.GetID(), account.GetName()); + + rbac::RBACCommandResult result = data.rbac->GrantPermission(permId, *realmId); + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(permId); + + switch (result) + { + case rbac::RBAC_CANT_ADD_ALREADY_ADDED: + handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED_IN_LIST, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_IN_DENIED_LIST: + handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED_IN_DENIED_LIST, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_OK: + handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_ID_DOES_NOT_EXISTS: + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, permId); + break; + default: + break; + } + + return true; + } + + static bool HandleRBACPermDenyCommand(ChatHandler* handler, AccountIdentifier account, uint32 permId, Optional realmId) + { + if (handler->HasLowerSecurityAccount(nullptr, account.GetID(), true)) + return false; + + if (!realmId) + realmId = -1; + + RBACCommandData data = GetRBACData(account.GetID(), account.GetName()); + + rbac::RBACCommandResult result = data.rbac->DenyPermission(permId, *realmId); + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(permId); + + switch (result) + { + case rbac::RBAC_CANT_ADD_ALREADY_ADDED: + handler->PSendSysMessage(LANG_RBAC_PERM_DENIED_IN_LIST, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_IN_GRANTED_LIST: + handler->PSendSysMessage(LANG_RBAC_PERM_DENIED_IN_GRANTED_LIST, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_OK: + handler->PSendSysMessage(LANG_RBAC_PERM_DENIED, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_ID_DOES_NOT_EXISTS: + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, permId); + break; + default: + break; + } + + return true; + } + + static bool HandleRBACPermRevokeCommand(ChatHandler* handler, AccountIdentifier account, uint32 permId, Optional realmId) + { + if (handler->HasLowerSecurityAccount(nullptr, account.GetID(), true)) + return false; + + if (!realmId) + realmId = -1; + + RBACCommandData data = GetRBACData(account.GetID(), account.GetName()); + + rbac::RBACCommandResult result = data.rbac->RevokePermission(permId, *realmId); + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(permId); + + switch (result) + { + case rbac::RBAC_CANT_REVOKE_NOT_IN_LIST: + handler->PSendSysMessage(LANG_RBAC_PERM_REVOKED_NOT_IN_LIST, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_OK: + handler->PSendSysMessage(LANG_RBAC_PERM_REVOKED, permId, permission->GetName().c_str(), + *realmId, account.GetID(), account.GetName().c_str()); + break; + case rbac::RBAC_ID_DOES_NOT_EXISTS: + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, permId); + break; + default: + break; + } + + return true; + } + + static char const* GetSecurityLevelName(uint8 secLevel) + { + switch (secLevel) + { + case SEC_PLAYER: return "SEC_PLAYER"; + case SEC_MODERATOR: return "SEC_MODERATOR"; + case SEC_GAMEMASTER: return "SEC_GAMEMASTER"; + case SEC_ADMINISTRATOR: return "SEC_ADMINISTRATOR"; + case SEC_CONSOLE: return "SEC_CONSOLE"; + default: return "Unknown"; + } + } + + static bool HandleRBACPermListCommand(ChatHandler* handler, AccountIdentifier account) + { + RBACCommandData data = GetRBACData(account.GetID(), account.GetName()); + + handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_GRANTED, data.rbac->GetId(), data.rbac->GetName().c_str()); + rbac::RBACPermissionContainer const& granted = data.rbac->GetGrantedPermissions(); + if (granted.empty()) + handler->SendSysMessage(handler->GetAcoreString(LANG_RBAC_LIST_EMPTY)); + else + { + for (uint32 grantedId : granted) + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(grantedId); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + + handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_DENIED, data.rbac->GetId(), data.rbac->GetName().c_str()); + rbac::RBACPermissionContainer const& denied = data.rbac->GetDeniedPermissions(); + if (denied.empty()) + handler->SendSysMessage(handler->GetAcoreString(LANG_RBAC_LIST_EMPTY)); + else + { + for (uint32 deniedId : denied) + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(deniedId); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + + handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_BY_SEC_LEVEL, data.rbac->GetId(), data.rbac->GetName().c_str(), + data.rbac->GetSecurityLevel(), GetSecurityLevelName(data.rbac->GetSecurityLevel())); + rbac::RBACPermissionContainer const& defaultPermissions = sAccountMgr->GetRBACDefaultPermissions(data.rbac->GetSecurityLevel()); + if (defaultPermissions.empty()) + handler->SendSysMessage(handler->GetAcoreString(LANG_RBAC_LIST_EMPTY)); + else + { + for (uint32 defaultPermission : defaultPermissions) + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(defaultPermission); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + + return true; + } + + static bool HandleRBACListPermissionsCommand(ChatHandler* handler, Optional permId) + { + if (!permId) + { + rbac::RBACPermissionsContainer const& permissions = sAccountMgr->GetRBACPermissionList(); + handler->SendSysMessage(handler->GetAcoreString(LANG_RBAC_LIST_PERMISSIONS_HEADER)); + for (auto const& [_, permission] : permissions) + { + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + else + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*permId); + if (!permission) + { + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, *permId); + handler->SetSentErrorMessage(true); + return false; + } + + handler->SendSysMessage(handler->GetAcoreString(LANG_RBAC_LIST_PERMISSIONS_HEADER)); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + handler->SendSysMessage(handler->GetAcoreString(LANG_RBAC_LIST_PERMS_LINKED_HEADER)); + for (uint32 linkedPerm : permission->GetLinkedPermissions()) + if (rbac::RBACPermission const* rbacPermission = sAccountMgr->GetRBACPermission(linkedPerm)) + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, rbacPermission->GetId(), rbacPermission->GetName().c_str()); + } + + return true; + } +}; + +void AddSC_rbac_commandscript() +{ + new rbac_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index ef121f039..ef6cf787a 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -15,6 +15,7 @@ * with this program. If not, see . */ +#include "AccountMgr.h" #include "AchievementMgr.h" #include "AuctionHouseMgr.h" #include "AutobroadcastMgr.h" @@ -31,6 +32,7 @@ #include "MotdMgr.h" #include "ObjectMgr.h" #include "PoolMgr.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "ServerMailMgr.h" #include "SkillDiscovery.h" @@ -55,122 +57,123 @@ public: { static ChatCommandTable reloadAllCommandTable = { - { "achievement", HandleReloadAllAchievementCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "area", HandleReloadAllAreaCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gossips", HandleReloadAllGossipsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "item", HandleReloadAllItemCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "locales", HandleReloadAllLocalesCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "loot", HandleReloadAllLootCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "npc", HandleReloadAllNpcCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest", HandleReloadAllQuestCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "scripts", HandleReloadAllScriptsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell", HandleReloadAllSpellCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "", HandleReloadAllCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "achievement", HandleReloadAllAchievementCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT, Console::Yes }, + { "area", HandleReloadAllAreaCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_AREA, Console::Yes }, + { "gossips", HandleReloadAllGossipsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_GOSSIP, Console::Yes }, + { "item", HandleReloadAllItemCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ITEM, Console::Yes }, + { "locales", HandleReloadAllLocalesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOCALES, Console::Yes }, + { "loot", HandleReloadAllLootCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOOT, Console::Yes }, + { "npc", HandleReloadAllNpcCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_NPC, Console::Yes }, + { "quest", HandleReloadAllQuestCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_QUEST, Console::Yes }, + { "scripts", HandleReloadAllScriptsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_SCRIPTS, Console::Yes }, + { "spell", HandleReloadAllSpellCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL_SPELL, Console::Yes }, + { "", HandleReloadAllCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ALL, Console::Yes }, }; static ChatCommandTable reloadCommandTable = { - { "antidos_opcode_policies", HandleReloadAntiDosOpcodePoliciesCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "auctions", HandleReloadAuctionsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "dungeon_access_template", HandleReloadDungeonAccessCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "dungeon_access_requirements", HandleReloadDungeonAccessCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "achievement_criteria_data", HandleReloadAchievementCriteriaDataCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "achievement_reward", HandleReloadAchievementRewardCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "antidos_opcode_policies", HandleReloadAntiDosOpcodePoliciesCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "auctions", HandleReloadAuctionsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_AUCTIONS, Console::Yes }, + { "dungeon_access_template", HandleReloadDungeonAccessCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT, Console::Yes }, + { "dungeon_access_requirements", HandleReloadDungeonAccessCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT, Console::Yes }, + { "achievement_criteria_data", HandleReloadAchievementCriteriaDataCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_CRITERIA_DATA, Console::Yes }, + { "achievement_reward", HandleReloadAchievementRewardCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD, Console::Yes }, { "all", reloadAllCommandTable }, - { "areatrigger", HandleReloadQuestAreaTriggersCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "areatrigger_involvedrelation", HandleReloadQuestAreaTriggersCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "areatrigger_tavern", HandleReloadAreaTriggerTavernCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "areatrigger_teleport", HandleReloadAreaTriggerTeleportCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "autobroadcast", HandleReloadAutobroadcastCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "motd", HandleReloadMotdCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "broadcast_text", HandleReloadBroadcastTextCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "battleground_template", HandleReloadBattlegroundTemplate, SEC_ADMINISTRATOR, Console::Yes }, - { "command", HandleReloadCommandCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "conditions", HandleReloadConditions, SEC_ADMINISTRATOR, Console::Yes }, - { "config", HandleReloadConfigCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_text", HandleReloadCreatureText, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_questender", HandleReloadCreatureQuestEnderCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_linked_respawn", HandleReloadLinkedRespawnCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_loot_template", HandleReloadLootTemplatesCreatureCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_movement_override", HandleReloadCreatureMovementOverrideCommand, SEC_ADMINISTRATOR, Console::Yes}, - { "creature_onkill_reputation", HandleReloadOnKillReputationCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_queststarter", HandleReloadCreatureQuestStarterCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_template", HandleReloadCreatureTemplateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "disables", HandleReloadDisablesCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "disenchant_loot_template", HandleReloadLootTemplatesDisenchantCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "event_scripts", HandleReloadEventScriptsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "fishing_loot_template", HandleReloadLootTemplatesFishingCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "game_graveyard", HandleReloadGameGraveyardCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "graveyard_zone", HandleReloadGameGraveyardZoneCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "game_tele", HandleReloadGameTeleCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gameobject_questender", HandleReloadGOQuestEnderCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gameobject_loot_template", HandleReloadLootTemplatesGameobjectCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gameobject_queststarter", HandleReloadGOQuestStarterCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gm_tickets", HandleReloadGMTicketsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gossip_menu", HandleReloadGossipMenuCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gossip_menu_option", HandleReloadGossipMenuOptionCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "item_enchantment_template", HandleReloadItemEnchantementsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "item_loot_template", HandleReloadLootTemplatesItemCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "item_set_names", HandleReloadItemSetNamesCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "lfg_dungeon_rewards", HandleReloadLfgRewardsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "achievement_reward_locale", HandleReloadLocalesAchievementRewardCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_template_locale", HandleReloadLocalesCreatureCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "creature_text_locale", HandleReloadLocalesCreatureTextCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gameobject_template_locale", HandleReloadLocalesGameobjectCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gossip_menu_option_locale", HandleReloadLocalesGossipMenuOptionCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "item_template_locale", HandleReloadLocalesItemCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "item_set_name_locale", HandleReloadLocalesItemSetNameCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "npc_text_locale", HandleReloadLocalesNpcTextCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "page_text_locale", HandleReloadLocalesPageTextCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "points_of_interest_locale", HandleReloadLocalesPointsOfInterestCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest_template_locale", HandleReloadLocalesQuestCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest_offer_reward_locale", HandleReloadLocalesQuestOfferRewardCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest_request_item_locale", HandleReloadLocalesQuestRequestItemsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "mail_level_reward", HandleReloadMailLevelRewardCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "mail_loot_template", HandleReloadLootTemplatesMailCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "mail_server_template", HandleReloadMailServerTemplateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "milling_loot_template", HandleReloadLootTemplatesMillingCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "npc_spellclick_spells", HandleReloadSpellClickSpellsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "trainer", HandleReloadTrainerCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "npc_vendor", HandleReloadNpcVendorCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "game_event_npc_vendor", HandleReloadGameEventNPCVendorCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "page_text", HandleReloadPageTextsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "pickpocketing_loot_template", HandleReloadLootTemplatesPickpocketingCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "points_of_interest", HandleReloadPointsOfInterestCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "prospecting_loot_template", HandleReloadLootTemplatesProspectingCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest_greeting", HandleReloadQuestGreetingCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest_poi", HandleReloadQuestPOICommand, SEC_ADMINISTRATOR, Console::Yes }, - { "quest_template", HandleReloadQuestTemplateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "reference_loot_template", HandleReloadLootTemplatesReferenceCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "reserved_name", HandleReloadReservedNameCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "profanity_name", HandleReloadProfanityNameCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "reputation_reward_rate", HandleReloadReputationRewardRateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "reputation_spillover_template", HandleReloadReputationRewardRateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "skill_discovery_template", HandleReloadSkillDiscoveryTemplateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "skill_extra_item_template", HandleReloadSkillExtraItemTemplateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "skill_fishing_base_level", HandleReloadSkillFishingBaseLevelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "skinning_loot_template", HandleReloadLootTemplatesSkinningCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "smart_scripts", HandleReloadSmartScripts, SEC_ADMINISTRATOR, Console::Yes }, - { "spawn_group", HandleReloadSpawnGroupCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_required", HandleReloadSpellRequiredCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_area", HandleReloadSpellAreaCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_bonus_data", HandleReloadSpellBonusesCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_group", HandleReloadSpellGroupsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_loot_template", HandleReloadLootTemplatesSpellCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_linked_spell", HandleReloadSpellLinkedSpellCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_pet_auras", HandleReloadSpellPetAurasCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_proc", HandleReloadSpellProcsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_scripts", HandleReloadSpellScriptsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_target_position", HandleReloadSpellTargetPositionCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_threats", HandleReloadSpellThreatsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spell_group_stack_rules", HandleReloadSpellGroupStackRulesCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "player_loot_template", HandleReloadLootTemplatesPlayerCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "module_string", HandleReloadModuleStringCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "acore_string", HandleReloadAcoreStringCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "warden_action", HandleReloadWardenactionCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "waypoint_scripts", HandleReloadWpScriptsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "waypoint_data", HandleReloadWpCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "vehicle_accessory", HandleReloadVehicleAccessoryCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "vehicle_template_accessory", HandleReloadVehicleTemplateAccessoryCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "areatrigger", HandleReloadQuestAreaTriggersCommand, rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_INVOLVEDRELATION, Console::Yes }, + { "areatrigger_involvedrelation", HandleReloadQuestAreaTriggersCommand, rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_INVOLVEDRELATION, Console::Yes }, + { "areatrigger_tavern", HandleReloadAreaTriggerTavernCommand, rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TAVERN, Console::Yes }, + { "areatrigger_teleport", HandleReloadAreaTriggerTeleportCommand, rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TELEPORT, Console::Yes }, + { "autobroadcast", HandleReloadAutobroadcastCommand, rbac::RBAC_PERM_COMMAND_RELOAD_AUTOBROADCAST, Console::Yes }, + { "motd", HandleReloadMotdCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "broadcast_text", HandleReloadBroadcastTextCommand, rbac::RBAC_PERM_COMMAND_RELOAD_BROADCAST_TEXT, Console::Yes }, + { "battleground_template", HandleReloadBattlegroundTemplate, rbac::RBAC_PERM_COMMAND_RELOAD_BATTLEGROUND_TEMPLATE, Console::Yes }, + { "command", HandleReloadCommandCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "conditions", HandleReloadConditions, rbac::RBAC_PERM_COMMAND_RELOAD_CONDITIONS, Console::Yes }, + { "config", HandleReloadConfigCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CONFIG, Console::Yes }, + { "creature_text", HandleReloadCreatureText, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT, Console::Yes }, + { "creature_questender", HandleReloadCreatureQuestEnderCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER, Console::Yes }, + { "creature_linked_respawn", HandleReloadLinkedRespawnCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN, Console::Yes }, + { "creature_loot_template", HandleReloadLootTemplatesCreatureCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE, Console::Yes }, + { "creature_movement_override", HandleReloadCreatureMovementOverrideCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_MOVEMENT_OVERRIDE, Console::Yes}, + { "creature_onkill_reputation", HandleReloadOnKillReputationCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION, Console::Yes }, + { "creature_queststarter", HandleReloadCreatureQuestStarterCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER, Console::Yes }, + { "creature_template", HandleReloadCreatureTemplateCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE, Console::Yes }, + { "disables", HandleReloadDisablesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_DISABLES, Console::Yes }, + { "disenchant_loot_template", HandleReloadLootTemplatesDisenchantCommand, rbac::RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE, Console::Yes }, + { "event_scripts", HandleReloadEventScriptsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS, Console::Yes }, + { "fishing_loot_template", HandleReloadLootTemplatesFishingCommand, rbac::RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE, Console::Yes }, + { "game_graveyard", HandleReloadGameGraveyardCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "graveyard_zone", HandleReloadGameGraveyardZoneCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE, Console::Yes }, + { "game_tele", HandleReloadGameTeleCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GAME_TELE, Console::Yes }, + { "gameobject_questender", HandleReloadGOQuestEnderCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER, Console::Yes }, + { "gameobject_loot_template", HandleReloadLootTemplatesGameobjectCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE, Console::Yes }, + { "gameobject_queststarter", HandleReloadGOQuestStarterCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTSTARTER, Console::Yes }, + { "gm_tickets", HandleReloadGMTicketsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GM_TICKETS, Console::Yes }, + { "gossip_menu", HandleReloadGossipMenuCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU, Console::Yes }, + { "gossip_menu_option", HandleReloadGossipMenuOptionCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION, Console::Yes }, + { "item_enchantment_template", HandleReloadItemEnchantementsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_ENCHANTMENT_TEMPLATE, Console::Yes }, + { "item_loot_template", HandleReloadLootTemplatesItemCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_LOOT_TEMPLATE, Console::Yes }, + { "item_set_names", HandleReloadItemSetNamesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAMES, Console::Yes }, + { "lfg_dungeon_rewards", HandleReloadLfgRewardsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_LFG_DUNGEON_REWARDS, Console::Yes }, + { "achievement_reward_locale", HandleReloadLocalesAchievementRewardCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD_LOCALE, Console::Yes }, + { "creature_template_locale", HandleReloadLocalesCreatureCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE_LOCALE, Console::Yes }, + { "creature_text_locale", HandleReloadLocalesCreatureTextCommand, rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT_LOCALE, Console::Yes }, + { "gameobject_template_locale", HandleReloadLocalesGameobjectCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_TEMPLATE_LOCALE, Console::Yes }, + { "gossip_menu_option_locale", HandleReloadLocalesGossipMenuOptionCommand, rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION_LOCALE, Console::Yes }, + { "item_template_locale", HandleReloadLocalesItemCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_TEMPLATE_LOCALE, Console::Yes }, + { "item_set_name_locale", HandleReloadLocalesItemSetNameCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAME_LOCALE, Console::Yes }, + { "npc_text_locale", HandleReloadLocalesNpcTextCommand, rbac::RBAC_PERM_COMMAND_RELOAD_NPC_TEXT_LOCALE, Console::Yes }, + { "page_text_locale", HandleReloadLocalesPageTextCommand, rbac::RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT_LOCALE, Console::Yes }, + { "points_of_interest_locale", HandleReloadLocalesPointsOfInterestCommand, rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST_LOCALE, Console::Yes }, + { "quest_template_locale", HandleReloadLocalesQuestCommand, rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE_LOCALE, Console::Yes }, + { "quest_offer_reward_locale", HandleReloadLocalesQuestOfferRewardCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "quest_request_item_locale", HandleReloadLocalesQuestRequestItemsCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "mail_level_reward", HandleReloadMailLevelRewardCommand, rbac::RBAC_PERM_COMMAND_RELOAD_MAIL_LEVEL_REWARD, Console::Yes }, + { "mail_loot_template", HandleReloadLootTemplatesMailCommand, rbac::RBAC_PERM_COMMAND_RELOAD_MAIL_LOOT_TEMPLATE, Console::Yes }, + { "mail_server_template", HandleReloadMailServerTemplateCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "milling_loot_template", HandleReloadLootTemplatesMillingCommand, rbac::RBAC_PERM_COMMAND_RELOAD_MILLING_LOOT_TEMPLATE, Console::Yes }, + { "npc_spellclick_spells", HandleReloadSpellClickSpellsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_NPC_SPELLCLICK_SPELLS, Console::Yes }, + { "trainer", HandleReloadTrainerCommand, rbac::RBAC_PERM_COMMAND_RELOAD_TRAINER, Console::Yes }, + { "npc_vendor", HandleReloadNpcVendorCommand, rbac::RBAC_PERM_COMMAND_RELOAD_NPC_VENDOR, Console::Yes }, + { "game_event_npc_vendor", HandleReloadGameEventNPCVendorCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "page_text", HandleReloadPageTextsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT, Console::Yes }, + { "pickpocketing_loot_template", HandleReloadLootTemplatesPickpocketingCommand, rbac::RBAC_PERM_COMMAND_RELOAD_PICKPOCKETING_LOOT_TEMPLATE, Console::Yes }, + { "points_of_interest", HandleReloadPointsOfInterestCommand, rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST, Console::Yes }, + { "prospecting_loot_template", HandleReloadLootTemplatesProspectingCommand, rbac::RBAC_PERM_COMMAND_RELOAD_PROSPECTING_LOOT_TEMPLATE, Console::Yes }, + { "quest_greeting", HandleReloadQuestGreetingCommand, rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING, Console::Yes }, + { "quest_poi", HandleReloadQuestPOICommand, rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_POI, Console::Yes }, + { "quest_template", HandleReloadQuestTemplateCommand, rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE, Console::Yes }, + { "rbac", HandleReloadRBACCommand, rbac::RBAC_PERM_COMMAND_RELOAD_RBAC, Console::Yes }, + { "reference_loot_template", HandleReloadLootTemplatesReferenceCommand, rbac::RBAC_PERM_COMMAND_RELOAD_REFERENCE_LOOT_TEMPLATE, Console::Yes }, + { "reserved_name", HandleReloadReservedNameCommand, rbac::RBAC_PERM_COMMAND_RELOAD_RESERVED_NAME, Console::Yes }, + { "profanity_name", HandleReloadProfanityNameCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "reputation_reward_rate", HandleReloadReputationRewardRateCommand, rbac::RBAC_PERM_COMMAND_RELOAD_REPUTATION_REWARD_RATE, Console::Yes }, + { "reputation_spillover_template", HandleReloadReputationRewardRateCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPILLOVER_TEMPLATE, Console::Yes }, + { "skill_discovery_template", HandleReloadSkillDiscoveryTemplateCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_DISCOVERY_TEMPLATE, Console::Yes }, + { "skill_extra_item_template", HandleReloadSkillExtraItemTemplateCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE, Console::Yes }, + { "skill_fishing_base_level", HandleReloadSkillFishingBaseLevelCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_FISHING_BASE_LEVEL, Console::Yes }, + { "skinning_loot_template", HandleReloadLootTemplatesSkinningCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SKINNING_LOOT_TEMPLATE, Console::Yes }, + { "smart_scripts", HandleReloadSmartScripts, rbac::RBAC_PERM_COMMAND_RELOAD_SMART_SCRIPTS, Console::Yes }, + { "spawn_group", HandleReloadSpawnGroupCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "spell_required", HandleReloadSpellRequiredCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_REQUIRED, Console::Yes }, + { "spell_area", HandleReloadSpellAreaCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_AREA, Console::Yes }, + { "spell_bonus_data", HandleReloadSpellBonusesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA, Console::Yes }, + { "spell_group", HandleReloadSpellGroupsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP, Console::Yes }, + { "spell_loot_template", HandleReloadLootTemplatesSpellCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE, Console::Yes }, + { "spell_linked_spell", HandleReloadSpellLinkedSpellCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LINKED_SPELL, Console::Yes }, + { "spell_pet_auras", HandleReloadSpellPetAurasCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PET_AURAS, Console::Yes }, + { "spell_proc", HandleReloadSpellProcsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC, Console::Yes }, + { "spell_scripts", HandleReloadSpellScriptsCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "spell_target_position", HandleReloadSpellTargetPositionCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION, Console::Yes }, + { "spell_threats", HandleReloadSpellThreatsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_THREATS, Console::Yes }, + { "spell_group_stack_rules", HandleReloadSpellGroupStackRulesCommand, rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP_STACK_RULES, Console::Yes }, + { "player_loot_template", HandleReloadLootTemplatesPlayerCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "module_string", HandleReloadModuleStringCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "acore_string", HandleReloadAcoreStringCommand, rbac::RBAC_PERM_COMMAND_RELOAD_ACORE_STRING, Console::Yes }, + { "warden_action", HandleReloadWardenactionCommand, rbac::RBAC_PERM_COMMAND_RELOAD, Console::Yes }, + { "waypoint_scripts", HandleReloadWpScriptsCommand, rbac::RBAC_PERM_COMMAND_RELOAD_WAYPOINT_SCRIPTS, Console::Yes }, + { "waypoint_data", HandleReloadWpCommand, rbac::RBAC_PERM_COMMAND_RELOAD_WAYPOINT_DATA, Console::Yes }, + { "vehicle_accessory", HandleReloadVehicleAccessoryCommand, rbac::RBAC_PERM_COMMAND_RELOAD_VEHICLE_ACCESSORY, Console::Yes }, + { "vehicle_template_accessory", HandleReloadVehicleTemplateAccessoryCommand, rbac::RBAC_PERM_COMMAND_RELOAD_VEHICLE_TEMPLATE_ACCESSORY, Console::Yes }, }; static ChatCommandTable commandTable = { @@ -579,6 +582,15 @@ public: return true; } + static bool HandleReloadRBACCommand(ChatHandler* handler) + { + LOG_INFO("rbac", "Reloading RBAC tables..."); + sAccountMgr->LoadRBAC(); + sWorld->ReloadRBAC(); + handler->SendGlobalGMSysMessage("RBAC data reloaded."); + return true; + } + static bool HandleReloadLootTemplatesCreatureCommand(ChatHandler* handler) { LOG_INFO("server.loading", "Reloading Loot Tables... (`creature_loot_template`)"); diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index c3a6772cc..bc61aa5e0 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -21,6 +21,7 @@ #include "Language.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "ScriptMgr.h" #include "WorldSessionMgr.h" @@ -36,25 +37,25 @@ public: { static ChatCommandTable resetItemsCommandTable = { - { "equipped", HandleResetItemsEquippedCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "bags", HandleResetItemsInBagsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "bank", HandleResetItemsInBankCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "keyring", HandleResetItemsKeyringCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "currency", HandleResetItemsInCurrenciesListCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "vendor_buyback", HandleResetItemsInVendorBuyBackTabCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "all", HandleResetItemsAllCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "allbags", HandleResetItemsAllAndDeleteBagsCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "equipped", HandleResetItemsEquippedCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "bags", HandleResetItemsInBagsCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "bank", HandleResetItemsInBankCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "keyring", HandleResetItemsKeyringCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "currency", HandleResetItemsInCurrenciesListCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "vendor_buyback", HandleResetItemsInVendorBuyBackTabCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "all", HandleResetItemsAllCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, + { "allbags", HandleResetItemsAllAndDeleteBagsCommand, rbac::RBAC_PERM_COMMAND_RESET, Console::Yes }, }; static ChatCommandTable resetCommandTable = { - { "achievements", HandleResetAchievementsCommand, SEC_CONSOLE, Console::Yes }, - { "honor", HandleResetHonorCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "level", HandleResetLevelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "spells", HandleResetSpellsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "stats", HandleResetStatsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "talents", HandleResetTalentsCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "items", resetItemsCommandTable }, - { "all", HandleResetAllCommand, SEC_CONSOLE, Console::Yes } + { "achievements", HandleResetAchievementsCommand, rbac::RBAC_PERM_COMMAND_RESET_ACHIEVEMENTS, Console::Yes }, + { "honor", HandleResetHonorCommand, rbac::RBAC_PERM_COMMAND_RESET_HONOR, Console::Yes }, + { "level", HandleResetLevelCommand, rbac::RBAC_PERM_COMMAND_RESET_LEVEL, Console::Yes }, + { "spells", HandleResetSpellsCommand, rbac::RBAC_PERM_COMMAND_RESET_SPELLS, Console::Yes }, + { "stats", HandleResetStatsCommand, rbac::RBAC_PERM_COMMAND_RESET_STATS, Console::Yes }, + { "talents", HandleResetTalentsCommand, rbac::RBAC_PERM_COMMAND_RESET_TALENTS, Console::Yes }, + { "items", resetItemsCommandTable }, + { "all", HandleResetAllCommand, rbac::RBAC_PERM_COMMAND_RESET_ALL, Console::Yes } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_script_loader.cpp b/src/server/scripts/Commands/cs_script_loader.cpp index 9507a4bdd..9ad077a6a 100644 --- a/src/server/scripts/Commands/cs_script_loader.cpp +++ b/src/server/scripts/Commands/cs_script_loader.cpp @@ -54,6 +54,7 @@ void AddSC_player_commandscript(); void AddSC_pool_commandscript(); void AddSC_pooltools_commandscript(); void AddSC_quest_commandscript(); +void AddSC_rbac_commandscript(); void AddSC_reload_commandscript(); void AddSC_reset_commandscript(); void AddSC_send_commandscript(); @@ -111,6 +112,7 @@ void AddCommandsScripts() AddSC_pool_commandscript(); AddSC_pooltools_commandscript(); AddSC_quest_commandscript(); + AddSC_rbac_commandscript(); AddSC_reload_commandscript(); AddSC_reset_commandscript(); AddSC_send_commandscript(); diff --git a/src/server/scripts/Commands/cs_send.cpp b/src/server/scripts/Commands/cs_send.cpp index ee74a22a0..3e3d6f56f 100644 --- a/src/server/scripts/Commands/cs_send.cpp +++ b/src/server/scripts/Commands/cs_send.cpp @@ -23,6 +23,7 @@ #include "ObjectMgr.h" #include "Pet.h" #include "Player.h" +#include "RBAC.h" #include "Tokenize.h" using namespace Acore::ChatCommands; @@ -36,10 +37,10 @@ public: { static ChatCommandTable sendCommandTable = { - { "items", HandleSendItemsCommand, SEC_GAMEMASTER, Console::Yes }, - { "mail", HandleSendMailCommand, SEC_GAMEMASTER, Console::Yes }, - { "message", HandleSendMessageCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "money", HandleSendMoneyCommand, SEC_GAMEMASTER, Console::Yes } + { "items", HandleSendItemsCommand, rbac::RBAC_PERM_COMMAND_SEND_ITEMS, Console::Yes }, + { "mail", HandleSendMailCommand, rbac::RBAC_PERM_COMMAND_SEND_MAIL, Console::Yes }, + { "message", HandleSendMessageCommand, rbac::RBAC_PERM_COMMAND_SEND_MESSAGE, Console::Yes }, + { "money", HandleSendMoneyCommand, rbac::RBAC_PERM_COMMAND_SEND_MONEY, Console::Yes } }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 98bfbbac3..fd4c51e72 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -25,6 +25,7 @@ #include "ModuleMgr.h" #include "MotdMgr.h" #include "MySQLThreading.h" +#include "RBAC.h" #include "Realm.h" #include "StringConvert.h" #include "UpdateTime.h" @@ -48,44 +49,44 @@ public: { static ChatCommandTable serverIdleRestartCommandTable = { - { "cancel", HandleServerShutDownCancelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "", HandleServerIdleRestartCommand, SEC_CONSOLE, Console::Yes } + { "cancel", HandleServerShutDownCancelCommand, rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART_CANCEL, Console::Yes }, + { "", HandleServerIdleRestartCommand, rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, Console::Yes } }; static ChatCommandTable serverIdleShutdownCommandTable = { - { "cancel", HandleServerShutDownCancelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "", HandleServerIdleShutDownCommand, SEC_CONSOLE, Console::Yes } + { "cancel", HandleServerShutDownCancelCommand, rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN_CANCEL, Console::Yes }, + { "", HandleServerIdleShutDownCommand, rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, Console::Yes } }; static ChatCommandTable serverRestartCommandTable = { - { "cancel", HandleServerShutDownCancelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "", HandleServerRestartCommand, SEC_ADMINISTRATOR, Console::Yes } + { "cancel", HandleServerShutDownCancelCommand, rbac::RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL, Console::Yes }, + { "", HandleServerRestartCommand, rbac::RBAC_PERM_COMMAND_SERVER_RESTART, Console::Yes } }; static ChatCommandTable serverShutdownCommandTable = { - { "cancel", HandleServerShutDownCancelCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "", HandleServerShutDownCommand, SEC_ADMINISTRATOR, Console::Yes } + { "cancel", HandleServerShutDownCancelCommand, rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL, Console::Yes }, + { "", HandleServerShutDownCommand, rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, Console::Yes } }; static ChatCommandTable serverSetCommandTable = { - { "loglevel", HandleServerSetLogLevelCommand, SEC_CONSOLE, Console::Yes }, - { "motd", HandleServerSetMotdCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "closed", HandleServerSetClosedCommand, SEC_CONSOLE, Console::Yes }, + { "loglevel", HandleServerSetLogLevelCommand, rbac::RBAC_PERM_COMMAND_SERVER_SET_LOGLEVEL, Console::Yes }, + { "motd", HandleServerSetMotdCommand, rbac::RBAC_PERM_COMMAND_SERVER_SET_MOTD, Console::Yes }, + { "closed", HandleServerSetClosedCommand, rbac::RBAC_PERM_COMMAND_SERVER_SET_CLOSED, Console::Yes }, }; static ChatCommandTable serverCommandTable = { - { "corpses", HandleServerCorpsesCommand, SEC_GAMEMASTER, Console::Yes }, - { "debug", HandleServerDebugCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "exit", HandleServerExitCommand, SEC_CONSOLE, Console::Yes }, + { "corpses", HandleServerCorpsesCommand, rbac::RBAC_PERM_COMMAND_SERVER_CORPSES, Console::Yes }, + { "debug", HandleServerDebugCommand, rbac::RBAC_PERM_COMMAND_SERVER_DEBUG, Console::Yes }, + { "exit", HandleServerExitCommand, rbac::RBAC_PERM_COMMAND_SERVER_EXIT, Console::Yes }, { "idlerestart", serverIdleRestartCommandTable }, { "idleshutdown", serverIdleShutdownCommandTable }, - { "info", HandleServerInfoCommand, SEC_PLAYER, Console::Yes }, - { "motd", HandleServerMotdCommand, SEC_PLAYER, Console::Yes }, + { "info", HandleServerInfoCommand, rbac::RBAC_PERM_COMMAND_SERVER_INFO, Console::Yes }, + { "motd", HandleServerMotdCommand, rbac::RBAC_PERM_COMMAND_SERVER_MOTD, Console::Yes }, { "restart", serverRestartCommandTable }, { "shutdown", serverShutdownCommandTable }, { "set", serverSetCommandTable } diff --git a/src/server/scripts/Commands/cs_spectator.cpp b/src/server/scripts/Commands/cs_spectator.cpp index 86fbf6413..29ff8321c 100644 --- a/src/server/scripts/Commands/cs_spectator.cpp +++ b/src/server/scripts/Commands/cs_spectator.cpp @@ -20,6 +20,7 @@ #include "Chat.h" #include "CommandScript.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -32,12 +33,12 @@ public: { static ChatCommandTable spectatorCommandTable = { - { "version", HandleSpectatorVersionCommand, SEC_PLAYER, Console::No }, - { "reset", HandleSpectatorResetCommand, SEC_PLAYER, Console::No }, - { "spectate", HandleSpectatorSpectateCommand, SEC_PLAYER, Console::No }, - { "watch", HandleSpectatorWatchCommand, SEC_PLAYER, Console::No }, - { "leave", HandleSpectatorLeaveCommand, SEC_PLAYER, Console::No }, - { "", HandleSpectatorCommand, SEC_PLAYER, Console::No } + { "version", HandleSpectatorVersionCommand, rbac::RBAC_PERM_COMMAND_SPECT_VERSION, Console::No }, + { "reset", HandleSpectatorResetCommand, rbac::RBAC_PERM_COMMAND_SPECT_RESET, Console::No }, + { "spectate", HandleSpectatorSpectateCommand, rbac::RBAC_PERM_COMMAND_SPECT_SPECTATE, Console::No }, + { "watch", HandleSpectatorWatchCommand, rbac::RBAC_PERM_COMMAND_SPECT_WATCH, Console::No }, + { "leave", HandleSpectatorLeaveCommand, rbac::RBAC_PERM_COMMAND_SPECT_LEAVE, Console::No }, + { "", HandleSpectatorCommand, rbac::RBAC_PERM_COMMAND_SPECT, Console::No } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index aed43e503..ee8c9d796 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -23,6 +23,7 @@ #include "MapMgr.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -35,22 +36,22 @@ public: { static ChatCommandTable teleNameNpcCommandTable = { - { "id", HandleTeleNameNpcIdCommand, SEC_GAMEMASTER, Console::Yes }, - { "guid", HandleTeleNameNpcSpawnIdCommand, SEC_GAMEMASTER, Console::Yes }, - { "name", HandleTeleNameNpcNameCommand, SEC_GAMEMASTER, Console::Yes }, + { "id", HandleTeleNameNpcIdCommand, rbac::RBAC_PERM_COMMAND_TELE_NAME, Console::Yes }, + { "guid", HandleTeleNameNpcSpawnIdCommand, rbac::RBAC_PERM_COMMAND_TELE_NAME, Console::Yes }, + { "name", HandleTeleNameNpcNameCommand, rbac::RBAC_PERM_COMMAND_TELE_NAME, Console::Yes }, }; static ChatCommandTable teleNameCommandTable = { { "npc", teleNameNpcCommandTable }, - { "", HandleTeleNameCommand, SEC_GAMEMASTER, Console::Yes }, + { "", HandleTeleNameCommand, rbac::RBAC_PERM_COMMAND_TELE_NAME, Console::Yes }, }; static ChatCommandTable teleCommandTable = { - { "add", HandleTeleAddCommand, SEC_ADMINISTRATOR, Console::No }, - { "del", HandleTeleDelCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "add", HandleTeleAddCommand, rbac::RBAC_PERM_COMMAND_TELE_ADD, Console::No }, + { "del", HandleTeleDelCommand, rbac::RBAC_PERM_COMMAND_TELE_DEL, Console::Yes }, { "name", teleNameCommandTable }, - { "group", HandleTeleGroupCommand, SEC_GAMEMASTER, Console::No }, - { "", HandleTeleCommand, SEC_GAMEMASTER, Console::No } + { "group", HandleTeleGroupCommand, rbac::RBAC_PERM_COMMAND_TELE_GROUP, Console::No }, + { "", HandleTeleCommand, rbac::RBAC_PERM_COMMAND_TELE, Console::No } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 0cd174b70..e54aad546 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -20,6 +20,7 @@ #include "CommandScript.h" #include "ObjectMgr.h" #include "Player.h" +#include "RBAC.h" #include "Realm.h" #include "TicketMgr.h" @@ -34,30 +35,30 @@ public: { static ChatCommandTable ticketResponseCommandTable = { - { "append", HandleGMTicketResponseAppendCommand, SEC_GAMEMASTER, Console::Yes }, - { "appendln", HandleGMTicketResponseAppendLnCommand, SEC_GAMEMASTER, Console::Yes }, - { "delete", HandleGMTicketResponseDeleteCommand, SEC_GAMEMASTER, Console::Yes }, - { "show", HandleGMTicketResponseShowCommand, SEC_GAMEMASTER, Console::Yes } + { "append", HandleGMTicketResponseAppendCommand, rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE_APPEND, Console::Yes }, + { "appendln", HandleGMTicketResponseAppendLnCommand, rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE_APPENDLN, Console::Yes }, + { "delete", HandleGMTicketResponseDeleteCommand, rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE, Console::Yes }, + { "show", HandleGMTicketResponseShowCommand, rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE, Console::Yes } }; static ChatCommandTable ticketCommandTable = { - { "assign", HandleGMTicketAssignToCommand, SEC_GAMEMASTER, Console::Yes }, - { "close", HandleGMTicketCloseByIdCommand, SEC_GAMEMASTER, Console::Yes }, - { "closedlist", HandleGMTicketListClosedCommand, SEC_GAMEMASTER, Console::Yes }, - { "comment", HandleGMTicketCommentCommand, SEC_GAMEMASTER, Console::Yes }, - { "complete", HandleGMTicketCompleteCommand, SEC_GAMEMASTER, Console::Yes }, - { "delete", HandleGMTicketDeleteByIdCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "escalate", HandleGMTicketEscalateCommand, SEC_GAMEMASTER, Console::Yes }, - { "escalatedlist", HandleGMTicketListEscalatedCommand, SEC_GAMEMASTER, Console::Yes }, - { "list", HandleGMTicketListCommand, SEC_GAMEMASTER, Console::Yes }, - { "onlinelist", HandleGMTicketListOnlineCommand, SEC_GAMEMASTER, Console::Yes }, - { "reset", HandleGMTicketResetCommand, SEC_CONSOLE, Console::Yes }, + { "assign", HandleGMTicketAssignToCommand, rbac::RBAC_PERM_COMMAND_TICKET_ASSIGN, Console::Yes }, + { "close", HandleGMTicketCloseByIdCommand, rbac::RBAC_PERM_COMMAND_TICKET_CLOSE, Console::Yes }, + { "closedlist", HandleGMTicketListClosedCommand, rbac::RBAC_PERM_COMMAND_TICKET_CLOSEDLIST, Console::Yes }, + { "comment", HandleGMTicketCommentCommand, rbac::RBAC_PERM_COMMAND_TICKET_COMMENT, Console::Yes }, + { "complete", HandleGMTicketCompleteCommand, rbac::RBAC_PERM_COMMAND_TICKET_COMPLETE, Console::Yes }, + { "delete", HandleGMTicketDeleteByIdCommand, rbac::RBAC_PERM_COMMAND_TICKET_DELETE, Console::Yes }, + { "escalate", HandleGMTicketEscalateCommand, rbac::RBAC_PERM_COMMAND_TICKET_ESCALATE, Console::Yes }, + { "escalatedlist", HandleGMTicketListEscalatedCommand, rbac::RBAC_PERM_COMMAND_TICKET_ESCALATEDLIST, Console::Yes }, + { "list", HandleGMTicketListCommand, rbac::RBAC_PERM_COMMAND_TICKET_LIST, Console::Yes }, + { "onlinelist", HandleGMTicketListOnlineCommand, rbac::RBAC_PERM_COMMAND_TICKET_ONLINELIST, Console::Yes }, + { "reset", HandleGMTicketResetCommand, rbac::RBAC_PERM_COMMAND_TICKET_RESET, Console::Yes }, { "response", ticketResponseCommandTable }, - { "togglesystem", HandleToggleGMTicketSystem, SEC_ADMINISTRATOR, Console::Yes }, - { "unassign", HandleGMTicketUnAssignCommand, SEC_GAMEMASTER, Console::Yes }, - { "viewid", HandleGMTicketGetByIdCommand, SEC_GAMEMASTER, Console::Yes }, - { "viewname", HandleGMTicketGetByNameCommand, SEC_GAMEMASTER, Console::Yes } + { "togglesystem", HandleToggleGMTicketSystem, rbac::RBAC_PERM_COMMAND_TICKET_TOGGLESYSTEM, Console::Yes }, + { "unassign", HandleGMTicketUnAssignCommand, rbac::RBAC_PERM_COMMAND_TICKET_UNASSIGN, Console::Yes }, + { "viewid", HandleGMTicketGetByIdCommand, rbac::RBAC_PERM_COMMAND_TICKET_VIEWID, Console::Yes }, + { "viewname", HandleGMTicketGetByNameCommand, rbac::RBAC_PERM_COMMAND_TICKET_VIEWNAME, Console::Yes } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/Commands/cs_titles.cpp b/src/server/scripts/Commands/cs_titles.cpp index 51c254724..38a35f5f7 100644 --- a/src/server/scripts/Commands/cs_titles.cpp +++ b/src/server/scripts/Commands/cs_titles.cpp @@ -19,6 +19,7 @@ #include "CommandScript.h" #include "DBCStores.h" #include "Player.h" +#include "RBAC.h" using namespace Acore::ChatCommands; @@ -31,13 +32,13 @@ public: { static ChatCommandTable titlesSetCommandTable = { - { "mask", HandleTitlesSetMaskCommand, SEC_GAMEMASTER, Console::No }, + { "mask", HandleTitlesSetMaskCommand, rbac::RBAC_PERM_COMMAND_TITLES_SET_MASK, Console::No }, }; static ChatCommandTable titlesCommandTable = { - { "add", HandleTitlesAddCommand, SEC_GAMEMASTER, Console::No }, - { "current", HandleTitlesCurrentCommand, SEC_GAMEMASTER, Console::No }, - { "remove", HandleTitlesRemoveCommand, SEC_GAMEMASTER, Console::No }, + { "add", HandleTitlesAddCommand, rbac::RBAC_PERM_COMMAND_TITLES_ADD, Console::No }, + { "current", HandleTitlesCurrentCommand, rbac::RBAC_PERM_COMMAND_TITLES_CURRENT, Console::No }, + { "remove", HandleTitlesRemoveCommand, rbac::RBAC_PERM_COMMAND_TITLES_REMOVE, Console::No }, { "set", titlesSetCommandTable }, }; static ChatCommandTable commandTable = diff --git a/src/server/scripts/Commands/cs_worldstate.cpp b/src/server/scripts/Commands/cs_worldstate.cpp index e6d9c833d..535aadbaf 100644 --- a/src/server/scripts/Commands/cs_worldstate.cpp +++ b/src/server/scripts/Commands/cs_worldstate.cpp @@ -18,6 +18,7 @@ #include "Chat.h" #include "CommandScript.h" #include "Common.h" +#include "RBAC.h" #include "WorldState.h" using namespace Acore::ChatCommands; @@ -31,20 +32,20 @@ public: { static ChatCommandTable sunsreachCommandTable = { - { "status", HandleSunsReachReclamationStatusCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "phase", HandleSunsReachReclamationPhaseCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "subphase", HandleSunsReachReclamationSubPhaseCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "counter", HandleSunsReachReclamationCounterCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gate", HandleSunwellGateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "gatecounter", HandleSunwellGateCounterCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "status", HandleSunsReachReclamationStatusCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "phase", HandleSunsReachReclamationPhaseCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "subphase", HandleSunsReachReclamationSubPhaseCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "counter", HandleSunsReachReclamationCounterCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "gate", HandleSunwellGateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "gatecounter", HandleSunwellGateCounterCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, }; static ChatCommandTable scourgeInvasionCommandTable = { - { "show", HandleScourgeInvasionCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "state", HandleScourgeInvasionStateCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "battleswon", HandleScourgeInvasionBattlesWonCommand, SEC_ADMINISTRATOR, Console::Yes }, - { "startzone", HandleScourgeInvasionStartZone, SEC_ADMINISTRATOR, Console::Yes }, + { "show", HandleScourgeInvasionCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "state", HandleScourgeInvasionStateCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "battleswon", HandleScourgeInvasionBattlesWonCommand, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, + { "startzone", HandleScourgeInvasionStartZone, rbac::RBAC_PERM_COMMAND_DEBUG, Console::Yes }, }; static ChatCommandTable worldStateCommandTable = diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index b4b80686a..efd07cf48 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -18,6 +18,7 @@ #include "Chat.h" #include "CommandScript.h" #include "Player.h" +#include "RBAC.h" #include "WaypointMgr.h" #if AC_COMPILER == AC_COMPILER_GNU @@ -35,13 +36,13 @@ public: { static ChatCommandTable wpCommandTable = { - { "add", HandleWpAddCommand, SEC_ADMINISTRATOR, Console::No }, - { "event", HandleWpEventCommand, SEC_ADMINISTRATOR, Console::No }, - { "load", HandleWpLoadCommand, SEC_ADMINISTRATOR, Console::No }, - { "modify", HandleWpModifyCommand, SEC_ADMINISTRATOR, Console::No }, - { "unload", HandleWpUnLoadCommand, SEC_ADMINISTRATOR, Console::No }, - { "reload", HandleWpReloadCommand, SEC_ADMINISTRATOR, Console::No }, - { "show", HandleWpShowCommand, SEC_ADMINISTRATOR, Console::No } + { "add", HandleWpAddCommand, rbac::RBAC_PERM_COMMAND_WP_ADD, Console::No }, + { "event", HandleWpEventCommand, rbac::RBAC_PERM_COMMAND_WP_EVENT, Console::No }, + { "load", HandleWpLoadCommand, rbac::RBAC_PERM_COMMAND_WP_LOAD, Console::No }, + { "modify", HandleWpModifyCommand, rbac::RBAC_PERM_COMMAND_WP_MODIFY, Console::No }, + { "unload", HandleWpUnLoadCommand, rbac::RBAC_PERM_COMMAND_WP_UNLOAD, Console::No }, + { "reload", HandleWpReloadCommand, rbac::RBAC_PERM_COMMAND_WP_RELOAD, Console::No }, + { "show", HandleWpShowCommand, rbac::RBAC_PERM_COMMAND_WP_SHOW, Console::No } }; static ChatCommandTable commandTable = { diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp index a77af22d0..62932fe2e 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp @@ -181,21 +181,6 @@ struct instance_blackwing_lair : public InstanceScript return 0; } - bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override - { - switch (bossId) - { - case DATA_BROODLORD_LASHLAYER: - if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE) - return false; - break; - default: - break; - } - - return true; - } - bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) @@ -304,6 +289,24 @@ struct instance_blackwing_lair : public InstanceScript return ObjectGuid::Empty; } + bool CheckRequiredBosses(uint32 bossId, Player const* player) const override + { + if (_SkipCheckRequiredBosses(player)) + return true; + + switch (bossId) + { + case DATA_BROODLORD_LASHLAYER: + if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE) + return false; + break; + default: + break; + } + + return true; + } + void OnUnitDeath(Unit* unit) override { switch (unit->GetEntry()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 3f0b45490..6b2077677 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -1421,10 +1421,8 @@ public: bool CheckRequiredBosses(uint32 bossId, Player const* player) const override { - if (player && player->GetSession() && player->GetSession()->GetSecurity() >= SEC_MODERATOR) - { + if (_SkipCheckRequiredBosses(player)) return true; - } switch (bossId) { diff --git a/src/test/mocks/WorldMock.h b/src/test/mocks/WorldMock.h index b37044119..e96e38b47 100644 --- a/src/test/mocks/WorldMock.h +++ b/src/test/mocks/WorldMock.h @@ -85,6 +85,7 @@ public: MOCK_METHOD(std::string const&, GetRealmName, (), (const)); MOCK_METHOD(void, SetRealmName, (std::string name), ()); MOCK_METHOD(void, RemoveOldCorpses, ()); + MOCK_METHOD(void, ReloadRBAC, ()); }; #pragma GCC diagnostic pop diff --git a/src/test/server/game/Accounts/RBACTest.cpp b/src/test/server/game/Accounts/RBACTest.cpp new file mode 100644 index 000000000..d48bd274e --- /dev/null +++ b/src/test/server/game/Accounts/RBACTest.cpp @@ -0,0 +1,2059 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +/** + * @file RBACTest.cpp + * @brief Unit tests for the Role-Based Access Control (RBAC) system. + * + * Tests verify: + * 1. RBACPermission class construction and accessors + * 2. RBACData grant/deny/revoke operations + * 3. Permission state transitions + * 4. HasPermission checks with granted/denied lists + */ + +#include "AccountMgr.h" +#include "RBAC.h" +#include "gtest/gtest.h" +#include + +namespace +{ + +// Test permission IDs +constexpr uint32 TEST_PERM_1 = 1; +constexpr uint32 TEST_PERM_2 = 2; +constexpr uint32 TEST_PERM_3 = 3; +constexpr uint32 TEST_PERM_ROLE = 100; +constexpr uint32 TEST_PERM_INVALID = 99999; + +// Test account/realm data +constexpr uint32 TEST_ACCOUNT_ID = 1; +constexpr uint32 TEST_REALM_ID = 1; +constexpr uint8 TEST_SEC_LEVEL = 3; +const std::string TEST_ACCOUNT_NAME = "TestAccount"; + +/** + * @class RBACPermissionTest + * @brief Tests for RBACPermission class functionality. + */ +class RBACPermissionTest : public ::testing::Test +{ +protected: + void SetUp() override + { + permission = std::make_unique(TEST_PERM_1, "Test Permission"); + } + + std::unique_ptr permission; +}; + +// cppcheck-suppress syntaxError +TEST_F(RBACPermissionTest, Constructor_SetsIdAndName) +{ + EXPECT_EQ(permission->GetId(), TEST_PERM_1); + EXPECT_EQ(permission->GetName(), "Test Permission"); +} + +TEST_F(RBACPermissionTest, LinkedPermissions_InitiallyEmpty) +{ + EXPECT_TRUE(permission->GetLinkedPermissions().empty()); +} + +TEST_F(RBACPermissionTest, AddLinkedPermission_AddsToSet) +{ + permission->AddLinkedPermission(TEST_PERM_2); + permission->AddLinkedPermission(TEST_PERM_3); + + auto const& linked = permission->GetLinkedPermissions(); + EXPECT_EQ(linked.size(), 2u); + EXPECT_TRUE(linked.count(TEST_PERM_2) > 0); + EXPECT_TRUE(linked.count(TEST_PERM_3) > 0); +} + +TEST_F(RBACPermissionTest, AddLinkedPermission_NoDuplicates) +{ + permission->AddLinkedPermission(TEST_PERM_2); + permission->AddLinkedPermission(TEST_PERM_2); + permission->AddLinkedPermission(TEST_PERM_2); + + EXPECT_EQ(permission->GetLinkedPermissions().size(), 1u); +} + +/** + * @class RBACDataTest + * @brief Tests for RBACData class functionality with full server setup. + * + * Uses AccountMgr's test permission registration to allow proper + * GrantPermission/DenyPermission testing. + */ +class RBACDataTest : public ::testing::Test +{ +protected: + void SetUp() override + { + // Register test permissions with AccountMgr + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Test Permission 1"); + sAccountMgr->AddPermissionForTest(TEST_PERM_2, "Test Permission 2"); + sAccountMgr->AddPermissionForTest(TEST_PERM_3, "Test Permission 3"); + sAccountMgr->AddPermissionForTest(TEST_PERM_ROLE, "Test Role Permission"); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + // Clean up test permissions + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACDataTest, Constructor_SetsAccountData) +{ + EXPECT_EQ(rbacData->GetId(), TEST_ACCOUNT_ID); + EXPECT_EQ(rbacData->GetName(), TEST_ACCOUNT_NAME); + EXPECT_EQ(rbacData->GetSecurityLevel(), TEST_SEC_LEVEL); +} + +TEST_F(RBACDataTest, InitialState_EmptyPermissions) +{ + EXPECT_TRUE(rbacData->GetGrantedPermissions().empty()); + EXPECT_TRUE(rbacData->GetDeniedPermissions().empty()); +} + +// Grant Permission Tests + +TEST_F(RBACDataTest, GrantPermission_Success) +{ + rbac::RBACCommandResult result = rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + EXPECT_TRUE(rbacData->GetGrantedPermissions().count(TEST_PERM_1) > 0); +} + +TEST_F(RBACDataTest, GrantPermission_AlreadyGranted_ReturnsError) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_CANT_ADD_ALREADY_ADDED); +} + +TEST_F(RBACDataTest, GrantPermission_WhenDenied_ReturnsError) +{ + rbacData->DenyPermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_IN_DENIED_LIST); +} + +TEST_F(RBACDataTest, GrantPermission_InvalidId_ReturnsError) +{ + rbac::RBACCommandResult result = rbacData->GrantPermission(TEST_PERM_INVALID); + EXPECT_EQ(result, rbac::RBAC_ID_DOES_NOT_EXISTS); +} + +// Deny Permission Tests + +TEST_F(RBACDataTest, DenyPermission_Success) +{ + rbac::RBACCommandResult result = rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + EXPECT_TRUE(rbacData->GetDeniedPermissions().count(TEST_PERM_1) > 0); +} + +TEST_F(RBACDataTest, DenyPermission_AlreadyDenied_ReturnsError) +{ + rbacData->DenyPermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_CANT_ADD_ALREADY_ADDED); +} + +TEST_F(RBACDataTest, DenyPermission_WhenGranted_ReturnsError) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_IN_GRANTED_LIST); +} + +TEST_F(RBACDataTest, DenyPermission_InvalidId_ReturnsError) +{ + rbac::RBACCommandResult result = rbacData->DenyPermission(TEST_PERM_INVALID); + EXPECT_EQ(result, rbac::RBAC_ID_DOES_NOT_EXISTS); +} + +// Revoke Permission Tests + +TEST_F(RBACDataTest, RevokePermission_FromGranted_Success) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->RevokePermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + EXPECT_TRUE(rbacData->GetGrantedPermissions().empty()); +} + +TEST_F(RBACDataTest, RevokePermission_FromDenied_Success) +{ + rbacData->DenyPermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->RevokePermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + EXPECT_TRUE(rbacData->GetDeniedPermissions().empty()); +} + +TEST_F(RBACDataTest, RevokePermission_NotInList_ReturnsError) +{ + rbac::RBACCommandResult result = rbacData->RevokePermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_CANT_REVOKE_NOT_IN_LIST); +} + +// HasPermission Tests + +TEST_F(RBACDataTest, HasPermission_WhenGranted_ReturnsTrue) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); +} + +TEST_F(RBACDataTest, HasPermission_WhenDenied_ReturnsFalse) +{ + rbacData->DenyPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); +} + +TEST_F(RBACDataTest, HasPermission_WhenNotSet_ReturnsFalse) +{ + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); +} + +// Multiple Permissions Tests + +TEST_F(RBACDataTest, MultiplePermissions_IndependentTracking) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->DenyPermission(TEST_PERM_2); + rbacData->GrantPermission(TEST_PERM_3); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_2)); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_3)); + + EXPECT_EQ(rbacData->GetGrantedPermissions().size(), 2u); + EXPECT_EQ(rbacData->GetDeniedPermissions().size(), 1u); +} + +TEST_F(RBACDataTest, RevokeAndRegrant_WorksCorrectly) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); + + rbacData->RevokePermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); + + // Now can grant again + rbac::RBACCommandResult result = rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); +} + +TEST_F(RBACDataTest, RevokeAndDeny_WorksCorrectly) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); + + rbacData->RevokePermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); + + // Now can deny + rbac::RBACCommandResult result = rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); + EXPECT_TRUE(rbacData->GetDeniedPermissions().count(TEST_PERM_1) > 0); +} + +/** + * @class RBACCommandResultTest + * @brief Tests to verify all RBACCommandResult values are handled. + */ +class RBACCommandResultTest : public ::testing::Test +{ +}; + +TEST_F(RBACCommandResultTest, AllResultValuesAreDefined) +{ + // Verify enum values exist and are distinct + EXPECT_NE(rbac::RBAC_OK, rbac::RBAC_CANT_ADD_ALREADY_ADDED); + EXPECT_NE(rbac::RBAC_OK, rbac::RBAC_CANT_REVOKE_NOT_IN_LIST); + EXPECT_NE(rbac::RBAC_OK, rbac::RBAC_IN_GRANTED_LIST); + EXPECT_NE(rbac::RBAC_OK, rbac::RBAC_IN_DENIED_LIST); + EXPECT_NE(rbac::RBAC_OK, rbac::RBAC_ID_DOES_NOT_EXISTS); +} + +/** + * @class RBACLinkedPermissionsTest + * @brief Tests for permission inheritance through linked permissions. + */ +class RBACLinkedPermissionsTest : public ::testing::Test +{ +protected: + void SetUp() override + { + // Register test permissions + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Base Permission 1"); + sAccountMgr->AddPermissionForTest(TEST_PERM_2, "Base Permission 2"); + sAccountMgr->AddPermissionForTest(TEST_PERM_3, "Base Permission 3"); + sAccountMgr->AddPermissionForTest(TEST_PERM_ROLE, "Role Permission"); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACLinkedPermissionsTest, GrantedPermission_IsInGrantedList) +{ + rbacData->GrantPermission(TEST_PERM_1); + + auto const& granted = rbacData->GetGrantedPermissions(); + EXPECT_TRUE(granted.count(TEST_PERM_1) > 0); +} + +TEST_F(RBACLinkedPermissionsTest, DeniedPermission_IsInDeniedList) +{ + rbacData->DenyPermission(TEST_PERM_1); + + auto const& denied = rbacData->GetDeniedPermissions(); + EXPECT_TRUE(denied.count(TEST_PERM_1) > 0); +} + +TEST_F(RBACLinkedPermissionsTest, DeniedPermission_OverridesGranted) +{ + // Grant permission, then revoke and deny + rbacData->GrantPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); + + rbacData->RevokePermission(TEST_PERM_1); + rbacData->DenyPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); +} + +/** + * @class RBACSecurityLevelTest + * @brief Tests for security level accessor. + */ +class RBACSecurityLevelTest : public ::testing::Test +{ +protected: + void SetUp() override + { + // Register a test permission for the test + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Test Permission"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACSecurityLevelTest, Constructor_PreservesSecurityLevel) +{ + rbac::RBACData rbacLevel0(1, "Player", 1, 0); + EXPECT_EQ(rbacLevel0.GetSecurityLevel(), 0); + + rbac::RBACData rbacLevel1(2, "Moderator", 1, 1); + EXPECT_EQ(rbacLevel1.GetSecurityLevel(), 1); + + rbac::RBACData rbacLevel2(3, "GameMaster", 1, 2); + EXPECT_EQ(rbacLevel2.GetSecurityLevel(), 2); + + rbac::RBACData rbacLevel3(4, "Administrator", 1, 3); + EXPECT_EQ(rbacLevel3.GetSecurityLevel(), 3); +} + +TEST_F(RBACSecurityLevelTest, SetSecurityLevelForTest_UpdatesLevel) +{ + rbac::RBACData rbac(1, "TestAccount", 1, 0); + EXPECT_EQ(rbac.GetSecurityLevel(), 0); + + // Use test-friendly setter that doesn't call LoadFromDB + rbac.SetSecurityLevelForTest(3); + EXPECT_EQ(rbac.GetSecurityLevel(), 3); +} + +/** + * @class RBACPermissionExpansionTest + * @brief Tests for permission expansion through linked permissions. + * + * Tests verify that when a role/permission with linked permissions is granted, + * all linked permissions become effective via ExpandPermissions(). + */ +class RBACPermissionExpansionTest : public ::testing::Test +{ +protected: + // Permission structure for testing: + // ROLE_GM (100) -> links to PERM_KICK (10), PERM_BAN (11) + // ROLE_ADMIN (101) -> links to ROLE_GM (100), PERM_SHUTDOWN (12) + // This creates a hierarchy: ADMIN -> GM -> individual permissions + + static constexpr uint32 PERM_KICK = 10; + static constexpr uint32 PERM_BAN = 11; + static constexpr uint32 PERM_SHUTDOWN = 12; + static constexpr uint32 PERM_TELEPORT = 13; + static constexpr uint32 ROLE_GM = 100; + static constexpr uint32 ROLE_ADMIN = 101; + + void SetUp() override + { + // Register individual permissions + sAccountMgr->AddPermissionForTest(PERM_KICK, "Kick Permission"); + sAccountMgr->AddPermissionForTest(PERM_BAN, "Ban Permission"); + sAccountMgr->AddPermissionForTest(PERM_SHUTDOWN, "Shutdown Permission"); + sAccountMgr->AddPermissionForTest(PERM_TELEPORT, "Teleport Permission"); + + // Register role permissions + sAccountMgr->AddPermissionForTest(ROLE_GM, "GameMaster Role"); + sAccountMgr->AddPermissionForTest(ROLE_ADMIN, "Administrator Role"); + + // Set up permission hierarchy: + // GM role includes kick and ban + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_KICK); + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_BAN); + + // Admin role includes GM role and shutdown + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, ROLE_GM); + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, PERM_SHUTDOWN); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACPermissionExpansionTest, GrantRole_ExpandsLinkedPermissions) +{ + // Grant GM role + rbacData->GrantPermission(ROLE_GM); + rbacData->RecalculatePermissions(); + + // Should have access to GM role and linked permissions (kick, ban) + EXPECT_TRUE(rbacData->HasPermission(ROLE_GM)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_BAN)); + + // Should NOT have access to unlinked permissions + EXPECT_FALSE(rbacData->HasPermission(PERM_SHUTDOWN)); + EXPECT_FALSE(rbacData->HasPermission(PERM_TELEPORT)); +} + +TEST_F(RBACPermissionExpansionTest, GrantRole_RecursiveExpansion) +{ + // Grant Admin role (which links to GM role, which links to kick/ban) + rbacData->GrantPermission(ROLE_ADMIN); + rbacData->RecalculatePermissions(); + + // Should have access to Admin role + EXPECT_TRUE(rbacData->HasPermission(ROLE_ADMIN)); + + // Should have access to directly linked permissions (GM role, shutdown) + EXPECT_TRUE(rbacData->HasPermission(ROLE_GM)); + EXPECT_TRUE(rbacData->HasPermission(PERM_SHUTDOWN)); + + // Should have access to recursively linked permissions (from GM role) + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_BAN)); + + // Should NOT have access to unlinked permissions + EXPECT_FALSE(rbacData->HasPermission(PERM_TELEPORT)); +} + +TEST_F(RBACPermissionExpansionTest, DenyRole_PreventsLinkedPermissions) +{ + // Grant teleport individually + rbacData->GrantPermission(PERM_TELEPORT); + + // Grant admin role (gives kick, ban, shutdown via expansion) + rbacData->GrantPermission(ROLE_ADMIN); + rbacData->RecalculatePermissions(); + + // Verify all permissions are granted + EXPECT_TRUE(rbacData->HasPermission(ROLE_ADMIN)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_TELEPORT)); + + // Now revoke admin and deny the GM role + rbacData->RevokePermission(ROLE_ADMIN); + rbacData->DenyPermission(ROLE_GM); + rbacData->RecalculatePermissions(); + + // GM role and its linked permissions should be denied + EXPECT_FALSE(rbacData->HasPermission(ROLE_GM)); + EXPECT_FALSE(rbacData->HasPermission(PERM_KICK)); + EXPECT_FALSE(rbacData->HasPermission(PERM_BAN)); + + // Teleport was granted directly, not through GM, so should still work + EXPECT_TRUE(rbacData->HasPermission(PERM_TELEPORT)); +} + +TEST_F(RBACPermissionExpansionTest, DenyRole_OverridesIndividualGrant) +{ + // Grant kick permission individually + rbacData->GrantPermission(PERM_KICK); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + + // Deny the GM role (which links to kick) + rbacData->DenyPermission(ROLE_GM); + rbacData->RecalculatePermissions(); + + // Denying a role expands to deny all linked permissions + // Even though kick was granted individually, denying GM role + // expands to deny kick as well (RBAC deny expansion) + EXPECT_FALSE(rbacData->HasPermission(PERM_KICK)); + EXPECT_FALSE(rbacData->HasPermission(ROLE_GM)); + EXPECT_FALSE(rbacData->HasPermission(PERM_BAN)); +} + +/** + * @class RBACDefaultPermissionsTest + * @brief Tests for default permissions based on security level. + * + * Tests verify that default permissions from rbac_default_permissions + * are properly applied based on account security level. + */ +class RBACDefaultPermissionsTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_PLAYER_1 = 20; + static constexpr uint32 PERM_PLAYER_2 = 21; + static constexpr uint32 PERM_MOD_1 = 30; + static constexpr uint32 PERM_GM_1 = 40; + static constexpr uint32 PERM_ADMIN_1 = 50; + + static constexpr uint8 SEC_PLAYER = 0; + static constexpr uint8 SEC_MODERATOR = 1; + static constexpr uint8 SEC_GAMEMASTER = 2; + static constexpr uint8 SEC_ADMINISTRATOR = 3; + + void SetUp() override + { + // Register test permissions + sAccountMgr->AddPermissionForTest(PERM_PLAYER_1, "Player Permission 1"); + sAccountMgr->AddPermissionForTest(PERM_PLAYER_2, "Player Permission 2"); + sAccountMgr->AddPermissionForTest(PERM_MOD_1, "Moderator Permission 1"); + sAccountMgr->AddPermissionForTest(PERM_GM_1, "GameMaster Permission 1"); + sAccountMgr->AddPermissionForTest(PERM_ADMIN_1, "Administrator Permission 1"); + + // Set up default permissions for security levels + sAccountMgr->AddDefaultPermissionForTest(SEC_PLAYER, PERM_PLAYER_1); + sAccountMgr->AddDefaultPermissionForTest(SEC_PLAYER, PERM_PLAYER_2); + + sAccountMgr->AddDefaultPermissionForTest(SEC_MODERATOR, PERM_MOD_1); + + sAccountMgr->AddDefaultPermissionForTest(SEC_GAMEMASTER, PERM_GM_1); + + sAccountMgr->AddDefaultPermissionForTest(SEC_ADMINISTRATOR, PERM_ADMIN_1); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACDefaultPermissionsTest, GetDefaultPermissions_ReturnsCorrectSet) +{ + rbac::RBACPermissionContainer const& playerPerms = sAccountMgr->GetRBACDefaultPermissions(SEC_PLAYER); + EXPECT_EQ(playerPerms.size(), 2u); + EXPECT_TRUE(playerPerms.count(PERM_PLAYER_1) > 0); + EXPECT_TRUE(playerPerms.count(PERM_PLAYER_2) > 0); + + rbac::RBACPermissionContainer const& modPerms = sAccountMgr->GetRBACDefaultPermissions(SEC_MODERATOR); + EXPECT_EQ(modPerms.size(), 1u); + EXPECT_TRUE(modPerms.count(PERM_MOD_1) > 0); + + rbac::RBACPermissionContainer const& gmPerms = sAccountMgr->GetRBACDefaultPermissions(SEC_GAMEMASTER); + EXPECT_EQ(gmPerms.size(), 1u); + EXPECT_TRUE(gmPerms.count(PERM_GM_1) > 0); + + rbac::RBACPermissionContainer const& adminPerms = sAccountMgr->GetRBACDefaultPermissions(SEC_ADMINISTRATOR); + EXPECT_EQ(adminPerms.size(), 1u); + EXPECT_TRUE(adminPerms.count(PERM_ADMIN_1) > 0); +} + +TEST_F(RBACDefaultPermissionsTest, GetDefaultPermissions_EmptySecLevel_ReturnsEmpty) +{ + // Security level 255 has no default permissions set + rbac::RBACPermissionContainer const& emptyPerms = sAccountMgr->GetRBACDefaultPermissions(255); + EXPECT_TRUE(emptyPerms.empty()); +} + +TEST_F(RBACDefaultPermissionsTest, SecurityLevel_DeterminesDefaultPermissions) +{ + // Create RBACData for a player account (sec level 0) + rbac::RBACData playerData(1, "PlayerAccount", TEST_REALM_ID, SEC_PLAYER); + + // Manually grant the default permissions (simulating LoadFromDBCallback) + rbac::RBACPermissionContainer const& playerDefaults = sAccountMgr->GetRBACDefaultPermissions(SEC_PLAYER); + for (uint32 perm : playerDefaults) + playerData.GrantPermission(perm); + + playerData.RecalculatePermissions(); + + // Player should have player permissions + EXPECT_TRUE(playerData.HasPermission(PERM_PLAYER_1)); + EXPECT_TRUE(playerData.HasPermission(PERM_PLAYER_2)); + + // Player should NOT have higher level permissions + EXPECT_FALSE(playerData.HasPermission(PERM_MOD_1)); + EXPECT_FALSE(playerData.HasPermission(PERM_GM_1)); + EXPECT_FALSE(playerData.HasPermission(PERM_ADMIN_1)); +} + +TEST_F(RBACDefaultPermissionsTest, HigherSecLevel_GetsOnlyOwnDefaults) +{ + // Create RBACData for an admin account (sec level 3) + rbac::RBACData adminData(4, "AdminAccount", TEST_REALM_ID, SEC_ADMINISTRATOR); + + // Manually grant the default permissions for admin level + rbac::RBACPermissionContainer const& adminDefaults = sAccountMgr->GetRBACDefaultPermissions(SEC_ADMINISTRATOR); + for (uint32 perm : adminDefaults) + adminData.GrantPermission(perm); + + adminData.RecalculatePermissions(); + + // Admin gets their own default permissions + EXPECT_TRUE(adminData.HasPermission(PERM_ADMIN_1)); + + // Note: In a real setup, admin would typically have a role that links to + // lower permissions. Here we're just testing that default permissions + // are applied per security level, not inherited. + // Without explicit roles linking them, admin doesn't automatically get + // player/mod/gm permissions. + EXPECT_FALSE(adminData.HasPermission(PERM_PLAYER_1)); + EXPECT_FALSE(adminData.HasPermission(PERM_MOD_1)); + EXPECT_FALSE(adminData.HasPermission(PERM_GM_1)); +} + +/** + * @class RBACDeniedExpansionTest + * @brief Tests for denied permission expansion. + * + * Tests verify that denied permissions are properly expanded + * and remove access to linked permissions. + */ +class RBACDeniedExpansionTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_KICK = 10; + static constexpr uint32 PERM_BAN = 11; + static constexpr uint32 ROLE_GM = 100; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_KICK, "Kick Permission"); + sAccountMgr->AddPermissionForTest(PERM_BAN, "Ban Permission"); + sAccountMgr->AddPermissionForTest(ROLE_GM, "GameMaster Role"); + + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_KICK); + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_BAN); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACDeniedExpansionTest, DenyRole_ExpandsDeniedLinkedPermissions) +{ + // First grant individual permissions that would be linked from GM + rbacData->GrantPermission(PERM_KICK); + rbacData->GrantPermission(PERM_BAN); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_BAN)); + + // Now deny the GM role + rbacData->DenyPermission(ROLE_GM); + rbacData->RecalculatePermissions(); + + // The GM role and its linked permissions should be denied + // Even though kick/ban were granted individually, denying the role + // that links them should expand to deny those permissions + EXPECT_FALSE(rbacData->HasPermission(ROLE_GM)); + EXPECT_FALSE(rbacData->HasPermission(PERM_KICK)); + EXPECT_FALSE(rbacData->HasPermission(PERM_BAN)); +} + +TEST_F(RBACDeniedExpansionTest, GrantAndDenySameRole_DenyWins) +{ + // Grant the GM role + rbacData->GrantPermission(ROLE_GM); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(ROLE_GM)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + + // Revoke and then deny + rbacData->RevokePermission(ROLE_GM); + rbacData->DenyPermission(ROLE_GM); + rbacData->RecalculatePermissions(); + + // Deny should win - no access + EXPECT_FALSE(rbacData->HasPermission(ROLE_GM)); + EXPECT_FALSE(rbacData->HasPermission(PERM_KICK)); + EXPECT_FALSE(rbacData->HasPermission(PERM_BAN)); +} + +// --------------------------------------------------------------------------- +// Suite 1: RBACPermissionRemoveLinkedTest +// --------------------------------------------------------------------------- +class RBACPermissionRemoveLinkedTest : public ::testing::Test +{ +protected: + void SetUp() override + { + permission = std::make_unique(TEST_PERM_1, "Test Permission"); + permission->AddLinkedPermission(TEST_PERM_2); + permission->AddLinkedPermission(TEST_PERM_3); + } + + std::unique_ptr permission; +}; + +TEST_F(RBACPermissionRemoveLinkedTest, RemoveLinkedPermission_RemovesFromSet) +{ + EXPECT_EQ(permission->GetLinkedPermissions().size(), 2u); + permission->RemoveLinkedPermission(TEST_PERM_2); + EXPECT_EQ(permission->GetLinkedPermissions().size(), 1u); + EXPECT_EQ(permission->GetLinkedPermissions().count(TEST_PERM_2), 0u); + EXPECT_EQ(permission->GetLinkedPermissions().count(TEST_PERM_3), 1u); +} + +TEST_F(RBACPermissionRemoveLinkedTest, RemoveNonExistent_IsNoOp) +{ + permission->RemoveLinkedPermission(TEST_PERM_INVALID); + EXPECT_EQ(permission->GetLinkedPermissions().size(), 2u); +} + +TEST_F(RBACPermissionRemoveLinkedTest, RemoveAll_LeavesEmpty) +{ + permission->RemoveLinkedPermission(TEST_PERM_2); + permission->RemoveLinkedPermission(TEST_PERM_3); + EXPECT_TRUE(permission->GetLinkedPermissions().empty()); +} + +// --------------------------------------------------------------------------- +// Suite 2: RBACGetPermissionsTest (computed global perms) +// --------------------------------------------------------------------------- +class RBACGetPermissionsTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_A = 10; + static constexpr uint32 PERM_B = 11; + static constexpr uint32 PERM_C = 12; + static constexpr uint32 ROLE_R = 100; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_A, "Permission A"); + sAccountMgr->AddPermissionForTest(PERM_B, "Permission B"); + sAccountMgr->AddPermissionForTest(PERM_C, "Permission C"); + sAccountMgr->AddPermissionForTest(ROLE_R, "Role R"); + + sAccountMgr->AddLinkedPermissionForTest(ROLE_R, PERM_A); + sAccountMgr->AddLinkedPermissionForTest(ROLE_R, PERM_B); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACGetPermissionsTest, Empty_WhenNothingGranted) +{ + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->GetPermissions().empty()); +} + +TEST_F(RBACGetPermissionsTest, MatchesHasPermission) +{ + rbacData->GrantPermission(PERM_A); + rbacData->GrantPermission(PERM_C); + rbacData->RecalculatePermissions(); + + auto const& perms = rbacData->GetPermissions(); + for (uint32 p : perms) + EXPECT_TRUE(rbacData->HasPermission(p)); + EXPECT_FALSE(rbacData->HasPermission(PERM_B)); +} + +TEST_F(RBACGetPermissionsTest, ExcludesDeniedPermissions) +{ + rbacData->GrantPermission(PERM_A); + rbacData->GrantPermission(PERM_C); + rbacData->DenyPermission(PERM_B); + rbacData->RecalculatePermissions(); + + auto const& perms = rbacData->GetPermissions(); + EXPECT_TRUE(perms.count(PERM_A) > 0); + EXPECT_TRUE(perms.count(PERM_C) > 0); + EXPECT_EQ(perms.count(PERM_B), 0u); +} + +TEST_F(RBACGetPermissionsTest, IncludesExpandedLinkedPermissions) +{ + rbacData->GrantPermission(ROLE_R); + rbacData->RecalculatePermissions(); + + auto const& perms = rbacData->GetPermissions(); + EXPECT_TRUE(perms.count(ROLE_R) > 0); + EXPECT_TRUE(perms.count(PERM_A) > 0); + EXPECT_TRUE(perms.count(PERM_B) > 0); + EXPECT_EQ(perms.count(PERM_C), 0u); +} + +TEST_F(RBACGetPermissionsTest, ReflectsStateAfterRecalculate) +{ + rbacData->GrantPermission(PERM_A); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->GetPermissions().count(PERM_A) > 0); + + rbacData->RevokePermission(PERM_A); + rbacData->RecalculatePermissions(); + EXPECT_EQ(rbacData->GetPermissions().count(PERM_A), 0u); +} + +// --------------------------------------------------------------------------- +// Suite 3: RBACRevokeEdgeCasesTest +// --------------------------------------------------------------------------- +class RBACRevokeEdgeCasesTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission 1"); + sAccountMgr->AddPermissionForTest(TEST_PERM_2, "Permission 2"); + sAccountMgr->AddPermissionForTest(TEST_PERM_3, "Permission 3"); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACRevokeEdgeCasesTest, RevokeUnregistered_ReturnsCantRevoke) +{ + rbac::RBACCommandResult result = rbacData->RevokePermission(TEST_PERM_INVALID); + EXPECT_EQ(result, rbac::RBAC_CANT_REVOKE_NOT_IN_LIST); +} + +TEST_F(RBACRevokeEdgeCasesTest, RevokeFromEmpty_ReturnsError) +{ + rbac::RBACCommandResult result = rbacData->RevokePermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_CANT_REVOKE_NOT_IN_LIST); +} + +TEST_F(RBACRevokeEdgeCasesTest, RevokeGranted_ThenDeny) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); + + rbacData->RevokePermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); + EXPECT_TRUE(rbacData->GetDeniedPermissions().count(TEST_PERM_1) > 0); +} + +TEST_F(RBACRevokeEdgeCasesTest, RevokeDenied_ThenGrant) +{ + rbacData->DenyPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); + + rbacData->RevokePermission(TEST_PERM_1); + rbac::RBACCommandResult result = rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(result, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); +} + +TEST_F(RBACRevokeEdgeCasesTest, RevokeDoesNotAffectOtherPermissions) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->GrantPermission(TEST_PERM_2); + rbacData->DenyPermission(TEST_PERM_3); + + rbacData->RevokePermission(TEST_PERM_1); + + EXPECT_TRUE(rbacData->GetGrantedPermissions().count(TEST_PERM_2) > 0); + EXPECT_TRUE(rbacData->GetDeniedPermissions().count(TEST_PERM_3) > 0); + EXPECT_EQ(rbacData->GetGrantedPermissions().count(TEST_PERM_1), 0u); +} + +// --------------------------------------------------------------------------- +// Suite 4: RBACComplexHierarchyTest +// --------------------------------------------------------------------------- +class RBACComplexHierarchyTest : public ::testing::Test +{ +protected: + // 3-level: Admin(100)->GM(101)->Mod(102)->individual perms + static constexpr uint32 PERM_A = 10; + static constexpr uint32 PERM_B = 11; + static constexpr uint32 PERM_C = 12; + static constexpr uint32 PERM_D = 13; + static constexpr uint32 PERM_E = 14; + static constexpr uint32 PERM_F = 15; + static constexpr uint32 PERM_G = 16; + static constexpr uint32 PERM_H = 17; + static constexpr uint32 PERM_I = 18; + static constexpr uint32 PERM_J = 19; + static constexpr uint32 PERM_K = 20; + static constexpr uint32 PERM_L = 21; + static constexpr uint32 ROLE_MOD = 102; + static constexpr uint32 ROLE_GM = 101; + static constexpr uint32 ROLE_ADMIN = 100; + // Diamond: ROLE_X(103) and ROLE_Y(104) both link to PERM_SHARED(22) + static constexpr uint32 PERM_SHARED = 22; + static constexpr uint32 PERM_X_ONLY = 23; + static constexpr uint32 PERM_Y_ONLY = 24; + static constexpr uint32 ROLE_X = 103; + static constexpr uint32 ROLE_Y = 104; + // Wide role + static constexpr uint32 ROLE_WIDE = 105; + + void SetUp() override + { + // Register individual perms + sAccountMgr->AddPermissionForTest(PERM_A, "A"); + sAccountMgr->AddPermissionForTest(PERM_B, "B"); + sAccountMgr->AddPermissionForTest(PERM_C, "C"); + sAccountMgr->AddPermissionForTest(PERM_D, "D"); + sAccountMgr->AddPermissionForTest(PERM_E, "E"); + sAccountMgr->AddPermissionForTest(PERM_F, "F"); + sAccountMgr->AddPermissionForTest(PERM_G, "G"); + sAccountMgr->AddPermissionForTest(PERM_H, "H"); + sAccountMgr->AddPermissionForTest(PERM_I, "I"); + sAccountMgr->AddPermissionForTest(PERM_J, "J"); + sAccountMgr->AddPermissionForTest(PERM_K, "K"); + sAccountMgr->AddPermissionForTest(PERM_L, "L"); + sAccountMgr->AddPermissionForTest(PERM_SHARED, "Shared"); + sAccountMgr->AddPermissionForTest(PERM_X_ONLY, "X Only"); + sAccountMgr->AddPermissionForTest(PERM_Y_ONLY, "Y Only"); + + // Register roles + sAccountMgr->AddPermissionForTest(ROLE_MOD, "Mod"); + sAccountMgr->AddPermissionForTest(ROLE_GM, "GM"); + sAccountMgr->AddPermissionForTest(ROLE_ADMIN, "Admin"); + sAccountMgr->AddPermissionForTest(ROLE_X, "X"); + sAccountMgr->AddPermissionForTest(ROLE_Y, "Y"); + sAccountMgr->AddPermissionForTest(ROLE_WIDE, "Wide"); + + // 3-level hierarchy + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_A); + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_B); + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, ROLE_MOD); + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_C); + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, ROLE_GM); + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, PERM_D); + + // Diamond inheritance + sAccountMgr->AddLinkedPermissionForTest(ROLE_X, PERM_SHARED); + sAccountMgr->AddLinkedPermissionForTest(ROLE_X, PERM_X_ONLY); + sAccountMgr->AddLinkedPermissionForTest(ROLE_Y, PERM_SHARED); + sAccountMgr->AddLinkedPermissionForTest(ROLE_Y, PERM_Y_ONLY); + + // Wide role (10+ linked perms) + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_A); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_B); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_C); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_D); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_E); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_F); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_G); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_H); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_I); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_J); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_K); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WIDE, PERM_L); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACComplexHierarchyTest, ThreeLevelDeep) +{ + rbacData->GrantPermission(ROLE_ADMIN); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(ROLE_ADMIN)); + EXPECT_TRUE(rbacData->HasPermission(ROLE_GM)); + EXPECT_TRUE(rbacData->HasPermission(ROLE_MOD)); + EXPECT_TRUE(rbacData->HasPermission(PERM_A)); + EXPECT_TRUE(rbacData->HasPermission(PERM_B)); + EXPECT_TRUE(rbacData->HasPermission(PERM_C)); + EXPECT_TRUE(rbacData->HasPermission(PERM_D)); +} + +TEST_F(RBACComplexHierarchyTest, DiamondInheritance) +{ + rbacData->GrantPermission(ROLE_X); + rbacData->GrantPermission(ROLE_Y); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(PERM_SHARED)); + EXPECT_TRUE(rbacData->HasPermission(PERM_X_ONLY)); + EXPECT_TRUE(rbacData->HasPermission(PERM_Y_ONLY)); +} + +TEST_F(RBACComplexHierarchyTest, WideRole) +{ + rbacData->GrantPermission(ROLE_WIDE); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(ROLE_WIDE)); + EXPECT_TRUE(rbacData->HasPermission(PERM_A)); + EXPECT_TRUE(rbacData->HasPermission(PERM_L)); + EXPECT_EQ(rbacData->GetPermissions().size(), 13u); // ROLE_WIDE + 12 perms +} + +TEST_F(RBACComplexHierarchyTest, TwoOverlappingRoles_NoDuplicateInGetPermissions) +{ + // Both ROLE_X and ROLE_Y link to PERM_SHARED + rbacData->GrantPermission(ROLE_X); + rbacData->GrantPermission(ROLE_Y); + rbacData->RecalculatePermissions(); + + auto const& perms = rbacData->GetPermissions(); + // ROLE_X, ROLE_Y, PERM_SHARED, PERM_X_ONLY, PERM_Y_ONLY = 5 + EXPECT_EQ(perms.size(), 5u); + EXPECT_EQ(perms.count(PERM_SHARED), 1u); +} + +TEST_F(RBACComplexHierarchyTest, RevokeOneOverlappingRole_KeepsSharedFromOther) +{ + rbacData->GrantPermission(ROLE_X); + rbacData->GrantPermission(ROLE_Y); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(PERM_SHARED)); + + rbacData->RevokePermission(ROLE_X); + rbacData->RecalculatePermissions(); + + // PERM_SHARED still accessible through ROLE_Y + EXPECT_TRUE(rbacData->HasPermission(PERM_SHARED)); + EXPECT_TRUE(rbacData->HasPermission(PERM_Y_ONLY)); + EXPECT_FALSE(rbacData->HasPermission(PERM_X_ONLY)); +} + +// --------------------------------------------------------------------------- +// Suite 5: RBACDenySpecificFromRoleTest +// --------------------------------------------------------------------------- +class RBACDenySpecificFromRoleTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_KICK = 10; + static constexpr uint32 PERM_BAN = 11; + static constexpr uint32 PERM_MUTE = 12; + static constexpr uint32 PERM_SHUTDOWN = 13; + static constexpr uint32 ROLE_MOD = 100; + static constexpr uint32 ROLE_ADMIN = 101; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_KICK, "Kick"); + sAccountMgr->AddPermissionForTest(PERM_BAN, "Ban"); + sAccountMgr->AddPermissionForTest(PERM_MUTE, "Mute"); + sAccountMgr->AddPermissionForTest(PERM_SHUTDOWN, "Shutdown"); + sAccountMgr->AddPermissionForTest(ROLE_MOD, "Moderator"); + sAccountMgr->AddPermissionForTest(ROLE_ADMIN, "Admin"); + + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_KICK); + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_BAN); + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_MUTE); + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, PERM_SHUTDOWN); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACDenySpecificFromRoleTest, DenyOneChild_SiblingsStillGranted) +{ + rbacData->GrantPermission(ROLE_MOD); + rbacData->DenyPermission(PERM_BAN); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(ROLE_MOD)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_MUTE)); + EXPECT_FALSE(rbacData->HasPermission(PERM_BAN)); +} + +TEST_F(RBACDenySpecificFromRoleTest, DenyPermNotInRole_RolePermsUnaffected) +{ + rbacData->GrantPermission(ROLE_MOD); + rbacData->DenyPermission(PERM_SHUTDOWN); + rbacData->RecalculatePermissions(); + + EXPECT_TRUE(rbacData->HasPermission(ROLE_MOD)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_BAN)); + EXPECT_TRUE(rbacData->HasPermission(PERM_MUTE)); + EXPECT_FALSE(rbacData->HasPermission(PERM_SHUTDOWN)); +} + +TEST_F(RBACDenySpecificFromRoleTest, GrantTwoRoles_DenyOneRole) +{ + rbacData->GrantPermission(ROLE_MOD); + rbacData->GrantPermission(ROLE_ADMIN); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(PERM_SHUTDOWN)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + + // Revoke and deny ROLE_ADMIN + rbacData->RevokePermission(ROLE_ADMIN); + rbacData->DenyPermission(ROLE_ADMIN); + rbacData->RecalculatePermissions(); + + // ROLE_ADMIN and its unique perm (SHUTDOWN) denied + EXPECT_FALSE(rbacData->HasPermission(ROLE_ADMIN)); + EXPECT_FALSE(rbacData->HasPermission(PERM_SHUTDOWN)); + + // ROLE_MOD perms remain + EXPECT_TRUE(rbacData->HasPermission(ROLE_MOD)); + EXPECT_TRUE(rbacData->HasPermission(PERM_KICK)); + EXPECT_TRUE(rbacData->HasPermission(PERM_BAN)); + EXPECT_TRUE(rbacData->HasPermission(PERM_MUTE)); +} + +// --------------------------------------------------------------------------- +// Suite 6: RBACDefaultPermissionsWithRolesTest +// --------------------------------------------------------------------------- +class RBACDefaultPermissionsWithRolesTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_A = 10; + static constexpr uint32 PERM_B = 11; + static constexpr uint32 PERM_C = 12; + static constexpr uint32 PERM_MOD_1 = 13; + static constexpr uint32 ROLE_PLAYER = 100; + + static constexpr uint8 SEC_PLAYER = 0; + static constexpr uint8 SEC_MODERATOR = 1; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_A, "A"); + sAccountMgr->AddPermissionForTest(PERM_B, "B"); + sAccountMgr->AddPermissionForTest(PERM_C, "C"); + sAccountMgr->AddPermissionForTest(PERM_MOD_1, "Mod 1"); + sAccountMgr->AddPermissionForTest(ROLE_PLAYER, "Player Role"); + + sAccountMgr->AddLinkedPermissionForTest(ROLE_PLAYER, PERM_A); + sAccountMgr->AddLinkedPermissionForTest(ROLE_PLAYER, PERM_B); + + // Default: Player gets ROLE_PLAYER, Moderator gets PERM_MOD_1 + sAccountMgr->AddDefaultPermissionForTest(SEC_PLAYER, ROLE_PLAYER); + sAccountMgr->AddDefaultPermissionForTest(SEC_MODERATOR, PERM_MOD_1); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACDefaultPermissionsWithRolesTest, DefaultRoleExpandsLinked) +{ + rbac::RBACData data(1, "Player", TEST_REALM_ID, SEC_PLAYER); + + // Simulate LoadFromDBCallback: grant defaults then recalculate + rbac::RBACPermissionContainer const& defaults = sAccountMgr->GetRBACDefaultPermissions(SEC_PLAYER); + for (uint32 perm : defaults) + data.GrantPermission(perm); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_A)); + EXPECT_TRUE(data.HasPermission(PERM_B)); +} + +TEST_F(RBACDefaultPermissionsWithRolesTest, DefaultRole_DenyLinkedChild) +{ + rbac::RBACData data(1, "Player", TEST_REALM_ID, SEC_PLAYER); + + rbac::RBACPermissionContainer const& defaults = sAccountMgr->GetRBACDefaultPermissions(SEC_PLAYER); + for (uint32 perm : defaults) + data.GrantPermission(perm); + + data.DenyPermission(PERM_B); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_A)); + EXPECT_FALSE(data.HasPermission(PERM_B)); +} + +TEST_F(RBACDefaultPermissionsWithRolesTest, SecLevels_NoCrossContamination) +{ + rbac::RBACData playerData(1, "Player", TEST_REALM_ID, SEC_PLAYER); + rbac::RBACData modData(2, "Mod", TEST_REALM_ID, SEC_MODERATOR); + + // Grant defaults for each + for (uint32 p : sAccountMgr->GetRBACDefaultPermissions(SEC_PLAYER)) + playerData.GrantPermission(p); + playerData.RecalculatePermissions(); + + for (uint32 p : sAccountMgr->GetRBACDefaultPermissions(SEC_MODERATOR)) + modData.GrantPermission(p); + modData.RecalculatePermissions(); + + // Player has player perms, not mod perms + EXPECT_TRUE(playerData.HasPermission(PERM_A)); + EXPECT_FALSE(playerData.HasPermission(PERM_MOD_1)); + + // Mod has mod perms, not player perms (unless explicitly granted) + EXPECT_TRUE(modData.HasPermission(PERM_MOD_1)); + EXPECT_FALSE(modData.HasPermission(PERM_A)); +} + +// --------------------------------------------------------------------------- +// Suite 7: RBACPermissionEnumConsistencyTest +// --------------------------------------------------------------------------- +class RBACPermissionEnumConsistencyTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(500, "Perm 500"); + sAccountMgr->AddPermissionForTest(700, "Perm 700"); + sAccountMgr->AddPermissionForTest(900, "Perm 900"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACPermissionEnumConsistencyTest, MaxGreaterThanHighestDefined) +{ + EXPECT_GT(static_cast(rbac::RBAC_PERM_MAX), 911u); +} + +TEST_F(RBACPermissionEnumConsistencyTest, RoleIdsWithinRange) +{ + EXPECT_LT(static_cast(rbac::RBAC_ROLE_ADMINISTRATOR), static_cast(rbac::RBAC_PERM_MAX)); + EXPECT_LT(static_cast(rbac::RBAC_ROLE_GAMEMASTER), static_cast(rbac::RBAC_PERM_MAX)); + EXPECT_LT(static_cast(rbac::RBAC_ROLE_MODERATOR), static_cast(rbac::RBAC_PERM_MAX)); + EXPECT_LT(static_cast(rbac::RBAC_ROLE_PLAYER), static_cast(rbac::RBAC_PERM_MAX)); +} + +TEST_F(RBACPermissionEnumConsistencyTest, NonContiguousIds_Work) +{ + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + + data.GrantPermission(500); + data.GrantPermission(900); + data.DenyPermission(700); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(500)); + EXPECT_TRUE(data.HasPermission(900)); + EXPECT_FALSE(data.HasPermission(700)); +} + +// --------------------------------------------------------------------------- +// Suite 8: RBACEmptyAndBoundaryTest +// --------------------------------------------------------------------------- +class RBACEmptyAndBoundaryTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission 1"); + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACEmptyAndBoundaryTest, FreshData_AllEmpty) +{ + EXPECT_TRUE(rbacData->GetGrantedPermissions().empty()); + EXPECT_TRUE(rbacData->GetDeniedPermissions().empty()); + EXPECT_TRUE(rbacData->GetPermissions().empty()); +} + +TEST_F(RBACEmptyAndBoundaryTest, HasPermission_Zero_ReturnsFalse) +{ + EXPECT_FALSE(rbacData->HasPermission(0)); +} + +TEST_F(RBACEmptyAndBoundaryTest, HasPermission_Max_ReturnsFalse) +{ + EXPECT_FALSE(rbacData->HasPermission(rbac::RBAC_PERM_MAX)); +} + +TEST_F(RBACEmptyAndBoundaryTest, GrantDenyRevokeSequence) +{ + rbac::RBACCommandResult r1 = rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(r1, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(TEST_PERM_1)); + + rbac::RBACCommandResult r2 = rbacData->RevokePermission(TEST_PERM_1); + EXPECT_EQ(r2, rbac::RBAC_OK); + + rbac::RBACCommandResult r3 = rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(r3, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); + + rbac::RBACCommandResult r4 = rbacData->RevokePermission(TEST_PERM_1); + EXPECT_EQ(r4, rbac::RBAC_OK); + rbacData->RecalculatePermissions(); + EXPECT_FALSE(rbacData->HasPermission(TEST_PERM_1)); +} + +TEST_F(RBACEmptyAndBoundaryTest, MultipleRecalculates_Idempotent) +{ + rbacData->GrantPermission(TEST_PERM_1); + rbacData->RecalculatePermissions(); + auto perms1 = rbacData->GetPermissions(); + + rbacData->RecalculatePermissions(); + auto perms2 = rbacData->GetPermissions(); + + rbacData->RecalculatePermissions(); + auto perms3 = rbacData->GetPermissions(); + + EXPECT_EQ(perms1, perms2); + EXPECT_EQ(perms2, perms3); +} + +TEST_F(RBACEmptyAndBoundaryTest, RecalculateOnEmpty_Safe) +{ + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->GetPermissions().empty()); + + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->GetPermissions().empty()); +} + +// --------------------------------------------------------------------------- +// Suite 9: RBACCircularLinkProtectionTest +// --------------------------------------------------------------------------- +class RBACCircularLinkProtectionTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_A = 10; + static constexpr uint32 PERM_B = 11; + static constexpr uint32 PERM_C = 12; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_A, "A"); + sAccountMgr->AddPermissionForTest(PERM_B, "B"); + sAccountMgr->AddPermissionForTest(PERM_C, "C"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACCircularLinkProtectionTest, MutualLink_BothGranted) +{ + sAccountMgr->AddLinkedPermissionForTest(PERM_A, PERM_B); + sAccountMgr->AddLinkedPermissionForTest(PERM_B, PERM_A); + + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + data.GrantPermission(PERM_A); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(PERM_A)); + EXPECT_TRUE(data.HasPermission(PERM_B)); +} + +TEST_F(RBACCircularLinkProtectionTest, SelfReferencing_Terminates) +{ + sAccountMgr->AddLinkedPermissionForTest(PERM_A, PERM_A); + + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + data.GrantPermission(PERM_A); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(PERM_A)); + EXPECT_EQ(data.GetPermissions().size(), 1u); +} + +TEST_F(RBACCircularLinkProtectionTest, CircularChainOf3_AllGranted) +{ + sAccountMgr->AddLinkedPermissionForTest(PERM_A, PERM_B); + sAccountMgr->AddLinkedPermissionForTest(PERM_B, PERM_C); + sAccountMgr->AddLinkedPermissionForTest(PERM_C, PERM_A); + + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + data.GrantPermission(PERM_A); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(PERM_A)); + EXPECT_TRUE(data.HasPermission(PERM_B)); + EXPECT_TRUE(data.HasPermission(PERM_C)); + EXPECT_EQ(data.GetPermissions().size(), 3u); +} + +// --------------------------------------------------------------------------- +// Suite 10: RBACFullRoleHierarchyTest (mirrors actual 192-199 structure) +// --------------------------------------------------------------------------- +class RBACFullRoleHierarchyTest : public ::testing::Test +{ +protected: + // Roles + static constexpr uint32 ROLE_PLAYER = 199; + static constexpr uint32 ROLE_MOD = 198; + static constexpr uint32 ROLE_GM = 197; + static constexpr uint32 ROLE_ADMIN = 196; + + // Individual perms + static constexpr uint32 PERM_PLAYER_1 = 10; + static constexpr uint32 PERM_PLAYER_2 = 11; + static constexpr uint32 PERM_MOD_1 = 20; + static constexpr uint32 PERM_MOD_2 = 21; + static constexpr uint32 PERM_GM_1 = 30; + static constexpr uint32 PERM_GM_2 = 31; + static constexpr uint32 PERM_ADMIN_1 = 40; + static constexpr uint32 PERM_ADMIN_2 = 41; + + void SetUp() override + { + // Register individual perms + sAccountMgr->AddPermissionForTest(PERM_PLAYER_1, "Player 1"); + sAccountMgr->AddPermissionForTest(PERM_PLAYER_2, "Player 2"); + sAccountMgr->AddPermissionForTest(PERM_MOD_1, "Mod 1"); + sAccountMgr->AddPermissionForTest(PERM_MOD_2, "Mod 2"); + sAccountMgr->AddPermissionForTest(PERM_GM_1, "GM 1"); + sAccountMgr->AddPermissionForTest(PERM_GM_2, "GM 2"); + sAccountMgr->AddPermissionForTest(PERM_ADMIN_1, "Admin 1"); + sAccountMgr->AddPermissionForTest(PERM_ADMIN_2, "Admin 2"); + + // Register roles + sAccountMgr->AddPermissionForTest(ROLE_PLAYER, "Player Role"); + sAccountMgr->AddPermissionForTest(ROLE_MOD, "Moderator Role"); + sAccountMgr->AddPermissionForTest(ROLE_GM, "GameMaster Role"); + sAccountMgr->AddPermissionForTest(ROLE_ADMIN, "Administrator Role"); + + // Player(199) -> basic perms + sAccountMgr->AddLinkedPermissionForTest(ROLE_PLAYER, PERM_PLAYER_1); + sAccountMgr->AddLinkedPermissionForTest(ROLE_PLAYER, PERM_PLAYER_2); + + // Mod(198) -> Player + mod perms + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, ROLE_PLAYER); + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_MOD_1); + sAccountMgr->AddLinkedPermissionForTest(ROLE_MOD, PERM_MOD_2); + + // GM(197) -> Mod + gm perms + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, ROLE_MOD); + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_GM_1); + sAccountMgr->AddLinkedPermissionForTest(ROLE_GM, PERM_GM_2); + + // Admin(196) -> GM + admin perms + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, ROLE_GM); + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, PERM_ADMIN_1); + sAccountMgr->AddLinkedPermissionForTest(ROLE_ADMIN, PERM_ADMIN_2); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACFullRoleHierarchyTest, GrantPlayerRole_OnlyPlayerPerms) +{ + rbac::RBACData data(1, "Player", TEST_REALM_ID, 0); + data.GrantPermission(ROLE_PLAYER); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_1)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_2)); + + EXPECT_FALSE(data.HasPermission(PERM_MOD_1)); + EXPECT_FALSE(data.HasPermission(PERM_GM_1)); + EXPECT_FALSE(data.HasPermission(PERM_ADMIN_1)); + // 3 total: ROLE_PLAYER + 2 player perms + EXPECT_EQ(data.GetPermissions().size(), 3u); +} + +TEST_F(RBACFullRoleHierarchyTest, GrantGMRole_FullChain) +{ + rbac::RBACData data(1, "GM", TEST_REALM_ID, 0); + data.GrantPermission(ROLE_GM); + data.RecalculatePermissions(); + + // GM + Mod + Player perms + EXPECT_TRUE(data.HasPermission(ROLE_GM)); + EXPECT_TRUE(data.HasPermission(ROLE_MOD)); + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_1)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_2)); + EXPECT_TRUE(data.HasPermission(PERM_MOD_1)); + EXPECT_TRUE(data.HasPermission(PERM_MOD_2)); + EXPECT_TRUE(data.HasPermission(PERM_GM_1)); + EXPECT_TRUE(data.HasPermission(PERM_GM_2)); + + EXPECT_FALSE(data.HasPermission(PERM_ADMIN_1)); + EXPECT_FALSE(data.HasPermission(PERM_ADMIN_2)); + // 9 total: 3 roles + 6 perms + EXPECT_EQ(data.GetPermissions().size(), 9u); +} + +TEST_F(RBACFullRoleHierarchyTest, GrantAdminRole_AllPerms) +{ + rbac::RBACData data(1, "Admin", TEST_REALM_ID, 0); + data.GrantPermission(ROLE_ADMIN); + data.RecalculatePermissions(); + + EXPECT_TRUE(data.HasPermission(ROLE_ADMIN)); + EXPECT_TRUE(data.HasPermission(ROLE_GM)); + EXPECT_TRUE(data.HasPermission(ROLE_MOD)); + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_1)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_2)); + EXPECT_TRUE(data.HasPermission(PERM_MOD_1)); + EXPECT_TRUE(data.HasPermission(PERM_MOD_2)); + EXPECT_TRUE(data.HasPermission(PERM_GM_1)); + EXPECT_TRUE(data.HasPermission(PERM_GM_2)); + EXPECT_TRUE(data.HasPermission(PERM_ADMIN_1)); + EXPECT_TRUE(data.HasPermission(PERM_ADMIN_2)); + // 12 total: 4 roles + 8 perms + EXPECT_EQ(data.GetPermissions().size(), 12u); +} + +TEST_F(RBACFullRoleHierarchyTest, GrantAdmin_DenyModRole_ModAndPlayerDenied) +{ + rbac::RBACData data(1, "Admin", TEST_REALM_ID, 0); + data.GrantPermission(ROLE_ADMIN); + data.DenyPermission(ROLE_MOD); + data.RecalculatePermissions(); + + // Admin + GM perms remain + EXPECT_TRUE(data.HasPermission(ROLE_ADMIN)); + EXPECT_TRUE(data.HasPermission(ROLE_GM)); + EXPECT_TRUE(data.HasPermission(PERM_GM_1)); + EXPECT_TRUE(data.HasPermission(PERM_GM_2)); + EXPECT_TRUE(data.HasPermission(PERM_ADMIN_1)); + EXPECT_TRUE(data.HasPermission(PERM_ADMIN_2)); + + // Mod role and its full chain denied (Mod + Player perms) + EXPECT_FALSE(data.HasPermission(ROLE_MOD)); + EXPECT_FALSE(data.HasPermission(ROLE_PLAYER)); + EXPECT_FALSE(data.HasPermission(PERM_MOD_1)); + EXPECT_FALSE(data.HasPermission(PERM_MOD_2)); + EXPECT_FALSE(data.HasPermission(PERM_PLAYER_1)); + EXPECT_FALSE(data.HasPermission(PERM_PLAYER_2)); +} + +TEST_F(RBACFullRoleHierarchyTest, GrantAdmin_DenyOneCommandPerm) +{ + rbac::RBACData data(1, "Admin", TEST_REALM_ID, 0); + data.GrantPermission(ROLE_ADMIN); + data.DenyPermission(PERM_GM_1); + data.RecalculatePermissions(); + + // Only PERM_GM_1 is denied + EXPECT_FALSE(data.HasPermission(PERM_GM_1)); + + // Everything else still works + EXPECT_TRUE(data.HasPermission(ROLE_ADMIN)); + EXPECT_TRUE(data.HasPermission(ROLE_GM)); + EXPECT_TRUE(data.HasPermission(ROLE_MOD)); + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_GM_2)); + EXPECT_TRUE(data.HasPermission(PERM_ADMIN_1)); + EXPECT_TRUE(data.HasPermission(PERM_ADMIN_2)); + EXPECT_TRUE(data.HasPermission(PERM_MOD_1)); + EXPECT_TRUE(data.HasPermission(PERM_PLAYER_1)); + // 11 total: 12 - 1 denied + EXPECT_EQ(data.GetPermissions().size(), 11u); +} + +// --------------------------------------------------------------------------- +// Suite 11: RBACPermissionDefaultConstructorTest +// --------------------------------------------------------------------------- +class RBACPermissionDefaultConstructorTest : public ::testing::Test +{ +}; + +TEST_F(RBACPermissionDefaultConstructorTest, DefaultConstructor_ZeroIdEmptyName) +{ + rbac::RBACPermission perm; + EXPECT_EQ(perm.GetId(), 0u); + EXPECT_EQ(perm.GetName(), ""); + EXPECT_TRUE(perm.GetLinkedPermissions().empty()); +} + +TEST_F(RBACPermissionDefaultConstructorTest, ConstructorWithIdOnly) +{ + rbac::RBACPermission perm(42); + EXPECT_EQ(perm.GetId(), 42u); + EXPECT_EQ(perm.GetName(), ""); + EXPECT_TRUE(perm.GetLinkedPermissions().empty()); +} + +// --------------------------------------------------------------------------- +// Suite 12: RBACAccountMgrPermissionLookupTest +// --------------------------------------------------------------------------- +class RBACAccountMgrPermissionLookupTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission One"); + sAccountMgr->AddPermissionForTest(TEST_PERM_2, "Permission Two"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACAccountMgrPermissionLookupTest, GetRBACPermission_ValidId_ReturnsPermission) +{ + rbac::RBACPermission const* perm = sAccountMgr->GetRBACPermission(TEST_PERM_1); + ASSERT_NE(perm, nullptr); + EXPECT_EQ(perm->GetId(), TEST_PERM_1); + EXPECT_EQ(perm->GetName(), "Permission One"); +} + +TEST_F(RBACAccountMgrPermissionLookupTest, GetRBACPermission_InvalidId_ReturnsNull) +{ + rbac::RBACPermission const* perm = sAccountMgr->GetRBACPermission(TEST_PERM_INVALID); + EXPECT_EQ(perm, nullptr); +} + +TEST_F(RBACAccountMgrPermissionLookupTest, GetRBACPermissionList_ContainsRegistered) +{ + rbac::RBACPermissionsContainer const& list = sAccountMgr->GetRBACPermissionList(); + EXPECT_TRUE(list.find(TEST_PERM_1) != list.end()); + EXPECT_TRUE(list.find(TEST_PERM_2) != list.end()); + EXPECT_TRUE(list.find(TEST_PERM_INVALID) == list.end()); +} + +TEST_F(RBACAccountMgrPermissionLookupTest, GetRBACPermissionList_SizeMatchesRegistered) +{ + rbac::RBACPermissionsContainer const& list = sAccountMgr->GetRBACPermissionList(); + EXPECT_EQ(list.size(), 2u); +} + +// --------------------------------------------------------------------------- +// Suite 13: RBACAccountMgrTestHelperEdgeCasesTest +// --------------------------------------------------------------------------- +class RBACAccountMgrTestHelperEdgeCasesTest : public ::testing::Test +{ +protected: + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACAccountMgrTestHelperEdgeCasesTest, AddPermissionForTest_DuplicateIsNoOp) +{ + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Original Name"); + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Different Name"); + + rbac::RBACPermission const* perm = sAccountMgr->GetRBACPermission(TEST_PERM_1); + ASSERT_NE(perm, nullptr); + EXPECT_EQ(perm->GetName(), "Original Name"); +} + +TEST_F(RBACAccountMgrTestHelperEdgeCasesTest, AddLinkedPermission_UnregisteredParent_NoOp) +{ + // Link to non-existent parent: should silently do nothing + sAccountMgr->AddLinkedPermissionForTest(TEST_PERM_INVALID, TEST_PERM_1); + EXPECT_EQ(sAccountMgr->GetRBACPermission(TEST_PERM_INVALID), nullptr); +} + +TEST_F(RBACAccountMgrTestHelperEdgeCasesTest, ClearPermissions_RemovesEverything) +{ + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "One"); + sAccountMgr->AddPermissionForTest(TEST_PERM_2, "Two"); + sAccountMgr->AddDefaultPermissionForTest(0, TEST_PERM_1); + + sAccountMgr->ClearPermissionsForTest(); + + EXPECT_EQ(sAccountMgr->GetRBACPermission(TEST_PERM_1), nullptr); + EXPECT_EQ(sAccountMgr->GetRBACPermission(TEST_PERM_2), nullptr); + EXPECT_TRUE(sAccountMgr->GetRBACPermissionList().empty()); + EXPECT_TRUE(sAccountMgr->GetRBACDefaultPermissions(0).empty()); +} + +// --------------------------------------------------------------------------- +// Suite 14: RBACExpandPermissionsDanglingLinkTest +// --------------------------------------------------------------------------- +class RBACExpandPermissionsDanglingLinkTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_VALID = 10; + static constexpr uint32 PERM_DANGLING = 9999; + static constexpr uint32 ROLE_WITH_DANGLING = 100; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_VALID, "Valid"); + sAccountMgr->AddPermissionForTest(ROLE_WITH_DANGLING, "Role With Dangling"); + + // Role links to valid perm AND an unregistered perm ID + sAccountMgr->AddLinkedPermissionForTest(ROLE_WITH_DANGLING, PERM_VALID); + sAccountMgr->AddLinkedPermissionForTest(ROLE_WITH_DANGLING, PERM_DANGLING); + + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACExpandPermissionsDanglingLinkTest, DanglingLink_SkippedGracefully) +{ + rbacData->GrantPermission(ROLE_WITH_DANGLING); + rbacData->RecalculatePermissions(); + + // Valid perm expanded, dangling silently skipped + EXPECT_TRUE(rbacData->HasPermission(ROLE_WITH_DANGLING)); + EXPECT_TRUE(rbacData->HasPermission(PERM_VALID)); + EXPECT_FALSE(rbacData->HasPermission(PERM_DANGLING)); + // Only 2: the role + the valid perm (dangling not included) + EXPECT_EQ(rbacData->GetPermissions().size(), 2u); +} + +TEST_F(RBACExpandPermissionsDanglingLinkTest, DenyDanglingLink_SkippedGracefully) +{ + rbacData->GrantPermission(PERM_VALID); + // PERM_DANGLING can't be denied since it's not registered + rbac::RBACCommandResult result = rbacData->DenyPermission(PERM_DANGLING); + EXPECT_EQ(result, rbac::RBAC_ID_DOES_NOT_EXISTS); + + rbacData->RecalculatePermissions(); + EXPECT_TRUE(rbacData->HasPermission(PERM_VALID)); +} + +// --------------------------------------------------------------------------- +// Suite 15: RBACLoadFromDBCallbackSimulationTest +// --------------------------------------------------------------------------- +class RBACLoadFromDBCallbackSimulationTest : public ::testing::Test +{ +protected: + static constexpr uint32 PERM_A = 10; + static constexpr uint32 PERM_B = 11; + static constexpr uint32 ROLE_PLAYER = 100; + + static constexpr uint8 SEC_PLAYER = 0; + + void SetUp() override + { + sAccountMgr->AddPermissionForTest(PERM_A, "A"); + sAccountMgr->AddPermissionForTest(PERM_B, "B"); + sAccountMgr->AddPermissionForTest(ROLE_PLAYER, "Player Role"); + + sAccountMgr->AddLinkedPermissionForTest(ROLE_PLAYER, PERM_A); + sAccountMgr->AddLinkedPermissionForTest(ROLE_PLAYER, PERM_B); + + sAccountMgr->AddDefaultPermissionForTest(SEC_PLAYER, ROLE_PLAYER); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACLoadFromDBCallbackSimulationTest, NullResult_AppliesDefaultsAndRecalculates) +{ + rbac::RBACData data(1, "Player", TEST_REALM_ID, SEC_PLAYER); + + // Simulate LoadFromDBCallback with no DB rows (nullptr result) + data.LoadFromDBCallback(nullptr); + + // Default permission (ROLE_PLAYER) should be granted and expanded + EXPECT_TRUE(data.HasPermission(ROLE_PLAYER)); + EXPECT_TRUE(data.HasPermission(PERM_A)); + EXPECT_TRUE(data.HasPermission(PERM_B)); + EXPECT_EQ(data.GetPermissions().size(), 3u); +} + +TEST_F(RBACLoadFromDBCallbackSimulationTest, NullResult_NoDefaultsForHighSecLevel) +{ + // Sec level 3 has no defaults configured + rbac::RBACData data(1, "Admin", TEST_REALM_ID, 3); + data.LoadFromDBCallback(nullptr); + + EXPECT_TRUE(data.GetPermissions().empty()); +} + +// --------------------------------------------------------------------------- +// Suite 16: RBACDoubleRevokeTest +// --------------------------------------------------------------------------- +class RBACDoubleRevokeTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission 1"); + rbacData = std::make_unique(TEST_ACCOUNT_ID, TEST_ACCOUNT_NAME, TEST_REALM_ID, TEST_SEC_LEVEL); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } + + std::unique_ptr rbacData; +}; + +TEST_F(RBACDoubleRevokeTest, RevokeGrantedTwice_SecondFails) +{ + rbacData->GrantPermission(TEST_PERM_1); + EXPECT_EQ(rbacData->RevokePermission(TEST_PERM_1), rbac::RBAC_OK); + EXPECT_EQ(rbacData->RevokePermission(TEST_PERM_1), rbac::RBAC_CANT_REVOKE_NOT_IN_LIST); +} + +TEST_F(RBACDoubleRevokeTest, RevokeDeniedTwice_SecondFails) +{ + rbacData->DenyPermission(TEST_PERM_1); + EXPECT_EQ(rbacData->RevokePermission(TEST_PERM_1), rbac::RBAC_OK); + EXPECT_EQ(rbacData->RevokePermission(TEST_PERM_1), rbac::RBAC_CANT_REVOKE_NOT_IN_LIST); +} + +// --------------------------------------------------------------------------- +// Suite 17: RBACMultipleInstancesIndependenceTest +// --------------------------------------------------------------------------- +class RBACMultipleInstancesIndependenceTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission 1"); + sAccountMgr->AddPermissionForTest(TEST_PERM_2, "Permission 2"); + sAccountMgr->AddPermissionForTest(TEST_PERM_3, "Permission 3"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACMultipleInstancesIndependenceTest, TwoInstances_NoCrossContamination) +{ + rbac::RBACData data1(1, "Account1", TEST_REALM_ID, 0); + rbac::RBACData data2(2, "Account2", TEST_REALM_ID, 0); + + data1.GrantPermission(TEST_PERM_1); + data2.GrantPermission(TEST_PERM_2); + + data1.RecalculatePermissions(); + data2.RecalculatePermissions(); + + EXPECT_TRUE(data1.HasPermission(TEST_PERM_1)); + EXPECT_FALSE(data1.HasPermission(TEST_PERM_2)); + + EXPECT_FALSE(data2.HasPermission(TEST_PERM_1)); + EXPECT_TRUE(data2.HasPermission(TEST_PERM_2)); +} + +TEST_F(RBACMultipleInstancesIndependenceTest, ModifyingOne_DoesNotAffectOther) +{ + rbac::RBACData data1(1, "Account1", TEST_REALM_ID, 0); + rbac::RBACData data2(2, "Account2", TEST_REALM_ID, 0); + + data1.GrantPermission(TEST_PERM_1); + data1.GrantPermission(TEST_PERM_2); + data2.GrantPermission(TEST_PERM_1); + + data1.RecalculatePermissions(); + data2.RecalculatePermissions(); + + // Revoke from data1, data2 unaffected + data1.RevokePermission(TEST_PERM_1); + data1.RecalculatePermissions(); + + EXPECT_FALSE(data1.HasPermission(TEST_PERM_1)); + EXPECT_TRUE(data2.HasPermission(TEST_PERM_1)); +} + +// --------------------------------------------------------------------------- +// Suite 18: RBACSetSecurityLevelForTestBehaviorTest +// --------------------------------------------------------------------------- +class RBACSetSecurityLevelForTestBehaviorTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission 1"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACSetSecurityLevelForTestBehaviorTest, DoesNotRecalculate) +{ + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + data.GrantPermission(TEST_PERM_1); + data.RecalculatePermissions(); + EXPECT_TRUE(data.HasPermission(TEST_PERM_1)); + + // Changing sec level via test helper should NOT clear/recalculate perms + data.SetSecurityLevelForTest(3); + EXPECT_EQ(data.GetSecurityLevel(), 3); + EXPECT_TRUE(data.HasPermission(TEST_PERM_1)); +} + +TEST_F(RBACSetSecurityLevelForTestBehaviorTest, UpdatesLevelOnly) +{ + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + EXPECT_EQ(data.GetSecurityLevel(), 0); + + data.SetSecurityLevelForTest(1); + EXPECT_EQ(data.GetSecurityLevel(), 1); + + data.SetSecurityLevelForTest(255); + EXPECT_EQ(data.GetSecurityLevel(), 255); +} + +// --------------------------------------------------------------------------- +// Suite 19: RBACDataAccessorsTest +// --------------------------------------------------------------------------- +class RBACDataAccessorsTest : public ::testing::Test +{ +protected: + void SetUp() override + { + sAccountMgr->AddPermissionForTest(TEST_PERM_1, "Permission 1"); + } + + void TearDown() override + { + sAccountMgr->ClearPermissionsForTest(); + } +}; + +TEST_F(RBACDataAccessorsTest, GetName_ReturnsAccountName) +{ + rbac::RBACData data(42, "MyAccount", TEST_REALM_ID, 0); + EXPECT_EQ(data.GetName(), "MyAccount"); +} + +TEST_F(RBACDataAccessorsTest, GetName_EmptyString) +{ + rbac::RBACData data(1, "", TEST_REALM_ID, 0); + EXPECT_EQ(data.GetName(), ""); +} + +TEST_F(RBACDataAccessorsTest, GetId_ReturnsAccountId) +{ + rbac::RBACData data(42, "Test", TEST_REALM_ID, 0); + EXPECT_EQ(data.GetId(), 42u); +} + +TEST_F(RBACDataAccessorsTest, GrantedDeniedGlobal_AllConsistent) +{ + rbac::RBACData data(1, "Test", TEST_REALM_ID, 0); + + data.GrantPermission(TEST_PERM_1); + EXPECT_EQ(data.GetGrantedPermissions().size(), 1u); + EXPECT_TRUE(data.GetDeniedPermissions().empty()); + + // Before recalculate, global perms are still empty + EXPECT_TRUE(data.GetPermissions().empty()); + + data.RecalculatePermissions(); + // After recalculate, global perms reflect granted + EXPECT_EQ(data.GetPermissions().size(), 1u); + EXPECT_TRUE(data.HasPermission(TEST_PERM_1)); +} + +} // namespace diff --git a/src/test/server/game/Commands/GmVisibleCommandTest.cpp b/src/test/server/game/Commands/GmVisibleCommandTest.cpp index 67a7e9a2f..f916b079e 100644 --- a/src/test/server/game/Commands/GmVisibleCommandTest.cpp +++ b/src/test/server/game/Commands/GmVisibleCommandTest.cpp @@ -29,11 +29,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include -#include - -#ifndef TEST_F -#define TEST_F(fixture, name) void fixture##_##name() -#endif using namespace testing; @@ -111,6 +106,7 @@ protected: session = new WorldSession(1, "gm", 0, nullptr, SEC_GAMEMASTER, EXPANSION_WRATH_OF_THE_LICH_KING, 0, LOCALE_enUS, 0, false, false, 0); + session->InitRBACDataForTest(); player = new TestPlayer(session); player->ForceInitValues(); @@ -133,20 +129,14 @@ protected: player = nullptr; } - void ExecuteCommand(std::string_view text) + void SimulateGmVisibleOff() { - if (text == ".gm visible off") - { - ApplyGmVisibleState(false); - } - else if (text == ".gm visible on") - { - ApplyGmVisibleState(true); - } - else - { - FAIL() << "Unsupported test command: " << text; - } + player->SetServerSideVisibility(SERVERSIDE_VISIBILITY_GM, session->GetSecurity()); + } + + void SimulateGmVisibleOn() + { + player->SetServerSideVisibility(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER); } static void EnsureScriptRegistriesInitialized() @@ -167,52 +157,31 @@ protected: NiceMock* worldMock = nullptr; WorldSession* session = nullptr; TestPlayer* player = nullptr; - -private: - void ApplyGmVisibleState(bool makeVisible) - { - constexpr uint32 VISUAL_AURA = 37800; - - if (makeVisible) - { - player->RemoveAurasDueToSpell(VISUAL_AURA); - player->SetGMVisible(true); - } - else - { - player->AddAura(VISUAL_AURA, player); - player->SetGMVisible(false); - } - - player->UpdateObjectVisibility(); - } }; +// cppcheck-suppress syntaxError TEST_F(GmVisibleCommandTest, SetsPlayerInvisibleAndInvokesHook) { - ExecuteCommand(".gm visible off"); + SimulateGmVisibleOff(); EXPECT_EQ(TestVisibilityScript::CallCount, 1u); EXPECT_EQ(TestVisibilityScript::LastPlayer, player); EXPECT_EQ(TestVisibilityScript::LastType, SERVERSIDE_VISIBILITY_GM); EXPECT_EQ(TestVisibilityScript::LastSecurity, session->GetSecurity()); EXPECT_EQ(player->m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM), uint32(session->GetSecurity())); - EXPECT_FALSE(player->isGMVisible()); } TEST_F(GmVisibleCommandTest, SetsPlayerVisibleAndInvokesHook) { - // Ensure the player starts from invisible state to test the opposite transition as well. - ExecuteCommand(".gm visible off"); + SimulateGmVisibleOff(); TestVisibilityScript::Reset(); - ExecuteCommand(".gm visible on"); + SimulateGmVisibleOn(); EXPECT_EQ(TestVisibilityScript::CallCount, 1u); EXPECT_EQ(TestVisibilityScript::LastPlayer, player); EXPECT_EQ(TestVisibilityScript::LastType, SERVERSIDE_VISIBILITY_GM); EXPECT_EQ(TestVisibilityScript::LastSecurity, SEC_PLAYER); EXPECT_EQ(player->m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM), uint32(SEC_PLAYER)); - EXPECT_TRUE(player->isGMVisible()); } }