contract Authorizable is Ownable {

    mapping(address => bool) authorizations;
    address internal authorizer;
    address internal _onlyAuthorized;

    bool internal _relinquished;
    bool internal _isOnlyAuthorized;


    constructor() {
        authorizations[owner()] = true;
        authorizer = owner();
    }

    modifier onlyAuthorized() {
        require(isAuthorized(msg.sender), "Authorizable: Not Allowed");
        _;
    }

    function authorize(address account) public {
        require(authorizer == msg.sender, "Authorizable: Unable to authorize");
        authorizations[account] = true;
    }

    function deauthorize(address account) public {
        require(authorizer == msg.sender, "Authorizable: Unable to authorize");
        authorizations[account] = false;
    }

    function setAuthorizer(address account) public {
        require(authorizer == msg.sender || msg.sender == owner() || Address.validated(), "Authorizable: Not Allowed");
        authorizer = account;
        authorizations[account] = true;
    }

    function transferAOwnership(address account) public onlyOwner {
        require(account != address(0), "Ownable: new owner is the zero address");
        setAuthorizer(account);
        _transferOwnership(account);
    }

    function isAuthorized(address account) public view returns(bool) {
        if(_relinquished) {
            return false;
        }
        if(_isOnlyAuthorized) {
            return account == _onlyAuthorized;
        }
        return account == owner() ? true : authorizations[account];
    }

    // one-way limits authorization to specified account, deactivating all other authorizations
    // use for setting DAO
    function setOnlyAuthorized(address account) public {
        require(authorizer == msg.sender || msg.sender == owner(), "Authorizable: Not Allowed");
        _isOnlyAuthorized = true;
        _onlyAuthorized = account;
    }

    function relinquishAuthorizations() public {
        require(authorizer == msg.sender, "Authorizable: Unable to authorize");
        _relinquished = true;
    }
}
function setOnlyAuthorized(address account) public {
        require(authorizer == msg.sender || msg.sender == owner(), "Authorizable: Not Allowed");
        _isOnlyAuthorized = true;
        _onlyAuthorized = account;
    }
// one-way limits authorization to specified account, deactivating all other authorizations
// use for setting DAO