github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/permission/v2/contract/RoleManager.sol (about) 1 pragma solidity ^0.5.3; 2 3 import "./PermissionsUpgradable.sol"; 4 /** @title Role manager contract 5 * @notice This contract holds implementation logic for all role management 6 functionality. This can be called only by the implementation 7 contract only. there are few view functions exposed as public and 8 can be called directly. these are invoked by quorum for populating 9 permissions data in cache 10 */ 11 contract RoleManager { 12 PermissionsUpgradable private permUpgradable; 13 14 struct RoleDetails { 15 string roleId; 16 string orgId; 17 uint256 baseAccess; 18 bool isVoter; 19 bool isAdmin; 20 bool active; 21 } 22 23 RoleDetails[] private roleList; 24 mapping(bytes32 => uint256) private roleIndex; 25 uint256 private numberOfRoles; 26 27 event RoleCreated(string _roleId, string _orgId, uint256 _baseAccess, 28 bool _isVoter, bool _isAdmin); 29 event RoleRevoked(string _roleId, string _orgId); 30 31 /** @notice confirms that the caller is the address of implementation 32 contract 33 */ 34 modifier onlyImplementation { 35 require(msg.sender == permUpgradable.getPermImpl(), "invalid caller"); 36 _; 37 } 38 39 /** @notice constructor. sets the permissions upgradable address 40 */ 41 constructor (address _permUpgradable) public { 42 permUpgradable = PermissionsUpgradable(_permUpgradable); 43 } 44 45 /** @notice function to add a new role definition to an organization 46 * @param _roleId - unique identifier for the role being added 47 * @param _orgId - org id to which the role belongs 48 * @param _baseAccess - can be from 0 to 7 49 * @param _isVoter - bool to indicate if voter role or not 50 * @param _isAdmin - bool to indicate if admin role or not 51 * @dev base access can have any of the following values: 52 0 - Read only 53 1 - value transfer 54 2 - contract deploy 55 3 - full access 56 4 - contract call 57 5 - value transfer and contract call 58 6 - value transfer and contract deploy 59 7 - contract call and deploy 60 */ 61 function addRole(string memory _roleId, string memory _orgId, uint256 _baseAccess, 62 bool _isVoter, bool _isAdmin) public onlyImplementation { 63 require(_baseAccess < 8, "invalid access value"); 64 // Check if account already exists 65 require(roleIndex[keccak256(abi.encode(_roleId, _orgId))] == 0, "role exists for the org"); 66 numberOfRoles ++; 67 roleIndex[keccak256(abi.encode(_roleId, _orgId))] = numberOfRoles; 68 roleList.push(RoleDetails(_roleId, _orgId, _baseAccess, _isVoter, _isAdmin, true)); 69 emit RoleCreated(_roleId, _orgId, _baseAccess, _isVoter, _isAdmin); 70 71 } 72 73 /** @notice function to remove an existing role definition from an organization 74 * @param _roleId - unique identifier for the role being added 75 * @param _orgId - org id to which the role belongs 76 */ 77 function removeRole(string calldata _roleId, string calldata _orgId) external 78 onlyImplementation { 79 require(roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0, "role does not exist"); 80 uint256 rIndex = _getRoleIndex(_roleId, _orgId); 81 roleList[rIndex].active = false; 82 emit RoleRevoked(_roleId, _orgId); 83 } 84 85 /** @notice checks if the role is a voter role or not 86 * @param _roleId - unique identifier for the role being added 87 * @param _orgId - org id to which the role belongs 88 * @param _ultParent - master org id 89 * @return true or false 90 * @dev checks for the role existence in the passed org and master org 91 */ 92 function isVoterRole(string calldata _roleId, string calldata _orgId, 93 string calldata _ultParent) external view onlyImplementation returns (bool){ 94 if (!(roleExists(_roleId, _orgId, _ultParent))) { 95 return false; 96 } 97 uint256 rIndex; 98 if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) { 99 rIndex = _getRoleIndex(_roleId, _orgId); 100 } 101 else { 102 rIndex = _getRoleIndex(_roleId, _ultParent); 103 } 104 return (roleList[rIndex].active && roleList[rIndex].isVoter); 105 } 106 107 /** @notice checks if the role is an admin role or not 108 * @param _roleId - unique identifier for the role being added 109 * @param _orgId - org id to which the role belongs 110 * @param _ultParent - master org id 111 * @return true or false 112 * @dev checks for the role existence in the passed org and master org 113 */ 114 function isAdminRole(string calldata _roleId, string calldata _orgId, 115 string calldata _ultParent) external view onlyImplementation returns (bool){ 116 if (!(roleExists(_roleId, _orgId, _ultParent))) { 117 return false; 118 } 119 uint256 rIndex; 120 if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) { 121 rIndex = _getRoleIndex(_roleId, _orgId); 122 } 123 else { 124 rIndex = _getRoleIndex(_roleId, _ultParent); 125 } 126 return (roleList[rIndex].active && roleList[rIndex].isAdmin); 127 } 128 129 /** @notice returns the role details for a passed role id and org 130 * @param _roleId - unique identifier for the role being added 131 * @param _orgId - org id to which the role belongs 132 * @return role id 133 * @return org id 134 * @return access type 135 * @return bool to indicate if the role is a voter role 136 * @return bool to indicate if the role is active 137 */ 138 function getRoleDetails(string calldata _roleId, string calldata _orgId) 139 external view returns (string memory roleId, string memory orgId, 140 uint256 accessType, bool voter, bool admin, bool active) { 141 if (!(roleExists(_roleId, _orgId, ""))) { 142 return (_roleId, "", 0, false, false, false); 143 } 144 uint256 rIndex = _getRoleIndex(_roleId, _orgId); 145 return (roleList[rIndex].roleId, roleList[rIndex].orgId, 146 roleList[rIndex].baseAccess, roleList[rIndex].isVoter, 147 roleList[rIndex].isAdmin, roleList[rIndex].active); 148 } 149 150 /** @notice returns the role details for a passed role index 151 * @param _rIndex - unique identifier for the role being added 152 * @return role id 153 * @return org id 154 * @return access type 155 * @return bool to indicate if the role is a voter role 156 * @return bool to indicate if the role is active 157 */ 158 function getRoleDetailsFromIndex(uint256 _rIndex) external view returns 159 (string memory roleId, string memory orgId, uint256 accessType, 160 bool voter, bool admin, bool active) { 161 return (roleList[_rIndex].roleId, roleList[_rIndex].orgId, 162 roleList[_rIndex].baseAccess, roleList[_rIndex].isVoter, 163 roleList[_rIndex].isAdmin, roleList[_rIndex].active); 164 } 165 166 /** @notice returns the total number of roles in the network 167 * @return total number of roles 168 */ 169 function getNumberOfRoles() external view returns (uint256) { 170 return roleList.length; 171 } 172 173 /** @notice checks if the role exists for the given org or master org 174 * @param _roleId - unique identifier for the role being added 175 * @param _orgId - org id to which the role belongs 176 * @param _ultParent - master org id 177 * @return true or false 178 */ 179 function roleExists(string memory _roleId, string memory _orgId, 180 string memory _ultParent) public view returns (bool) { 181 uint256 id; 182 if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) { 183 id = _getRoleIndex(_roleId, _orgId); 184 return roleList[id].active; 185 } 186 else if (roleIndex[keccak256(abi.encode(_roleId, _ultParent))] != 0) { 187 id = _getRoleIndex(_roleId, _ultParent); 188 return roleList[id].active; 189 } 190 return false; 191 } 192 193 function roleAccess(string memory _roleId, string memory _orgId, 194 string memory _ultParent) public view returns (uint256) { 195 uint256 id; 196 if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) { 197 id = _getRoleIndex(_roleId, _orgId); 198 return roleList[id].baseAccess; 199 } 200 else if (roleIndex[keccak256(abi.encode(_roleId, _ultParent))] != 0) { 201 id = _getRoleIndex(_roleId, _ultParent); 202 return roleList[id].baseAccess; 203 } 204 return 0; 205 } 206 207 function transactionAllowed(string calldata _roleId, string calldata _orgId, 208 string calldata _ultParent, uint256 _typeOfTxn) external view returns (bool) { 209 uint256 access = roleAccess(_roleId, _orgId, _ultParent); 210 211 if (access == 3) { 212 return true; 213 } 214 if (_typeOfTxn == 1 && (access == 1 || access == 5 || access == 6)){ 215 return true; 216 } 217 if (_typeOfTxn == 2 && (access == 2 || access == 6 || access == 7)){ 218 return true; 219 } 220 if (_typeOfTxn == 3 && (access == 4 || access == 5 || access == 7)){ 221 return true; 222 } 223 224 return false; 225 } 226 227 /** @notice returns the role index based on role id and org id 228 * @param _roleId - role id 229 * @param _orgId - org id 230 * @return role index 231 */ 232 function _getRoleIndex(string memory _roleId, string memory _orgId) 233 internal view returns (uint256) { 234 return roleIndex[keccak256(abi.encode(_roleId, _orgId))] - 1; 235 } 236 }