2019-03-14 23:41:04 -07:00
|
|
|
pragma solidity ^0.5.3;
|
|
|
|
|
|
|
|
import "./PermissionsUpgradable.sol";
|
|
|
|
|
|
|
|
contract OrgManager {
|
|
|
|
string private adminOrgId;
|
2019-03-19 02:15:51 -07:00
|
|
|
PermissionsUpgradable private permUpgradable;
|
2019-03-14 23:41:04 -07:00
|
|
|
// checks if first time network boot up has happened or not
|
|
|
|
bool private networkBoot = false;
|
2019-04-04 03:25:43 -07:00
|
|
|
uint private DEPTH_LIMIT = 4;
|
2019-04-14 21:32:06 -07:00
|
|
|
uint private BREADTH_LIMIT = 4;
|
2019-03-14 23:41:04 -07:00
|
|
|
// enum OrgStatus {0- NotInList, 1- Proposed, 2- Approved, 3- PendingSuspension, 4- Suspended, 5- RevokeSuspension}
|
|
|
|
struct OrgDetails {
|
|
|
|
string orgId;
|
|
|
|
uint status;
|
2019-04-03 07:25:01 -07:00
|
|
|
string parentId;
|
2019-04-04 03:25:43 -07:00
|
|
|
string fullOrgId;
|
2019-04-08 23:58:30 -07:00
|
|
|
string ultParent;
|
2019-04-03 07:25:01 -07:00
|
|
|
uint pindex;
|
|
|
|
uint level;
|
2019-04-08 23:58:30 -07:00
|
|
|
uint [] subOrgIndexList;
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
2019-04-03 07:25:01 -07:00
|
|
|
|
2019-03-14 23:41:04 -07:00
|
|
|
OrgDetails [] private orgList;
|
|
|
|
mapping(bytes32 => uint) private OrgIndex;
|
|
|
|
uint private orgNum = 0;
|
|
|
|
|
|
|
|
// events related to Master Org add
|
2019-04-09 02:52:06 -07:00
|
|
|
event OrgApproved(string _orgId, string _porgId, string _ultParent, uint _level, uint _status);
|
|
|
|
event OrgPendingApproval(string _orgId, string _porgId, string _ultParent, uint _level, uint _status);
|
|
|
|
event OrgSuspended(string _orgId, string _porgId, string _ultParent, uint _level);
|
|
|
|
event OrgSuspensionRevoked(string _orgId, string _porgId, string _ultParent, uint _level);
|
2019-03-14 23:41:04 -07:00
|
|
|
|
|
|
|
modifier onlyImpl
|
|
|
|
{
|
|
|
|
require(msg.sender == permUpgradable.getPermImpl());
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
modifier orgNotExists(string memory _orgId) {
|
|
|
|
require(checkOrgExists(_orgId) == false, "Org already exists");
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
modifier orgExists(string memory _orgId) {
|
|
|
|
require(checkOrgExists(_orgId) == true, "Org does not exists");
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
2019-03-15 02:26:57 -07:00
|
|
|
constructor (address _permUpgradable) public {
|
2019-03-19 02:15:51 -07:00
|
|
|
permUpgradable = PermissionsUpgradable(_permUpgradable);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getImpl() public view returns (address) {
|
|
|
|
return permUpgradable.getPermImpl();
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
2019-04-14 21:32:06 -07:00
|
|
|
function setUpOrg(string calldata _orgId, uint _breadth, uint _depth) external
|
2019-03-14 23:41:04 -07:00
|
|
|
onlyImpl
|
2019-03-27 04:07:01 -07:00
|
|
|
{
|
2019-04-03 07:25:01 -07:00
|
|
|
addNewOrg("", _orgId, 1, 2);
|
2019-04-14 21:32:06 -07:00
|
|
|
DEPTH_LIMIT = _depth;
|
|
|
|
BREADTH_LIMIT = _breadth;
|
2019-03-27 04:07:01 -07:00
|
|
|
}
|
|
|
|
|
2019-04-03 07:25:01 -07:00
|
|
|
function addNewOrg(string memory _pOrg, string memory _orgId, uint _level, uint _status) internal
|
2019-03-14 23:41:04 -07:00
|
|
|
{
|
2019-04-03 07:25:01 -07:00
|
|
|
bytes32 pid = "";
|
|
|
|
bytes32 oid = "";
|
2019-04-04 03:25:43 -07:00
|
|
|
uint parentIndex = 0;
|
2019-04-08 23:58:30 -07:00
|
|
|
|
2019-04-03 07:25:01 -07:00
|
|
|
if (_level == 1) {//root
|
|
|
|
oid = keccak256(abi.encodePacked(_orgId));
|
|
|
|
} else {
|
|
|
|
pid = keccak256(abi.encodePacked(_pOrg));
|
|
|
|
oid = keccak256(abi.encodePacked(_pOrg, ".", _orgId));
|
|
|
|
}
|
2019-03-14 23:41:04 -07:00
|
|
|
orgNum++;
|
2019-04-03 07:25:01 -07:00
|
|
|
OrgIndex[oid] = orgNum;
|
2019-03-14 23:41:04 -07:00
|
|
|
uint id = orgList.length++;
|
2019-04-03 07:25:01 -07:00
|
|
|
if (_level == 1) {
|
|
|
|
orgList[id].level = _level;
|
|
|
|
orgList[id].pindex = 0;
|
2019-04-04 03:25:43 -07:00
|
|
|
orgList[id].fullOrgId = _orgId;
|
2019-04-08 23:58:30 -07:00
|
|
|
orgList[id].ultParent = _orgId;
|
2019-04-03 07:25:01 -07:00
|
|
|
} else {
|
2019-04-04 03:25:43 -07:00
|
|
|
parentIndex = OrgIndex[pid] - 1;
|
|
|
|
|
2019-04-08 23:58:30 -07:00
|
|
|
require(orgList[parentIndex].subOrgIndexList.length < BREADTH_LIMIT, "breadth level exceeded");
|
|
|
|
require(orgList[parentIndex].level < DEPTH_LIMIT, "depth level exceeded");
|
2019-04-04 03:25:43 -07:00
|
|
|
|
2019-04-08 23:58:30 -07:00
|
|
|
orgList[id].level = orgList[parentIndex].level + 1;
|
2019-04-04 03:25:43 -07:00
|
|
|
orgList[id].pindex = parentIndex;
|
2019-04-08 23:58:30 -07:00
|
|
|
orgList[id].ultParent = orgList[parentIndex].ultParent;
|
2019-04-04 03:25:43 -07:00
|
|
|
uint subOrgId = orgList[parentIndex].subOrgIndexList.length++;
|
|
|
|
orgList[parentIndex].subOrgIndexList[subOrgId] = id;
|
|
|
|
orgList[id].fullOrgId = string(abi.encodePacked(_pOrg, ".", _orgId));
|
2019-04-03 07:25:01 -07:00
|
|
|
}
|
2019-03-14 23:41:04 -07:00
|
|
|
orgList[id].orgId = _orgId;
|
2019-04-03 07:25:01 -07:00
|
|
|
orgList[id].parentId = _pOrg;
|
2019-03-27 04:07:01 -07:00
|
|
|
orgList[id].status = _status;
|
2019-04-09 02:52:06 -07:00
|
|
|
if (_status == 1) {
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgPendingApproval(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level, 1);
|
2019-04-09 02:52:06 -07:00
|
|
|
}
|
|
|
|
else {
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgApproved(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level, 2);
|
2019-04-09 02:52:06 -07:00
|
|
|
}
|
2019-03-27 04:07:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function getNumberOfOrgs() public view returns (uint)
|
|
|
|
{
|
|
|
|
return orgList.length;
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Org related functions
|
|
|
|
// returns the org index for the org list
|
|
|
|
function getOrgIndex(string memory _orgId) public view returns (uint)
|
|
|
|
{
|
|
|
|
return OrgIndex[keccak256(abi.encodePacked(_orgId))] - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getOrgStatus(string memory _orgId) public view returns (uint)
|
|
|
|
{
|
|
|
|
return orgList[OrgIndex[keccak256(abi.encodePacked(_orgId))]].status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// function for adding a new master org
|
|
|
|
function addOrg(string calldata _orgId) external
|
|
|
|
onlyImpl
|
|
|
|
orgNotExists(_orgId)
|
|
|
|
{
|
2019-04-03 07:25:01 -07:00
|
|
|
addNewOrg("", _orgId, 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// function for adding a new master org
|
|
|
|
function addSubOrg(string calldata _pOrg, string calldata _orgId) external
|
|
|
|
onlyImpl
|
|
|
|
orgNotExists(string(abi.encodePacked(_pOrg, ".", _orgId)))
|
|
|
|
{
|
2019-04-08 23:58:30 -07:00
|
|
|
addNewOrg(_pOrg, _orgId, 2, 2);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function updateOrg(string calldata _orgId, uint _status) external
|
|
|
|
onlyImpl
|
|
|
|
orgExists(_orgId)
|
2019-03-28 02:53:11 -07:00
|
|
|
returns (uint)
|
2019-03-14 23:41:04 -07:00
|
|
|
{
|
2019-04-03 07:25:01 -07:00
|
|
|
require((_status == 3 || _status == 5), "Operation not allowed");
|
2019-05-07 01:23:17 -07:00
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
require(orgList[id].level == 1, "not a master org. operation not allowed");
|
|
|
|
|
2019-03-28 02:53:11 -07:00
|
|
|
uint reqStatus;
|
|
|
|
uint pendingOp;
|
|
|
|
if (_status == 3) {
|
|
|
|
reqStatus = 2;
|
|
|
|
pendingOp = 2;
|
|
|
|
}
|
|
|
|
else if (_status == 5) {
|
|
|
|
reqStatus = 4;
|
|
|
|
pendingOp = 3;
|
|
|
|
}
|
|
|
|
require(checkOrgStatus(_orgId, reqStatus) == true, "Operation not allowed");
|
2019-03-14 23:41:04 -07:00
|
|
|
if (_status == 3) {
|
|
|
|
suspendOrg(_orgId);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
revokeOrgSuspension(_orgId);
|
|
|
|
}
|
2019-03-28 02:53:11 -07:00
|
|
|
return pendingOp;
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function approveOrgStatusUpdate(string calldata _orgId, uint _status) external
|
|
|
|
onlyImpl
|
|
|
|
orgExists(_orgId)
|
|
|
|
{
|
|
|
|
if (_status == 3) {
|
|
|
|
approveOrgSuspension(_orgId);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
approveOrgRevokeSuspension(_orgId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// function for adding a new master org
|
|
|
|
function suspendOrg(string memory _orgId) internal
|
|
|
|
{
|
|
|
|
require(checkOrgStatus(_orgId, 2) == true, "Org not in approved state");
|
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
orgList[id].status = 3;
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgPendingApproval(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level, 3);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function revokeOrgSuspension(string memory _orgId) internal
|
|
|
|
|
|
|
|
{
|
|
|
|
require(checkOrgStatus(_orgId, 4) == true, "Org not in suspended state");
|
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
orgList[id].status = 5;
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgPendingApproval(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level, 5);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function approveOrg(string calldata _orgId) external
|
|
|
|
onlyImpl
|
|
|
|
{
|
|
|
|
require(checkOrgStatus(_orgId, 1) == true, "Nothing to approve");
|
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
orgList[id].status = 2;
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgApproved(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level, 2);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function approveOrgSuspension(string memory _orgId) internal
|
|
|
|
{
|
|
|
|
require(checkOrgStatus(_orgId, 3) == true, "Nothing to approve");
|
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
orgList[id].status = 4;
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgSuspended(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function approveOrgRevokeSuspension(string memory _orgId) internal
|
|
|
|
{
|
|
|
|
require(checkOrgStatus(_orgId, 5) == true, "Nothing to approve");
|
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
orgList[id].status = 2;
|
2019-04-12 05:28:22 -07:00
|
|
|
emit OrgSuspensionRevoked(orgList[id].orgId, orgList[id].parentId, orgList[id].ultParent, orgList[id].level);
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function checkOrgStatus(string memory _orgId, uint _orgStatus) public view returns (bool){
|
|
|
|
uint id = getOrgIndex(_orgId);
|
|
|
|
return ((OrgIndex[keccak256(abi.encodePacked(_orgId))] != 0) && orgList[id].status == _orgStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
// function to check if morg exists
|
|
|
|
function checkOrgExists(string memory _orgId) public view returns (bool)
|
|
|
|
{
|
|
|
|
return (!(OrgIndex[keccak256(abi.encodePacked(_orgId))] == 0));
|
|
|
|
}
|
|
|
|
|
2019-04-03 07:25:01 -07:00
|
|
|
// function to check if morg exists
|
|
|
|
function checkNodeExists(string memory _pOrg, string memory _orgId) public view returns (bool)
|
|
|
|
{
|
|
|
|
return (!(OrgIndex[keccak256(abi.encodePacked(_pOrg, _orgId))] == 0));
|
|
|
|
}
|
|
|
|
|
2019-03-14 23:41:04 -07:00
|
|
|
// returns org and master org details based on org index
|
2019-04-09 02:52:06 -07:00
|
|
|
function getOrgInfo(uint _orgIndex) external view returns (string memory, string memory, string memory, uint, uint)
|
2019-04-04 03:25:43 -07:00
|
|
|
{
|
2019-04-09 02:52:06 -07:00
|
|
|
return (orgList[_orgIndex].orgId, orgList[_orgIndex].parentId, orgList[_orgIndex].ultParent, orgList[_orgIndex].level, orgList[_orgIndex].status);
|
2019-04-04 03:25:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function getSubOrgInfo(uint _orgIndex) external view returns (uint[] memory)
|
|
|
|
{
|
|
|
|
return orgList[_orgIndex].subOrgIndexList;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getSubOrgIndexLength(uint _orgIndex) external view returns (uint)
|
|
|
|
{
|
|
|
|
return orgList[_orgIndex].subOrgIndexList.length;
|
|
|
|
}
|
|
|
|
function getSubOrgIndexLength(uint _orgIndex, uint _subOrgIndex) external view returns (uint)
|
2019-03-14 23:41:04 -07:00
|
|
|
{
|
2019-04-04 03:25:43 -07:00
|
|
|
return orgList[_orgIndex].subOrgIndexList[_subOrgIndex];
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|
2019-04-08 23:58:30 -07:00
|
|
|
|
|
|
|
function getUltimateParent(string calldata _orgId) external view returns (string memory)
|
|
|
|
{
|
|
|
|
return orgList[getOrgIndex(_orgId)].ultParent;
|
|
|
|
}
|
2019-03-14 23:41:04 -07:00
|
|
|
}
|