Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apm grant fix, apm revoke and apm manager commands #1597

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/Apm-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,23 @@ aragon apm grant [addr1 ... addrN]
```

- `addresses`: The addresses being granted the permission to publish to the repo.

## aragon apm revoke

Revoke an address the permission to create new versions in your package (defined in `arapp.json`), by interacting directly with the ACL, without performing transaction pathing.

```sh
aragon apm revoke <entity>
```

- `entity`: The entity address being revoked the permission to publish to the repo.

## aragon apm manager

Set an address to be the permission manager of your package (defined in `arapp.json`), by interacting directly with the ACL, without performing transaction pathing.

```sh
aragon apm manager <entity>
```

- `entity`: The entity address being set as permission manager.
52 changes: 52 additions & 0 deletions packages/cli/src/commands/apm_cmds/manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { blue } from 'chalk'
import { apmSetPermissionManager } from '@aragon/toolkit'
//
import { ensureWeb3 } from '../../helpers/web3-fallback'

export const command = 'manager <entity>'
export const describe =
'Set an entity as the permission manager of this package'

export const builder = function(yargs) {
return yargs.positional('entity', {
description: 'The address to be the new permission manager ofthe repo',
})
}

export const handler = async function({
// Globals
reporter,
gasPrice,
network,
module,
apm: apmOptions,
// Arguments
entity,
}) {
const web3 = await ensureWeb3(network)

const progressHandler = (step, data) => {
switch (step) {
case 1:
reporter.info(`Fetching repository`)
break
case 2:
reporter.info(
`Setting permission manager for ${blue(module.appName)} for ${data}`
)
break
case 3:
reporter.success(`Successful transaction (${blue(data)})`)
break
}
}

await apmSetPermissionManager(
web3,
module.appName,
apmOptions,
entity,
progressHandler,
{ gasPrice: gasPrice || network.gasPrice }
)
}
55 changes: 55 additions & 0 deletions packages/cli/src/commands/apm_cmds/revoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { blue } from 'chalk'
import { apmRevokePermission } from '@aragon/toolkit'
//
import { ensureWeb3 } from '../../helpers/web3-fallback'

export const command = 'revoke entity'
export const describe =
'Revoke an entity the permission to create new versions in this package'

export const builder = function(yargs) {
return yargs.positional('entity', {
description:
'The address being revoked the permission to publish to the repo',
})
}

export const handler = async function({
// Globals
reporter,
gasPrice,
network,
module,
apm: apmOptions,
// Arguments
entity,
}) {
const web3 = await ensureWeb3(network)

const progressHandler = (step, data) => {
switch (step) {
case 1:
reporter.info(`Fetching repository`)
break
case 2:
reporter.info(
`Revoking permission to publish on ${blue(
module.appName
)} for ${data}`
)
break
case 3:
reporter.success(`Successful transaction (${blue(data)})`)
break
}
}

await apmRevokePermission(
web3,
module.appName,
apmOptions,
entity,
progressHandler,
{ gasPrice: gasPrice || network.gasPrice }
)
}
2 changes: 1 addition & 1 deletion packages/cli/src/helpers/ensureDevchain.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const ensureDevchain = async ({ port, logger = noop }) => {
try {
const { detach } = await startProcess({
cmd: 'node',
args: [binPath, 'devchain', '--port', port],
args: [binPath, 'devchain', '--port', port, '--reset'],
readyOutput: 'Devchain running at',
execaOpts: {
detached: true,
Expand Down
46 changes: 46 additions & 0 deletions packages/toolkit/src/apm/apmRevokePermission.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import APM from '@aragon/apm'
import ACL from './util/acl'

export default async (
web3,
apmRepoName,
apmOptions,
entity,
progressHandler = () => {},
{ gasPrice }
) => {
if (entity.length === 0) {
throw new Error('No addresse provided')
}

const apm = await APM(web3, apmOptions)
const acl = ACL(web3)

progressHandler(1)

const repo = await apm.getRepository(apmRepoName)
if (repo === null) {
throw new Error(
`Repository ${apmRepoName} does not exist and it's registry does not exist`
)
}

/* eslint-disable-next-line */
progressHandler(2, entity)

// Decode sender
const accounts = await web3.eth.getAccounts()
const from = accounts[0]

// Build transaction
const transaction = await acl.revoke(repo.options.address, entity, from)

transaction.from = from
transaction.gasPrice = gasPrice
// the recommended gasLimit is already calculated by the ACL module

const receipt = await web3.eth.sendTransaction(transaction)
progressHandler(3, receipt.transactionHash)

return receipt
}
50 changes: 50 additions & 0 deletions packages/toolkit/src/apm/apmSetPermissionManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import APM from '@aragon/apm'
import ACL from './util/acl'

