/* * Copyright (C) 2008-2013 TrinityCore * * 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: * - Pemission: Defines an autorization to perform certain operation. * - Role: Set of permissions. * - Group: Set of roles. * - An Account can have multiple groups, roles and permissions. * - Account Groups can only be granted or revoked * - 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: * Group Grants + Role Grants + User Grans - Role Grants - User Grants * - Groups, Roles and Permissions can be assigned by realm */ #ifndef _RBAC_H #define _RBAC_H #include "Define.h" #include #include #include #include enum RBACPermissions { RBAC_PERM_INSTANT_LOGOUT = 1, RBAC_PERM_SKIP_QUEUE, RBAC_PERM_JOIN_NORMAL_BG, RBAC_PERM_JOIN_RANDOM_BG, RBAC_PERM_JOIN_ARENAS, RBAC_PERM_JOIN_DUNGEON_FINDER, RBAC_PERM_PLAYER_COMMANDS, RBAC_PERM_MODERATOR_COMMANDS, RBAC_PERM_GAMEMASTER_COMMANDS, RBAC_PERM_ADMINISTRATOR_COMMANDS, 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::bitset RBACPermissionContainer; typedef std::set RBACRoleContainer; typedef std::set RBACGroupContainer; class RBACObject { public: RBACObject(uint32 id = 0, std::string const& name = ""): _id(id), _name(name) { } /// Gets the Name of the Object std::string const& GetName() const { return _name; } /// Gets the Id of the Object uint32 GetId() const { return _id; } private: uint32 _id; ///> id of the object std::string _name; ///> name of the object }; /// Permission: Defines an autorization to perform certain operation class RBACPermission: public RBACObject { public: RBACPermission(uint32 id = 0, std::string const& name = ""): RBACObject(id, name) { } }; /// Set of Permissions class RBACRole: public RBACObject { public: RBACRole(uint32 id = 0, std::string const& name = ""): RBACObject(id, name) { } /// Gets the Permissions assigned to this role RBACPermissionContainer const& GetPermissions() const { return _perms; } /// Grants a Permission (Adds) void GrantPermission(uint32 id) { _perms.set(id); } /// Revokes a Permission (Removes) void RevokePermission(uint32 id) { _perms.reset(id); } private: RBACPermissionContainer _perms; ///> Set of permissions }; /// Set of Roles class RBACGroup: public RBACObject { public: RBACGroup(uint32 id = 0, std::string const& name = ""): RBACObject(id, name) { } /// Gets the Roles assigned to this group RBACRoleContainer const& GetRoles() const { return _roles; } /// Grants a Role (Adds) void GrantRole(uint32 role) { _roles.insert(role); } /// Revokes a Role (Removes) void RevokeRole(uint32 role) { _roles.erase(role); } private: RBACRoleContainer _roles; ///> Set of Roles }; /* * @name RBACData * @brief Contains all needed information about the acccount * * This class contains all the data needed to calculate the account permissions. * RBACDAta is formed by group permissions and user permissions through: * - Granted Groups, which contains roles, which contains permissions: Set of granted permissions * - Granted Roles, which contains permissions: Set of granted permissions * - Denied Roles, which contains permissions: Set of denied permissions * - Granted Permissions * - Denied Permissions * * Calculation of current Permissions: Granted permissions - Denied permissions * - Granted permissions: through groups, through roles and directly assigned * - Denied permissions: through roles and directly assigned */ class RBACData: public RBACObject { public: RBACData(uint32 id, std::string const& name, int32 realmId): RBACObject(id, name), _realmId(realmId) { } /** * @name HasPermission * @brief Checks if certain action is allowed * * Checks if certain action can be performed. * * @return grant or deny action * * Example Usage: * @code * bool Player::CanJoinArena(Battleground* bg) * { * return bg->isArena() && HasPermission(RBAC_PERM_JOIN_ARENA); * } * @endcode */ bool HasPermission(uint32 permission) { return _globalPerms.test(permission); } // 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; } /// Returns all the granted roles RBACRoleContainer const& GetGrantedRoles() const { return _grantedRoles; } /// Returns all the denied roles RBACRoleContainer const& GetDeniedRoles() const { return _deniedRoles; } /// Returns all the granted groups RBACGroupContainer const& GetGroups() const { return _groups; } /** * @name AddGroup * @brief Adds new group * * Add a new group to the account. If realm is 0 or the group can not be added * No save to db action will be performed. * * Fails if group Id does not exists or group already present * * @param groupId group to be added * @param realmId realm affected * * @return Success or failure (with reason) to add the group * * Example Usage: * @code * // previously defined "RBACData* rbac" with proper initialization * uint32 groupId = 2; * if (rbac->AddGroup(groupId) == RBAC_OK) * sLog->outDebug(LOG_FILTER_PLAYER, "Group %u succesfully added", groupId); * @endcode */ RBACCommandResult AddGroup(uint32 groupId, int32 realmId = 0); /** * @name RemoveGroup * @brief Removes a group * * Removes a group from the account. If realm is 0 or the group can not be removed * No save to db action will be performed. Any delete operation will always affect * "all realms (-1)" in addition to the realm specified * * Fails if group not present * * @param groupId group to be removed * @param realmId realm affected * * @return Success or failure (with reason) to remove the group * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 groupId = 2; * if (rbac->RemoveGroup(groupId) == RBAC_OK) * sLog->outDebug(LOG_FILTER_PLAYER, "Group %u succesfully removed", groupId); * @endcode */ RBACCommandResult RemoveGroup(uint32 groupId, int32 realmId = 0); /** * @name GrantRole * @brief Grants a role * * Grants a role to the account. If realm is 0 or the role can not be added * No save to db action will be performed. * * Fails if role Id does not exists or role already granted or denied * * @param roleId role to be granted * @param realmId realm affected * * @return Success or failure (with reason) to grant the role * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 roleId = 2; * if (rbac->GrantRole(roleId) == RBAC_IN_DENIED_LIST) * sLog->outDebug(LOG_FILTER_PLAYER, "Failed to grant role %u, already denied", roleId); * @endcode */ RBACCommandResult GrantRole(uint32 roleId, int32 realmId = 0); /** * @name DenyRole * @brief Denies a role * * Denied a role to the account. If realm is 0 or the role can not be added * No save to db action will be performed. * * Fails if role Id does not exists or role already granted or denied * * @param roleId role to be denied * @param realmId realm affected * * @return Success or failure (with reason) to deny the role * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 roleId = 2; * if (rbac->DenyRole(roleId) == RBAC_ID_DOES_NOT_EXISTS) * sLog->outDebug(LOG_FILTER_PLAYER, "Role Id %u does not exists", roleId); * @endcode */ RBACCommandResult DenyRole(uint32 roleId, int32 realmId = 0); /** * @name RevokeRole * @brief Removes a role * * Removes a role from the account. If realm is 0 or the role can not be removed * No save to db action will be performed. Any delete operation will always affect * "all realms (-1)" in addition to the realm specified * * Fails if role not present * * @param roleId role to be removed * @param realmId realm affected * * @return Success or failure (with reason) to remove the role * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 roleId = 2; * if (rbac->RevokeRole(roleId) == RBAC_OK) * sLog->outDebug(LOG_FILTER_PLAYER, "Role %u succesfully removed", roleId); * @endcode */ RBACCommandResult RevokeRole(uint32 roleId, int32 realmId = 0); /** * @name GrantRole * @brief Grants a permission * * Grants a permission to the account. If realm is 0 or the permission can not be added * No save to db action will be performed. * * Fails if permission Id does not exists or permission already granted or denied * * @param permissionId permission to be granted * @param realmId realm affected * * @return Success or failure (with reason) to grant the permission * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 permissionId = 2; * if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST) * sLog->outDebug(LOG_FILTER_PLAYER, "Failed to grant permission %u, already denied", permissionId); * @endcode */ RBACCommandResult GrantPermission(uint32 permissionId, int32 realmId = 0); /** * @name DenyPermission * @brief Denies a permission * * Denied a permission to the account. If realm is 0 or the permission can not be added * No save to db action will be performed. * * Fails if permission Id does not exists or permission already granted or denied * * @param permissionId permission to be denied * @param realmId realm affected * * @return Success or failure (with reason) to deny the permission * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 permissionId = 2; * if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS) * sLog->outDebug(LOG_FILTER_PLAYER, "Role Id %u does not exists", permissionId); * @endcode */ RBACCommandResult DenyPermission(uint32 permissionId, int32 realmId = 0); /** * @name RevokePermission * @brief Removes a permission * * Removes a permission from the account. If realm is 0 or the permission can not be removed * No save to db action will be performed. Any delete operation will always affect * "all realms (-1)" in addition to the realm specified * * Fails if permission not present * * @param permissionId permission to be removed * @param realmId realm affected * * @return Success or failure (with reason) to remove the permission * * Example Usage: * // previously defined "RBACData* rbac" with proper initialization * uint32 permissionId = 2; * if (rbac->RevokeRole(permissionId) == RBAC_OK) * sLog->outDebug(LOG_FILTER_PLAYER, "Permission %u succesfully removed", permissionId); * @endcode */ RBACCommandResult RevokePermission(uint32 permissionId, int32 realmId = 0); /// Loads all permissions, groups and roles assigned to current account void LoadFromDB(); private: /// Saves a role to DB, Granted or Denied void SaveRole(uint32 role, bool granted, int32 realm); /// Saves a permission to DB, Granted or Denied void SavePermission(uint32 role, bool granted, int32 realm); /** * @name CalculateNewPermissions * @brief Calculates new permissions * * Calculates new permissions after some change in groups, roles or permissions. * The calculation is done Granted - Denied: * - Granted permissions: through groups, through roles and directly assigned * - Denied permissions: through roles and directly assigned */ void CalculateNewPermissions(); int32 GetRealmId() { return _realmId; } int32 _realmId; ///> RealmId Affected RBACGroupContainer _groups; ///> Granted groups RBACRoleContainer _grantedRoles; ///> Granted roles RBACRoleContainer _deniedRoles; ///> Denied roles RBACPermissionContainer _grantedPerms; ///> Granted permissions RBACPermissionContainer _deniedPerms; ///> Denied permissions RBACPermissionContainer _globalPerms; ///> Calculated permissions }; #endif