2019-03-14 23:41:04 -07:00
|
|
|
pragma solidity ^0.5.3;
|
2019-05-08 20:07:54 -07:00
|
|
|
|
2019-03-15 02:26:57 -07:00
|
|
|
import "./PermissionsUpgradable.sol";
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @title Role manager contract
|
|
|
|
* @notice This contract holds implementation logic for all role management
|
|
|
|
functionality. This can be called only by the implementation
|
|
|
|
contract only. there are few view functions exposed as public and
|
|
|
|
can be called directly. these are invoked by quorum for populating
|
|
|
|
permissions data in cache
|
|
|
|
*/
|
2019-03-14 23:41:04 -07:00
|
|
|
contract RoleManager {
|
2019-03-19 02:15:51 -07:00
|
|
|
PermissionsUpgradable private permUpgradable;
|
2019-05-08 20:07:54 -07:00
|
|
|
|
2019-03-14 23:41:04 -07:00
|
|
|
struct RoleDetails {
|
|
|
|
string roleId;
|
|
|
|
string orgId;
|
2019-07-21 20:25:14 -07:00
|
|
|
uint256 baseAccess;
|
2019-03-14 23:41:04 -07:00
|
|
|
bool isVoter;
|
2019-04-26 01:35:51 -07:00
|
|
|
bool isAdmin;
|
2019-03-14 23:41:04 -07:00
|
|
|
bool active;
|
|
|
|
}
|
|
|
|
|
|
|
|
RoleDetails[] private roleList;
|
2019-07-21 20:25:14 -07:00
|
|
|
mapping(bytes32 => uint256) private roleIndex;
|
|
|
|
uint256 private numberOfRoles;
|
2019-03-14 23:41:04 -07:00
|
|
|
|
2019-07-21 20:25:14 -07:00
|
|
|
event RoleCreated(string _roleId, string _orgId, uint256 _baseAccess,
|
2019-07-19 01:16:50 -07:00
|
|
|
bool _isVoter, bool _isAdmin);
|
2019-03-14 23:41:04 -07:00
|
|
|
event RoleRevoked(string _roleId, string _orgId);
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice confirms that the caller is the address of implementation
|
|
|
|
contract
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
modifier onlyImplementation {
|
2019-07-21 20:17:39 -07:00
|
|
|
require(msg.sender == permUpgradable.getPermImpl(), "invalid caller");
|
2019-03-15 02:26:57 -07:00
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice constructor. sets the permissions upgradable address
|
|
|
|
*/
|
2019-03-15 02:26:57 -07:00
|
|
|
constructor (address _permUpgradable) public {
|
2019-03-19 02:15:51 -07:00
|
|
|
permUpgradable = PermissionsUpgradable(_permUpgradable);
|
2019-03-15 02:26:57 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice function to add a new role definition to an organization
|
|
|
|
* @param _roleId - unique identifier for the role being added
|
|
|
|
* @param _orgId - org id to which the role belongs
|
|
|
|
* @param _baseAccess - 0-ReadOnly, 1-Transact, 2-ContractDeply, 3- Full
|
|
|
|
* @param _isVoter - bool to indicate if voter role or not
|
|
|
|
* @param _isAdmin - bool to indicate if admin role or not
|
|
|
|
* @dev base access can have any of the following values:
|
|
|
|
0 - Read only
|
|
|
|
1 - Transact only
|
|
|
|
2 - Contract deploy. can transact as well
|
|
|
|
3 - Full access
|
|
|
|
*/
|
2019-07-21 20:25:14 -07:00
|
|
|
function addRole(string memory _roleId, string memory _orgId, uint256 _baseAccess,
|
2019-07-19 01:16:50 -07:00
|
|
|
bool _isVoter, bool _isAdmin) public onlyImplementation {
|
2019-03-14 23:41:04 -07:00
|
|
|
// Check if account already exists
|
2019-07-21 20:17:39 -07:00
|
|
|
require(roleIndex[keccak256(abi.encode(_roleId, _orgId))] == 0, "role exists for the org");
|
|
|
|
numberOfRoles ++;
|
|
|
|
roleIndex[keccak256(abi.encode(_roleId, _orgId))] = numberOfRoles;
|
|
|
|
roleList.push(RoleDetails(_roleId, _orgId, _baseAccess, _isVoter, _isAdmin, true));
|
|
|
|
emit RoleCreated(_roleId, _orgId, _baseAccess, _isVoter, _isAdmin);
|
|
|
|
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice function to remove an existing role definition from an organization
|
|
|
|
* @param _roleId - unique identifier for the role being added
|
|
|
|
* @param _orgId - org id to which the role belongs
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
function removeRole(string calldata _roleId, string calldata _orgId) external
|
|
|
|
onlyImplementation {
|
2019-07-21 20:17:39 -07:00
|
|
|
require(roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0, "role does not exist");
|
2019-07-21 20:25:14 -07:00
|
|
|
uint256 rIndex = _getRoleIndex(_roleId, _orgId);
|
2019-07-21 20:17:39 -07:00
|
|
|
roleList[rIndex].active = false;
|
|
|
|
emit RoleRevoked(_roleId, _orgId);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice checks if the role is a voter role or not
|
|
|
|
* @param _roleId - unique identifier for the role being added
|
|
|
|
* @param _orgId - org id to which the role belongs
|
|
|
|
* @param _ultParent - master org id
|
|
|
|
* @return true or false
|
|
|
|
* @dev checks for the role existence in the passed org and master org
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
function isVoterRole(string calldata _roleId, string calldata _orgId,
|
|
|
|
string calldata _ultParent) external view onlyImplementation returns (bool){
|
2019-04-09 20:10:35 -07:00
|
|
|
if (!(roleExists(_roleId, _orgId, _ultParent))) {
|
2019-03-14 23:41:04 -07:00
|
|
|
return false;
|
|
|
|
}
|
2019-07-21 20:25:14 -07:00
|
|
|
uint256 rIndex;
|
2019-07-19 01:16:50 -07:00
|
|
|
if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) {
|
|
|
|
rIndex = _getRoleIndex(_roleId, _orgId);
|
2019-04-09 20:10:35 -07:00
|
|
|
}
|
|
|
|
else {
|
2019-07-19 01:16:50 -07:00
|
|
|
rIndex = _getRoleIndex(_roleId, _ultParent);
|
2019-04-09 20:10:35 -07:00
|
|
|
}
|
2019-07-19 01:16:50 -07:00
|
|
|
return (roleList[rIndex].active && roleList[rIndex].isVoter);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice checks if the role is an admin role or not
|
|
|
|
* @param _roleId - unique identifier for the role being added
|
|
|
|
* @param _orgId - org id to which the role belongs
|
|
|
|
* @param _ultParent - master org id
|
|
|
|
* @return true or false
|
|
|
|
* @dev checks for the role existence in the passed org and master org
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
function isAdminRole(string calldata _roleId, string calldata _orgId,
|
|
|
|
string calldata _ultParent) external view onlyImplementation returns (bool){
|
2019-04-09 20:10:35 -07:00
|
|
|
if (!(roleExists(_roleId, _orgId, _ultParent))) {
|
2019-03-14 23:41:04 -07:00
|
|
|
return false;
|
|
|
|
}
|
2019-07-21 20:25:14 -07:00
|
|
|
uint256 rIndex;
|
2019-07-19 01:16:50 -07:00
|
|
|
if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) {
|
|
|
|
rIndex = _getRoleIndex(_roleId, _orgId);
|
2019-04-09 20:10:35 -07:00
|
|
|
}
|
|
|
|
else {
|
2019-07-19 01:16:50 -07:00
|
|
|
rIndex = _getRoleIndex(_roleId, _ultParent);
|
2019-04-09 20:10:35 -07:00
|
|
|
}
|
2019-07-19 01:16:50 -07:00
|
|
|
return (roleList[rIndex].active && roleList[rIndex].isAdmin);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice returns the role details for a passed role id and org
|
|
|
|
* @param _roleId - unique identifier for the role being added
|
|
|
|
* @param _orgId - org id to which the role belongs
|
|
|
|
* @return role id
|
|
|
|
* @return org id
|
|
|
|
* @return access type
|
|
|
|
* @return bool to indicate if the role is a voter role
|
|
|
|
* @return bool to indicate if the role is active
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
function getRoleDetails(string calldata _roleId, string calldata _orgId)
|
|
|
|
external view returns (string memory roleId, string memory orgId,
|
2019-07-30 01:56:44 -07:00
|
|
|
uint256 accessType, bool voter, bool admin, bool active) {
|
2019-07-19 01:16:50 -07:00
|
|
|
if (!(roleExists(_roleId, _orgId, ""))) {
|
2019-07-30 01:56:44 -07:00
|
|
|
return (_roleId, "", 0, false, false, false);
|
2019-04-26 01:35:51 -07:00
|
|
|
}
|
2019-07-21 20:25:14 -07:00
|
|
|
uint256 rIndex = _getRoleIndex(_roleId, _orgId);
|
2019-07-19 01:16:50 -07:00
|
|
|
return (roleList[rIndex].roleId, roleList[rIndex].orgId,
|
2019-07-30 01:56:44 -07:00
|
|
|
roleList[rIndex].baseAccess, roleList[rIndex].isVoter,
|
|
|
|
roleList[rIndex].isAdmin, roleList[rIndex].active);
|
2019-07-19 01:16:50 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice returns the role details for a passed role index
|
|
|
|
* @param _rIndex - unique identifier for the role being added
|
|
|
|
* @return role id
|
|
|
|
* @return org id
|
|
|
|
* @return access type
|
|
|
|
* @return bool to indicate if the role is a voter role
|
|
|
|
* @return bool to indicate if the role is active
|
|
|
|
*/
|
2019-07-21 20:25:14 -07:00
|
|
|
function getRoleDetailsFromIndex(uint256 _rIndex) external view returns
|
|
|
|
(string memory roleId, string memory orgId, uint256 accessType,
|
2019-07-19 01:16:50 -07:00
|
|
|
bool voter, bool admin, bool active) {
|
|
|
|
return (roleList[_rIndex].roleId, roleList[_rIndex].orgId,
|
|
|
|
roleList[_rIndex].baseAccess, roleList[_rIndex].isVoter,
|
|
|
|
roleList[_rIndex].isAdmin, roleList[_rIndex].active);
|
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice returns the total number of roles in the network
|
|
|
|
* @return total number of roles
|
|
|
|
*/
|
2019-07-21 20:25:14 -07:00
|
|
|
function getNumberOfRoles() external view returns (uint256) {
|
2019-07-19 01:16:50 -07:00
|
|
|
return roleList.length;
|
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice checks if the role exists for the given org or master org
|
|
|
|
* @param _roleId - unique identifier for the role being added
|
|
|
|
* @param _orgId - org id to which the role belongs
|
|
|
|
* @param _ultParent - master org id
|
|
|
|
* @return true or false
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
function roleExists(string memory _roleId, string memory _orgId,
|
|
|
|
string memory _ultParent) public view returns (bool) {
|
2019-07-21 20:25:14 -07:00
|
|
|
uint256 id;
|
2019-07-19 01:16:50 -07:00
|
|
|
if (roleIndex[keccak256(abi.encode(_roleId, _orgId))] != 0) {
|
|
|
|
id = _getRoleIndex(_roleId, _orgId);
|
|
|
|
return roleList[id].active;
|
2019-04-26 01:35:51 -07:00
|
|
|
}
|
2019-07-19 01:16:50 -07:00
|
|
|
else if (roleIndex[keccak256(abi.encode(_roleId, _ultParent))] != 0) {
|
|
|
|
id = _getRoleIndex(_roleId, _ultParent);
|
|
|
|
return roleList[id].active;
|
2019-04-26 01:35:51 -07:00
|
|
|
}
|
2019-07-19 01:16:50 -07:00
|
|
|
return false;
|
2019-04-26 01:35:51 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 01:56:44 -07:00
|
|
|
/** @notice returns the role index based on role id and org id
|
|
|
|
* @param _roleId - role id
|
|
|
|
* @param _orgId - org id
|
|
|
|
* @return role index
|
|
|
|
*/
|
2019-07-19 01:16:50 -07:00
|
|
|
function _getRoleIndex(string memory _roleId, string memory _orgId)
|
2019-07-21 20:25:14 -07:00
|
|
|
internal view returns (uint256) {
|
2019-07-19 01:16:50 -07:00
|
|
|
return roleIndex[keccak256(abi.encode(_roleId, _orgId))] - 1;
|
|
|
|
}
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|