feat: RBAC authentication contract and role library
This commit is contained in:
77
test/RBAC.js
Normal file
77
test/RBAC.js
Normal file
@ -0,0 +1,77 @@
|
||||
const RBACMock = artifacts.require('./helpers/RBACMock.sol')
|
||||
|
||||
import expectThrow from './helpers/expectThrow'
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-as-promised'))
|
||||
.should()
|
||||
|
||||
contract('RBAC', function(accounts) {
|
||||
let mock
|
||||
|
||||
const [
|
||||
owner,
|
||||
anyone,
|
||||
...advisors
|
||||
] = accounts
|
||||
|
||||
before(async () => {
|
||||
mock = await RBACMock.new(advisors, { from: owner })
|
||||
})
|
||||
|
||||
context('in normal conditions', () => {
|
||||
it('allows owner to call #onlyOwnersCanDoThis', async () => {
|
||||
await mock.onlyOwnersCanDoThis({ from: owner })
|
||||
.should.be.fulfilled
|
||||
})
|
||||
it('allows owner to call #onlyAdvisorsCanDoThis', async () => {
|
||||
await mock.onlyAdvisorsCanDoThis({ from: owner })
|
||||
.should.be.fulfilled
|
||||
})
|
||||
it('allows advisors to call #onlyAdvisorsCanDoThis', async () => {
|
||||
await mock.onlyAdvisorsCanDoThis({ from: advisors[0] })
|
||||
.should.be.fulfilled
|
||||
})
|
||||
it('allows owner to call #eitherOwnerOrAdvisorCanDoThis', async () => {
|
||||
await mock.eitherOwnerOrAdvisorCanDoThis({ from: owner })
|
||||
.should.be.fulfilled
|
||||
})
|
||||
it('allows advisors to call #eitherOwnerOrAdvisorCanDoThis', async () => {
|
||||
await mock.eitherOwnerOrAdvisorCanDoThis({ from: advisors[0] })
|
||||
.should.be.fulfilled
|
||||
})
|
||||
it('does not allow owners to call #nobodyCanDoThis', async () => {
|
||||
expectThrow(
|
||||
mock.nobodyCanDoThis({ from: owner })
|
||||
)
|
||||
})
|
||||
it('does not allow advisors to call #nobodyCanDoThis', async () => {
|
||||
expectThrow(
|
||||
mock.nobodyCanDoThis({ from: advisors[0] })
|
||||
)
|
||||
})
|
||||
it('does not allow anyone to call #nobodyCanDoThis', async () => {
|
||||
expectThrow(
|
||||
mock.nobodyCanDoThis({ from: anyone })
|
||||
)
|
||||
})
|
||||
it('allows an owner to remove an advisor\'s role', async () => {
|
||||
await mock.removeAdvisor(advisors[0], { from: owner })
|
||||
.should.be.fulfilled
|
||||
})
|
||||
})
|
||||
|
||||
context('in adversarial conditions', () => {
|
||||
it('does not allow an advisor to remove another advisor', async () => {
|
||||
expectThrow(
|
||||
mock.removeAdvisor(advisors[1], { from: advisors[0] })
|
||||
)
|
||||
})
|
||||
it('does not allow "anyone" to remove an advisor', async () => {
|
||||
expectThrow(
|
||||
mock.removeAdvisor(advisors[0], { from: anyone })
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
68
test/helpers/RBACMock.sol
Normal file
68
test/helpers/RBACMock.sol
Normal file
@ -0,0 +1,68 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import '../../contracts/ownership/rbac/RBAC.sol';
|
||||
|
||||
|
||||
contract RBACMock is RBAC {
|
||||
|
||||
modifier onlyOwnerOrAdvisor()
|
||||
{
|
||||
require(
|
||||
hasRole(msg.sender, "owner") ||
|
||||
hasRole(msg.sender, "advisor")
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
function RBACMock(address[] _advisors)
|
||||
public
|
||||
{
|
||||
addRole(msg.sender, "owner");
|
||||
addRole(msg.sender, "advisor");
|
||||
|
||||
for (uint256 i = 0; i < _advisors.length; i++) {
|
||||
addRole(_advisors[i], "advisor");
|
||||
}
|
||||
}
|
||||
|
||||
function onlyOwnersCanDoThis()
|
||||
onlyRole("owner")
|
||||
view
|
||||
external
|
||||
{
|
||||
}
|
||||
|
||||
function onlyAdvisorsCanDoThis()
|
||||
onlyRole("advisor")
|
||||
view
|
||||
external
|
||||
{
|
||||
}
|
||||
|
||||
function eitherOwnerOrAdvisorCanDoThis()
|
||||
onlyOwnerOrAdvisor
|
||||
view
|
||||
external
|
||||
{
|
||||
}
|
||||
|
||||
function nobodyCanDoThis()
|
||||
onlyRole("unknown")
|
||||
view
|
||||
external
|
||||
{
|
||||
}
|
||||
|
||||
// owners can remove advisor's role
|
||||
function removeAdvisor(address _addr)
|
||||
onlyRole("owner")
|
||||
public
|
||||
{
|
||||
// revert if the user isn't an advisor
|
||||
// (perhaps you want to soft-fail here instead?)
|
||||
checkRole(_addr, "advisor");
|
||||
|
||||
// remove the advisor's role
|
||||
removeRole(_addr, "advisor");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user