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  }