pragma solidity ^0.5.3; import "./RoleManager.sol"; import "./AccountManager.sol"; import "./VoterManager.sol"; import "./NodeManager.sol"; import "./OrgManager.sol"; import "./PermissionsUpgradable.sol"; contract PermissionsImplementation { AccountManager private accounts; RoleManager private roles; VoterManager private voter; NodeManager private nodes; OrgManager private org; PermissionsUpgradable private permUpgradable; string private adminOrg; string private adminRole; string private orgAdminRole; uint private fullAccess = 3; // checks if first time network boot up has happened or not bool private networkBoot = false; modifier onlyProxy { require(msg.sender == permUpgradable.getPermInterface(), "can be called by proxy only"); _; } // Modifiers // Checks if the given network boot up is pending exists modifier networkBootStatus(bool _status) { require(networkBoot == _status, "Incorrect network boot status"); _; } modifier networkAdmin(address _account) { require(isNetworkAdmin(_account) == true, "Not an network admin"); _; } modifier orgAdmin(address _account, string memory _orgId) { require(isOrgAdmin(_account, _orgId) == true, "Not an org admin"); _; } modifier orgNotExists(string memory _orgId) { require(checkOrgExists(_orgId) != true, "Org already exists"); _; } modifier orgExists(string memory _orgId) { require(checkOrgExists(_orgId) == true, "Org does not exists"); _; } modifier orgApproved(string memory _orgId) { require(checkOrgApproved(_orgId) == true, "Org not approved"); _; } constructor (address _permUpgradable) public { permUpgradable = PermissionsUpgradable(_permUpgradable); } // initial set up related functions // set policy related attributes function setPolicy(string calldata _nwAdminOrg, string calldata _nwAdminRole, string calldata _oAdminRole) external onlyProxy networkBootStatus(false) { adminOrg = _nwAdminOrg; adminRole = _nwAdminRole; orgAdminRole = _oAdminRole; } function init(address _orgManager, address _rolesManager, address _acctManager, address _voterManager, address _nodeManager) external onlyProxy networkBootStatus(false) { org = OrgManager(_orgManager); roles = RoleManager(_rolesManager); accounts = AccountManager(_acctManager); voter = VoterManager(_voterManager); nodes = NodeManager(_nodeManager); org.addAdminOrg(adminOrg); roles.addRole(adminRole, adminOrg, fullAccess, true); accounts.setDefaults(adminRole, orgAdminRole); } function addAdminNodes(string calldata _enodeId) external onlyProxy networkBootStatus(false) { nodes.addAdminNode(_enodeId, adminOrg); } function addAdminAccounts(address _acct) external onlyProxy networkBootStatus(false) { // add the account as a voter for the admin org updateVoterList(adminOrg, _acct, true); // add the account as an account with full access into the admin org accounts.addNWAdminAccount(_acct, adminOrg); } // update the network boot status as true function updateNetworkBootStatus() external onlyProxy networkBootStatus(false) returns (bool) { networkBoot = true; return networkBoot; } function addOrg(string calldata _orgId, string calldata _enodeId, address _account, address _caller) external onlyProxy networkBootStatus(true) networkAdmin(_caller) { voter.addVotingItem(adminOrg, _orgId, _enodeId, _account, 1); org.addOrg(_orgId); nodes.addNode(_enodeId, _orgId); require(validateAccount(_account, _orgId) == true, "Operation cannot be performed"); accounts.assignAccountRole(_account, _orgId, orgAdminRole); } function approveOrg(string calldata _orgId, string calldata _enodeId, address _account, address _caller) external onlyProxy networkAdmin(_caller) { require(checkOrgStatus(_orgId, 1) == true, "Nothing to approve"); if ((processVote(adminOrg, _caller, 1))) { org.approveOrg(_orgId); roles.addRole(orgAdminRole, _orgId, fullAccess, true); nodes.approveNode(_enodeId, _orgId); accounts.approveOrgAdminAccount(_account); } } // function for adding a new master org function addSubOrg(string calldata _pOrg, string calldata _orgId, string calldata _enodeId, address _account, address _caller) external orgExists(_pOrg) orgAdmin(_caller, _pOrg) { org.addSubOrg(_pOrg, _orgId); string memory pid = string(abi.encodePacked(_pOrg, ".", _orgId)); if (bytes(_enodeId).length > 0) { nodes.addNode(_enodeId, pid); } if (_account != address(0)) { require(validateAccount(_account, pid) == true, "Operation cannot be performed"); accounts.assignAccountRole(_account, pid, orgAdminRole); } } function updateOrgStatus(string calldata _orgId, uint _status, address _caller) external onlyProxy networkAdmin(_caller) { uint pendingOp; pendingOp = org.updateOrg(_orgId, _status); voter.addVotingItem(adminOrg, _orgId, "", address(0), pendingOp); } function approveOrgStatus(string calldata _orgId, uint _status, address _caller) external onlyProxy networkAdmin(_caller) { require((_status == 3 || _status == 5), "Operation not allowed"); uint pendingOp; if (_status == 3) { pendingOp = 2; } else if (_status == 5) { pendingOp = 3; } require(checkOrgStatus(_orgId, _status) == true, "Operation not allowed"); if ((processVote(adminOrg, _caller, pendingOp))) { org.approveOrgStatusUpdate(_orgId, _status); } } // Role related functions function addNewRole(string calldata _roleId, string calldata _orgId, uint _access, bool _voter, address _caller) external onlyProxy orgApproved(_orgId) orgAdmin(_caller, _orgId) { //add new roles can be created by org admins only roles.addRole(_roleId, _orgId, _access, _voter); } function removeRole(string calldata _roleId, string calldata _orgId, address _caller) external onlyProxy orgApproved(_orgId) orgAdmin(_caller, _orgId) { require(((keccak256(abi.encodePacked(_roleId)) != keccak256(abi.encodePacked(adminRole))) && (keccak256(abi.encodePacked(_roleId)) != keccak256(abi.encodePacked(orgAdminRole)))), "Admin roles cannot be removed"); roles.removeRole(_roleId, _orgId); } // Account related functions function assignOrgAdminAccount(string calldata _orgId, address _account, address _caller) external onlyProxy orgExists(_orgId) networkAdmin(_caller) { require(validateAccount(_account, _orgId) == true, "Operation cannot be performed"); // check if orgAdmin already exists if yes then op cannot be performed require(checkOrgAdminExists(_orgId) != true, "org admin exists"); // assign the account org admin role and propose voting accounts.assignAccountRole(_account, _orgId, orgAdminRole); //add voting item voter.addVotingItem(adminOrg, _orgId, "", _account, 4); } function approveOrgAdminAccount(address _account, address _caller) external onlyProxy networkAdmin(_caller) { require(isNetworkAdmin(_caller) == true, "can be called from network admin only"); if ((processVote(adminOrg, _caller, 4))) { accounts.approveOrgAdminAccount(_account); } } function assignAccountRole(address _acct, string memory _orgId, string memory _roleId, address _caller) public onlyProxy orgAdmin(_caller, _orgId) orgApproved(_orgId) { require(validateAccount(_acct, _orgId) == true, "Operation cannot be performed"); require(roleExists(_roleId, _orgId) == true, "role does not exists"); accounts.assignAccountRole(_acct, _orgId, _roleId); } // Node related functions function addNode(string calldata _orgId, string calldata _enodeId, address _caller) external onlyProxy orgApproved(_orgId) orgAdmin(_caller, _orgId) { // check that the node is not part of another org nodes.addOrgNode(_enodeId, _orgId); } function updateNodeStatus(string calldata _orgId, string calldata _enodeId, uint _status, address _caller) external onlyProxy orgExists(_orgId) orgAdmin(_caller, _orgId) { nodes.updateNodeStatus(_enodeId, _orgId, _status); } // Get network boot status function getNetworkBootStatus() external view returns (bool) { return networkBoot; } // Voter related functions function updateVoterList(string memory _orgId, address _account, bool _add) internal { if (_add) { voter.addVoter(_orgId, _account); } else { voter.deleteVoter(_orgId, _account); } } function processVote(string memory _orgId, address _caller, uint _pendingOp) internal returns (bool) { return voter.processVote(_orgId, _caller, _pendingOp); } function getPendingOp(string calldata _orgId) external view returns (string memory, string memory, address, uint) { return voter.getPendingOpDetails(_orgId); } // helper functions function isNetworkAdmin(address _account) public view returns (bool) { return (keccak256(abi.encodePacked(accounts.getAccountRole(_account))) == keccak256(abi.encodePacked(adminRole))); } function isOrgAdmin(address _account, string memory _orgId) public view returns (bool) { return (accounts.checkOrgAdmin(_account, _orgId, getUltimateParent(_orgId))); } function validateAccount(address _account, string memory _orgId) public view returns (bool) { return (accounts.valAcctAccessChange(_account, _orgId, getUltimateParent(_orgId))); } function checkOrgExists(string memory _orgId) internal view returns (bool) { return org.checkOrgExists(_orgId); } function checkOrgApproved(string memory _orgId) internal view returns (bool) { return org.checkOrgStatus(_orgId, 2); } function checkOrgStatus(string memory _orgId, uint _status) internal view returns (bool) { return org.checkOrgStatus(_orgId, _status); } function checkOrgAdminExists(string memory _orgId) internal view returns (bool) { return accounts.orgAdminExists(_orgId); } function roleExists(string memory _roleId, string memory _orgId) internal view returns (bool) { return roles.roleExists(_roleId, _orgId, org.getUltimateParent(_orgId)); } function isVoterRole(string memory _roleId, string memory _orgId) internal view returns (bool) { return roles.isVoterRole(_roleId, _orgId, getUltimateParent(_orgId)); } function getUltimateParent(string memory _orgId) internal view returns (string memory) { return org.getUltimateParent(_orgId); } }