/* * Organization: Fraunhofer AISEC * Author: Christof Ferreira Torres * Date: 06.03.2018 */ pragma solidity ^0.4.18; import "./libs/Ownable.sol"; import "./libs/Destructible.sol"; contract IdentityMgmt is Ownable, Destructible { // Keeps a list of institution indexes (required at deletion) address[] private institutionIndex; // Mapping institution address to IPFS profile data hash mapping(address => bytes32) private accreditedInstitutions; // Keeps a list of certifier indexes (required at deletion) mapping(address => address[]) private certifierIndex; // Mapping certfier address to institution address mapping(address => address) private accreditedCertifiers; // Flag to determine if address is from a real contract or from a non-existing one bool private isRealIdentityMgmt = false; // Log events event InstitutionAdded(address caller, address institution, bytes32 profile, uint256 timestamp); event InstitutionRemoved(address caller, address institution, uint256 timestamp); event CertifierAdded(address caller, address certifier, uint256 timestamp); event CertifierRemoved(address caller, address certifier, uint256 timestamp); // Returns true when msg.sender is an accredited institution. modifier onlyAccreditedInstitutions() { require(accreditedInstitutions[msg.sender] > 0); _; } /* Constructor */ function IdentityMgmt() public { isRealIdentityMgmt = true; } /* Standard functions in order to mange money tranfers and self destruction */ // Default function which basically does nothing except receiving money function() public payable {} // Removes the storage and code of the smart contract from the blockchain and // transfers the funds to a given destination. Can only be called by the owner. function destroy(address destination) onlyOwner external { require(destination != address(0)); selfdestruct(destination); } // Transfer all the current funds to a given destionation. Can only be called // by the owner. function transfer(address destination) onlyOwner external payable { require(destination != address(0)); destination.transfer(this.balance); } /* Contract functions */ // Returns true once this contract has been deployed. Can be called by anyone. function isIdentityMgmt() public constant returns (bool) { return isRealIdentityMgmt; } // Returns true if the given certifier is an accredited certfier. Can be called by anyone. function isAccreditedCertifier(address certifier) public constant returns (bool) { return (accreditedInstitutions[accreditedCertifiers[certifier]] > 0); } // Returns the address of the institution the given certifier is associated // with. Can be called by anyone. function getInstitutionFromCertifier(address certifier) public constant returns (address) { return accreditedCertifiers[certifier]; } // Returns the IPFS hash of a given accredited institution. Can be called by anyone. function getInstitutionProfile(address institution) public constant returns (bytes32) { return accreditedInstitutions[institution]; } // Adds a given institution and its IPFS hash to the list of accredited institutions. // Can only be called by the owner. function addInstitution(address institution, bytes32 profile) public onlyOwner { require(institution != address(0)); require(accreditedInstitutions[institution] == 0); institutionIndex.push(institution); accreditedInstitutions[institution] = profile; InstitutionAdded(msg.sender, institution, profile, now); } // Returns a list of accredited institutions and their respective IPFS hashes. // Can only be called by the owner. function getInstitutions() public constant onlyOwner returns (address[], bytes32[]) { bytes32[] memory profiles = new bytes32[](institutionIndex.length); for (uint i = 0; i < institutionIndex.length; i++) { profiles[i] = accreditedInstitutions[institutionIndex[i]]; } return (institutionIndex, profiles); } // Removes a given institution from the list of accredited institutions. // Can only be called by the owner. function removeInstitution(address institution) public onlyOwner { require(institution != address(0)); require(accreditedInstitutions[institution] > 0); bool found = false; uint index = 0; for (uint i = 0; i < institutionIndex.length; i++) { if (institutionIndex[i] == institution) { found = true; index = i; break; } } if (found) { for (uint j = index; j < institutionIndex.length; j++) { if (j+1 < institutionIndex.length) { institutionIndex[j] = institutionIndex[j+1]; } } delete institutionIndex[institutionIndex.length-1]; institutionIndex.length--; delete accreditedInstitutions[institution]; InstitutionRemoved(msg.sender, institution, now); } } // Adds a certfier to the list of accredited certifiers. Can only be called // by an accredited institution. function addCertifier(address certifier) public onlyAccreditedInstitutions { require(certifier != address(0)); require(accreditedCertifiers[certifier] == 0); certifierIndex[msg.sender].push(certifier); accreditedCertifiers[certifier] = msg.sender; CertifierAdded(msg.sender, certifier, now); } // Returns a list of accredited certfier for the calling institution. Can // only be called by an accredited institution. function getCertifiers() public constant onlyAccreditedInstitutions returns (address[]) { return certifierIndex[msg.sender]; } // Removes a given certifier from the list of accredited certifiers associated // with the calling institution. Can only be called by an accredited institution. function removeCertifier(address certifier) public onlyAccreditedInstitutions { require(certifier != address(0)); require(msg.sender == accreditedCertifiers[certifier]); bool found = false; uint index = 0; for (uint i = 0; i < certifierIndex[msg.sender].length; i++) { if (certifierIndex[msg.sender][i] == certifier) { found = true; index = i; break; } } if (found) { for (uint j = index; j < certifierIndex[msg.sender].length; j++) { if (j+1 < certifierIndex[msg.sender].length) { certifierIndex[msg.sender][j] = certifierIndex[msg.sender][j+1]; } } delete certifierIndex[msg.sender][certifierIndex[msg.sender].length-1]; certifierIndex[msg.sender].length--; delete accreditedCertifiers[certifier]; CertifierRemoved(msg.sender, certifier, now); } } }