export default async (
web3,
apmRepoName,
apmOptions,
entity,
progressHandler = () => {},
{ gasPrice }
) => {
if (entity.length === 0) {
throw new Error('No addresse provided')
}

const apm = await APM(web3, apmOptions)
const acl = ACL(web3)

progressHandler(1)

const repo = await apm.getRepository(apmRepoName)
if (repo === null) {
throw new Error(
`Repository ${apmRepoName} does not exist and it's registry does not exist`
)
}

/* eslint-disable-next-line */
progressHandler(2, entity)

// Decode sender
const accounts = await web3.eth.getAccounts()
const from = accounts[0]

// Build transaction
const transaction = await acl.setPermissionManager(
entity,
repo.options.address,
from
)

transaction.from = from
transaction.gasPrice = gasPrice
// the recommended gasLimit is already calculated by the ACL module

const receipt = await web3.eth.sendTransaction(transaction)
progressHandler(3, receipt.transactionHash)

return receipt
}
2 changes: 1 addition & 1 deletion packages/toolkit/src/apm/grantNewVersionsPermission.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default async (
const from = accounts[0]

// Build transaction
const transaction = await acl.grant(repo.options.address, address)
const transaction = await acl.grant(repo.options.address, address, from)

transaction.from = from
transaction.gasPrice = gasPrice
Expand Down
2 changes: 2 additions & 0 deletions packages/toolkit/src/apm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export { default as grantNewVersionsPermission } from './grantNewVersionsPermiss
export { default as apmPublishVersion } from './apmPublishVersion'
export { default as apmPublishVersionIntent } from './apmPublishVersionIntent'
export { default as apmGetFile } from './apmGetFile'
export { default as apmRevokePermission } from './apmRevokePermission'
export { default as apmSetPermissionManager } from './apmSetPermissionManager'
33 changes: 30 additions & 3 deletions packages/toolkit/src/apm/util/acl.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,40 @@ export default web3 => {
}

return {
grant: async (repoAddr, grantee) => {
grant: async (repoAddr, grantee, from) => {
const acl = await getACL(repoAddr)

const roleId = await getRoleId(repoAddr)

const call = acl.methods.grantPermission(grantee, repoAddr, roleId)
const estimatedGas = call.estimateGas()
const estimatedGas = call.estimateGas({ from })

return {
to: acl.options.address,
data: call.encodeABI(),
gas: await getRecommendedGasLimit(web3, estimatedGas),
}
},

revoke: async (repoAddr, grantee, from) => {
const acl = await getACL(repoAddr)

const roleId = await getRoleId(repoAddr)
const call = acl.methods.revokePermission(grantee, repoAddr, roleId)
const estimatedGas = call.estimateGas({ from })

return {
to: acl.options.address,
data: call.encodeABI(),
gas: await getRecommendedGasLimit(web3, estimatedGas),
}
},

setPermissionManager: async (entity, repoAddr, from) => {
const acl = await getACL(repoAddr)

const roleId = await getRoleId(repoAddr)
const call = acl.methods.setPermissionManager(entity, repoAddr, roleId)
const estimatedGas = call.estimateGas({ from })

return {
to: acl.options.address,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import test from 'ava'
import sinon from 'sinon'
//
import grantNewVersionsPermission from '../../src/apm/grantNewVersionsPermission'
import apmRevokePermission from '../../src/apm/apmRevokePermission'
import apmSetPermissionManager from '../../src/apm/apmSetPermissionManager'
import { getLocalWeb3, getApmOptions } from '../test-helpers'

import { abi as aclAbi } from '@aragon/abis/os/artifacts/ACL'
Expand Down Expand Up @@ -67,7 +69,7 @@ test.before('setup and make a successful call', async t => {

/* Tests */

test('permissions are not set for any accounts', async t => {
test.serial('permissions are not set for any accounts', async t => {
const anyone = accounts[2]

const hasPermission = await acl.methods
Expand All @@ -77,7 +79,7 @@ test('permissions are not set for any accounts', async t => {
t.false(hasPermission)
})

test('properly sets permissions for grantees', async t => {
test.serial('properly sets permissions for grantees', async t => {
const grantee = grantees[0]

const hasPermission = await acl.methods
Expand All @@ -87,7 +89,7 @@ test('properly sets permissions for grantees', async t => {
t.true(hasPermission)
})

test('properly calls the progressHandler', t => {
test.serial('properly calls the progressHandler', t => {
const receipt = receipts[0]

t.is(progressHandler.callCount, 3)
Expand All @@ -96,7 +98,7 @@ test('properly calls the progressHandler', t => {
t.true(progressHandler.getCall(2).calledWith(3, receipt.transactionHash))
})

test('Should throw when no grantees are provided', async t => {
test.serial('Should throw when no grantees are provided', async t => {
await t.throwsAsync(
grantNewVersionsPermission(
web3,
Expand All @@ -108,3 +110,47 @@ test('Should throw when no grantees are provided', async t => {
)
)
})

test.serial(
'apmRevokePermission properly revokes permission for entity',
async t => {
const entity = grantees[0]

await apmRevokePermission(
web3,
apmRepoName,
apmOptions,
entity,
() => {},
txOptions
)

const hasPermission = await acl.methods
.hasPermission(entity, repoAddress, role)
.call()

t.false(hasPermission)
}
)

test.serial(
'apmSetPermissionManager properly sets the permission manager',
async t => {
const entity = grantees[0]

await apmSetPermissionManager(
web3,
apmRepoName,
apmOptions,
entity,
() => {},
txOptions
)

const permissionManager = await acl.methods
.getPermissionManager(repoAddress, role)
.call()

t.is(entity, permissionManager)
}
)