github.com/hyperion-hyn/go-ethereum@v2.4.0+incompatible/permission/contract/OrgManager.sol (about) 1 pragma solidity ^0.5.3; 2 3 import "./PermissionsUpgradable.sol"; 4 /** @title Organization manager contract 5 * @notice This contract holds implementation logic for all org 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 * @dev the status of the organization is denoted by a set of integer 11 values. These are as below: 12 0 - Not in list, 13 1 - Org proposed for approval by network admins 14 2 - Org in Approved status 15 3 - Org proposed for suspension and pending approval by network admins 16 4 - Org in Suspended, 17 Once the node is blacklisted no further activity on the node is 18 possible. 19 */ 20 contract OrgManager { 21 string private adminOrgId; 22 PermissionsUpgradable private permUpgradable; 23 // checks if first time network boot up has happened or not 24 bool private networkBoot = false; 25 26 // variables which control the breadth and depth of the sub org tree 27 uint private DEPTH_LIMIT = 4; 28 uint private BREADTH_LIMIT = 4; 29 struct OrgDetails { 30 string orgId; 31 uint status; 32 string parentId; 33 string fullOrgId; 34 string ultParent; 35 uint pindex; 36 uint level; 37 uint [] subOrgIndexList; 38 } 39 40 OrgDetails [] private orgList; 41 mapping(bytes32 => uint) private OrgIndex; 42 uint private orgNum = 0; 43 44 // events related to Master Org add 45 event OrgApproved(string _orgId, string _porgId, string _ultParent, 46 uint _level, uint _status); 47 event OrgPendingApproval(string _orgId, string _porgId, string _ultParent, 48 uint _level, uint _status); 49 event OrgSuspended(string _orgId, string _porgId, string _ultParent, 50 uint _level); 51 event OrgSuspensionRevoked(string _orgId, string _porgId, string _ultParent, 52 uint _level); 53 54 /** @notice confirms that the caller is the address of implementation 55 contract 56 */ 57 modifier onlyImplementation{ 58 require(msg.sender == permUpgradable.getPermImpl(), "invalid caller"); 59 _; 60 } 61 62 /** @notice checks if the org id does not exists 63 * @param _orgId - org id 64 * @return true if org does not exist 65 */ 66 modifier orgDoesNotExist(string memory _orgId) { 67 require(checkOrgExists(_orgId) == false, "org exists"); 68 _; 69 } 70 71 /** @notice checks if the org id does exists 72 * @param _orgId - org id 73 * @return true if org exists 74 */ 75 modifier orgExists(string memory _orgId) { 76 require(checkOrgExists(_orgId) == true, "org does not exist"); 77 _; 78 } 79 80 /** @notice constructor. sets the permissions upgradable address 81 */ 82 constructor (address _permUpgradable) public { 83 permUpgradable = PermissionsUpgradable(_permUpgradable); 84 } 85 86 /** @notice called at the time of network initialization. sets the depth 87 breadth for sub orgs creation. and creates the default network 88 admin org as per config file 89 */ 90 function setUpOrg(string calldata _orgId, uint256 _breadth, uint256 _depth) external 91 onlyImplementation { 92 _addNewOrg("", _orgId, 1, 2); 93 DEPTH_LIMIT = _depth; 94 BREADTH_LIMIT = _breadth; 95 } 96 /** @notice function for adding a new master org to the network 97 * @param _orgId unique org id to be added 98 * @dev org will be added if it does exist 99 */ 100 function addOrg(string calldata _orgId) external 101 onlyImplementation 102 orgDoesNotExist(_orgId) { 103 _addNewOrg("", _orgId, 1, 1); 104 } 105 106 /** @notice function for adding a new sub org under a parent org 107 * @param _pOrgId unique org id to be added 108 * @dev org will be added if it does exist 109 */ 110 function addSubOrg(string calldata _pOrgId, string calldata _orgId) external 111 onlyImplementation 112 orgDoesNotExist(string(abi.encodePacked(_pOrgId, ".", _orgId))) { 113 _addNewOrg(_pOrgId, _orgId, 2, 2); 114 } 115 116 /** @notice updates the status of a master org. 117 * @param _orgId unique org id to be added 118 * @param _action action being performed 119 * @dev status cannot be updated for sub orgs. 120 This function can be called for the following actions: 121 1 - to suspend an org 122 2 - to activate the org back 123 */ 124 function updateOrg(string calldata _orgId, uint256 _action) external 125 onlyImplementation 126 orgExists(_orgId) 127 returns (uint256){ 128 require((_action == 1 || _action == 2), "invalid action. operation not allowed"); 129 uint256 id = _getOrgIndex(_orgId); 130 require(orgList[id].level == 1, "not a master org. operation not allowed"); 131 132 uint256 reqStatus; 133 uint256 pendingOp; 134 if (_action == 1) { 135 reqStatus = 2; 136 pendingOp = 2; 137 } 138 else if (_action == 2) { 139 reqStatus = 4; 140 pendingOp = 3; 141 } 142 require(checkOrgStatus(_orgId, reqStatus) == true, 143 "org status does not allow the operation"); 144 if (_action == 1) { 145 _suspendOrg(_orgId); 146 } 147 else { 148 _revokeOrgSuspension(_orgId); 149 } 150 return pendingOp; 151 } 152 153 /** @notice function to approve org status change for master orgs 154 * @param _orgId unique org id to be added 155 * @param _action approval for action 156 * @dev status cannot be updated for sub orgs. 157 This function can be called for the following actions: 158 1 - to suspend an org 159 2 - to activate the org back 160 */ 161 function approveOrgStatusUpdate(string calldata _orgId, uint256 _action) external 162 onlyImplementation 163 orgExists(_orgId) { 164 if (_action == 1) { 165 _approveOrgSuspension(_orgId); 166 } 167 else { 168 _approveOrgRevokeSuspension(_orgId); 169 } 170 } 171 172 /** @notice function to approve org status change for master orgs 173 * @param _orgId unique org id to be added 174 */ 175 function approveOrg(string calldata _orgId) external 176 onlyImplementation { 177 require(checkOrgStatus(_orgId, 1) == true, "nothing to approve"); 178 uint256 id = _getOrgIndex(_orgId); 179 orgList[id].status = 2; 180 emit OrgApproved(orgList[id].orgId, orgList[id].parentId, 181 orgList[id].ultParent, orgList[id].level, 2); 182 } 183 184 /** @notice returns org info for a given org index 185 * @param _orgIndex org index 186 * @return org id 187 * @return parent org id 188 * @return ultimate parent id 189 * @return level in the org tree 190 * @return status 191 */ 192 function getOrgInfo(uint256 _orgIndex) external view returns (string memory, 193 string memory, string memory, uint256, uint256) { 194 return (orgList[_orgIndex].orgId, orgList[_orgIndex].parentId, 195 orgList[_orgIndex].ultParent, orgList[_orgIndex].level, orgList[_orgIndex].status); 196 } 197 198 /** @notice returns the master org id for the given org or sub org 199 * @param _orgId org id 200 * @return master org id 201 */ 202 function getUltimateParent(string calldata _orgId) external view 203 onlyImplementation 204 returns (string memory) { 205 return orgList[_getOrgIndex(_orgId)].ultParent; 206 } 207 208 /** @notice returns the total number of orgs in the network 209 * @return master org id 210 */ 211 function getNumberOfOrgs() public view returns (uint256) { 212 return orgList.length; 213 } 214 215 /** @notice confirms that org status is same as passed status 216 * @param _orgId org id 217 * @param _orgStatus org status 218 * @return true or false 219 */ 220 function checkOrgStatus(string memory _orgId, uint256 _orgStatus) 221 public view returns (bool){ 222 uint256 id = _getOrgIndex(_orgId); 223 return ((OrgIndex[keccak256(abi.encodePacked(_orgId))] != 0) 224 && orgList[id].status == _orgStatus); 225 } 226 227 /** @notice confirms if the org exists in the network 228 * @param _orgId org id 229 * @return true or false 230 */ 231 function checkOrgExists(string memory _orgId) public view returns (bool) { 232 return (!(OrgIndex[keccak256(abi.encodePacked(_orgId))] == 0)); 233 } 234 235 /** @notice updates the org status to suspended 236 * @param _orgId org id 237 */ 238 function _suspendOrg(string memory _orgId) internal { 239 require(checkOrgStatus(_orgId, 2) == true, 240 "org not in approved status. operation cannot be done"); 241 uint256 id = _getOrgIndex(_orgId); 242 orgList[id].status = 3; 243 emit OrgPendingApproval(orgList[id].orgId, orgList[id].parentId, 244 orgList[id].ultParent, orgList[id].level, 3); 245 } 246 247 /** @notice revokes the suspension of an org 248 * @param _orgId org id 249 */ 250 function _revokeOrgSuspension(string memory _orgId) internal { 251 require(checkOrgStatus(_orgId, 4) == true, "org not in suspended state"); 252 uint256 id = _getOrgIndex(_orgId); 253 orgList[id].status = 5; 254 emit OrgPendingApproval(orgList[id].orgId, orgList[id].parentId, 255 orgList[id].ultParent, orgList[id].level, 5); 256 } 257 258 /** @notice approval function for org suspension activity 259 * @param _orgId org id 260 */ 261 function _approveOrgSuspension(string memory _orgId) internal { 262 require(checkOrgStatus(_orgId, 3) == true, "nothing to approve"); 263 uint256 id = _getOrgIndex(_orgId); 264 orgList[id].status = 4; 265 emit OrgSuspended(orgList[id].orgId, orgList[id].parentId, 266 orgList[id].ultParent, orgList[id].level); 267 } 268 269 /** @notice approval function for revoking org suspension 270 * @param _orgId org id 271 */ 272 function _approveOrgRevokeSuspension(string memory _orgId) internal { 273 require(checkOrgStatus(_orgId, 5) == true, "nothing to approve"); 274 uint256 id = _getOrgIndex(_orgId); 275 orgList[id].status = 2; 276 emit OrgSuspensionRevoked(orgList[id].orgId, orgList[id].parentId, 277 orgList[id].ultParent, orgList[id].level); 278 } 279 280 /** @notice function to add a new organization 281 * @param _pOrgId parent org id 282 * @param _orgId org id 283 * @param _level level in org hierarchy 284 * @param _status status of the org 285 */ 286 function _addNewOrg(string memory _pOrgId, string memory _orgId, 287 uint256 _level, uint _status) internal { 288 bytes32 pid = ""; 289 bytes32 oid = ""; 290 uint256 parentIndex = 0; 291 292 if (_level == 1) {//root 293 oid = keccak256(abi.encodePacked(_orgId)); 294 } else { 295 pid = keccak256(abi.encodePacked(_pOrgId)); 296 oid = keccak256(abi.encodePacked(_pOrgId, ".", _orgId)); 297 } 298 orgNum++; 299 OrgIndex[oid] = orgNum; 300 uint256 id = orgList.length++; 301 if (_level == 1) { 302 orgList[id].level = _level; 303 orgList[id].pindex = 0; 304 orgList[id].fullOrgId = _orgId; 305 orgList[id].ultParent = _orgId; 306 } else { 307 parentIndex = OrgIndex[pid] - 1; 308 309 require(orgList[parentIndex].subOrgIndexList.length < BREADTH_LIMIT, 310 "breadth level exceeded"); 311 require(orgList[parentIndex].level < DEPTH_LIMIT, 312 "depth level exceeded"); 313 314 orgList[id].level = orgList[parentIndex].level + 1; 315 orgList[id].pindex = parentIndex; 316 orgList[id].ultParent = orgList[parentIndex].ultParent; 317 uint256 subOrgId = orgList[parentIndex].subOrgIndexList.length++; 318 orgList[parentIndex].subOrgIndexList[subOrgId] = id; 319 orgList[id].fullOrgId = string(abi.encodePacked(_pOrgId, ".", _orgId)); 320 } 321 orgList[id].orgId = _orgId; 322 orgList[id].parentId = _pOrgId; 323 orgList[id].status = _status; 324 if (_status == 1) { 325 emit OrgPendingApproval(orgList[id].orgId, orgList[id].parentId, 326 orgList[id].ultParent, orgList[id].level, 1); 327 } 328 else { 329 emit OrgApproved(orgList[id].orgId, orgList[id].parentId, 330 orgList[id].ultParent, orgList[id].level, 2); 331 } 332 } 333 334 /** @notice returns the org index from the org list for the given org 335 * @return org index 336 */ 337 function _getOrgIndex(string memory _orgId) public view returns (uint){ 338 return OrgIndex[keccak256(abi.encodePacked(_orgId))] - 1; 339 } 340 341 }