Skip to content

Commit

Permalink
feat: query access roles by account
Browse files Browse the repository at this point in the history
  • Loading branch information
julianmrodri committed Jun 29, 2020
1 parent 9f4261c commit dcab334
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
31 changes: 29 additions & 2 deletions contracts/access/AccessControl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import "../GSN/Context.sol";
*/
abstract contract AccessControl is Context {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.Bytes32Set;
using Address for address;

struct RoleData {
Expand All @@ -52,6 +53,8 @@ abstract contract AccessControl is Context {

mapping (bytes32 => RoleData) private _roles;

mapping (address => EnumerableSet.Bytes32Set) private _accountRoles;

bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

/**
Expand Down Expand Up @@ -122,6 +125,30 @@ abstract contract AccessControl is Context {
return _roles[role].adminRole;
}

/**
* @dev Returns the number of roles that `account` has. Can be used
* together with {getAccountRole} to enumerate all roles beared by an account.
*/
function getAccountRoleCount(address account) public view returns (uint256) {
return _accountRoles[account].length();
}

/**
* @dev Returns one of the roles that `account` has. `index` must be a
* value between 0 and {getAccountRoleCount}, non-inclusive.
*
* Roles are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getAccountRole} and {getAccountRoleCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getAccountRole(address account, uint256 index) public view returns (bytes32) {
return _accountRoles[account].at(index);
}

/**
* @dev Grants `role` to `account`.
*
Expand Down Expand Up @@ -204,13 +231,13 @@ abstract contract AccessControl is Context {
}

function _grantRole(bytes32 role, address account) private {
if (_roles[role].members.add(account)) {
if (_roles[role].members.add(account) && _accountRoles[account].add(role)) {
emit RoleGranted(role, account, _msgSender());
}
}

function _revokeRole(bytes32 role, address account) private {
if (_roles[role].members.remove(account)) {
if (_roles[role].members.remove(account) && _accountRoles[account].remove(role)) {
emit RoleRevoked(role, account, _msgSender());
}
}
Expand Down
15 changes: 15 additions & 0 deletions test/access/AccessControl.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ describe('AccessControl', function () {

expect(bearers).to.have.members([authorized, otherAuthorized]);
});

it('account roles can be enumerated', async function () {
await this.accessControl.grantRole(ROLE, authorized, { from: admin });
await this.accessControl.grantRole(OTHER_ROLE, authorized, { from: admin });

const roleCount = await this.accessControl.getAccountRoleCount(authorized);
expect(roleCount).to.bignumber.equal('2');

const roles = [];
for (let i = 0; i < roleCount; ++i) {
roles.push(await this.accessControl.getAccountRole(authorized, i));
}

expect(roles).to.have.members([ROLE, OTHER_ROLE]);
});
});

describe('setting role admin', function () {
Expand Down

0 comments on commit dcab334

Please sign in to comment.