quorum/controls/permission/AccountManager.sol

193 lines
7.1 KiB
Solidity

pragma solidity ^0.5.3;
import "./PermissionsUpgradable.sol";
contract AccountManager {
PermissionsUpgradable private permUpgradable;
// enum AccountStatus {0-NotInList, 1-PendingApproval, 2-Active, 3-Inactive}
struct AccountAccessDetails {
address acctId;
string orgId;
string role;
uint status;
bool orgAdmin;
}
AccountAccessDetails[] private acctAccessList;
mapping(address => uint) private accountIndex;
uint private numberOfAccts;
string private adminRole;
string private orgAdminRole;
mapping(bytes32 => address) private orgAdminIndex;
// account permission events
event AccountAccessModified(address _address, string _orgId, string _roleId, bool _orgAdmin, uint _status);
event AccountAccessRevoked(address _address, string _orgId, string _roleId, bool _orgAdmin);
modifier onlyImpl
{
require(msg.sender == permUpgradable.getPermImpl());
_;
}
constructor (address _permUpgradable) public {
permUpgradable = PermissionsUpgradable(_permUpgradable);
}
// Get account details given index
function orgAdminExists(string memory _orgId) public view returns (bool)
{
return (orgAdminIndex[keccak256(abi.encodePacked(_orgId))] != address(0));
}
function getAccountStatus(address _acct) internal view returns (uint)
{
if (accountIndex[_acct] == 0) {
return 0;
}
uint aIndex = getAcctIndex(_acct);
return (acctAccessList[aIndex].status);
}
function getAccountDetails(address _acct) external view returns (address, string memory, string memory, uint, bool)
{
if (accountIndex[_acct] == 0) {
return (_acct, "NONE", "", 0, false);
}
uint aIndex = getAcctIndex(_acct);
return (acctAccessList[aIndex].acctId, acctAccessList[aIndex].orgId, acctAccessList[aIndex].role, acctAccessList[aIndex].status, acctAccessList[aIndex].orgAdmin);
}
function getAccountDetailsFromIndex(uint aIndex) external view returns (address, string memory, string memory, uint, bool)
{
return (acctAccessList[aIndex].acctId, acctAccessList[aIndex].orgId, acctAccessList[aIndex].role, acctAccessList[aIndex].status, acctAccessList[aIndex].orgAdmin);
}
// Get number of accounts
function getNumberOfAccounts() external view returns (uint)
{
return acctAccessList.length;
}
function setDefaults(string calldata _nwAdminRole, string calldata _oAdminRole) external
{
adminRole = _nwAdminRole;
orgAdminRole = _oAdminRole;
}
function setAccountRole(address _address, string memory _orgId, string memory _roleId, uint _status, bool _oAdmin) internal
{
// Check if account already exists
uint aIndex = getAcctIndex(_address);
if (accountIndex[_address] != 0) {
acctAccessList[aIndex].role = _roleId;
acctAccessList[aIndex].status = _status;
acctAccessList[aIndex].orgAdmin = _oAdmin;
}
else {
numberOfAccts ++;
accountIndex[_address] = numberOfAccts;
acctAccessList.push(AccountAccessDetails(_address, _orgId, _roleId, _status, _oAdmin));
}
if (_oAdmin) {
orgAdminIndex[keccak256(abi.encodePacked(_orgId))] = _address;
}
emit AccountAccessModified(_address, _orgId, _roleId, _oAdmin, _status);
}
function addNWAdminAccount(address _address, string calldata _orgId) external
{
setAccountRole(_address, _orgId, adminRole, 2, true);
}
function assignAccountRole(address _address, string calldata _orgId, string calldata _roleId) external
{
bool oAdminRole = false;
uint status = 2;
// if the role id is ORGADMIN then check if already an orgadmin exists
if ((keccak256(abi.encodePacked(_roleId)) == keccak256(abi.encodePacked(orgAdminRole))) ||
(keccak256(abi.encodePacked(_roleId)) == keccak256(abi.encodePacked(adminRole)))) {
if (orgAdminIndex[keccak256(abi.encodePacked(_orgId))] != address(0)) {
return;
}
else {
oAdminRole = true;
status = 1;
}
}
setAccountRole(_address, _orgId, _roleId, status, oAdminRole);
}
function approveOrgAdminAccount(address _address) external
{
// check of the account role is ORGADMIN and status is pending approval
// if yes update the status to approved
string memory role = getAccountRole(_address);
uint status = getAccountStatus(_address);
if ((keccak256(abi.encodePacked(role)) == keccak256(abi.encodePacked(orgAdminRole))) &&
(status == 1)) {
uint aIndex = getAcctIndex(_address);
acctAccessList[aIndex].status = 2;
emit AccountAccessModified(_address, acctAccessList[aIndex].orgId, acctAccessList[aIndex].role, acctAccessList[aIndex].orgAdmin, acctAccessList[aIndex].status);
}
}
function revokeAccountRole(address _address) external
{
// Check if account already exists
uint aIndex = getAcctIndex(_address);
if (accountIndex[_address] != 0) {
acctAccessList[aIndex].status = 3;
emit AccountAccessRevoked(_address, acctAccessList[aIndex].orgId, acctAccessList[aIndex].role, acctAccessList[aIndex].orgAdmin);
}
}
function getAccountRole(address _acct) public view returns (string memory)
{
if (accountIndex[_acct] == 0) {
return "NONE";
}
uint acctIndex = getAcctIndex(_acct);
if (acctAccessList[acctIndex].status != 0) {
return acctAccessList[acctIndex].role;
}
else {
return "NONE";
}
}
function checkOrgAdmin(address _acct, string calldata _orgId, string calldata _ultParent) external view returns (bool)
{
if (accountIndex[_acct] == 0) {
return false;
}
uint acctIndex = getAcctIndex(_acct);
return ((acctAccessList[acctIndex].orgAdmin) &&
((keccak256(abi.encodePacked(acctAccessList[acctIndex].orgId)) == keccak256(abi.encodePacked(_orgId))) ||
(keccak256(abi.encodePacked(acctAccessList[acctIndex].orgId)) == keccak256(abi.encodePacked(_ultParent)))));
}
// this function checks if account access can be modified. Account access can be modified for a new account
// or if the call is from the orgadmin of the same org.
function valAcctAccessChange(address _acct, string calldata _orgId, string calldata _ultParent) external view returns (bool)
{
if (accountIndex[_acct] == 0) {
return true;
}
uint acctIndex = getAcctIndex(_acct);
return ((keccak256(abi.encodePacked(acctAccessList[acctIndex].orgId)) == keccak256(abi.encodePacked(_orgId))) ||
(keccak256(abi.encodePacked(acctAccessList[acctIndex].orgId)) == keccak256(abi.encodePacked(_ultParent))));
}
// Returns the account index based on account id
function getAcctIndex(address _acct) internal view returns (uint)
{
return accountIndex[_acct] - 1;
}
}