Skip to content
Draft
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
4 changes: 4 additions & 0 deletions bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ cli
'--base64',
'Format as base64 identity CID string. Useful when saving it as an environment variable.'
)
.option(
'--use-space-recovery-key',
'The recovery key of the space to use as the issuer of this delegation. Can only be used to grant capabilities on the given space.'
)
.action(createDelegation)

cli
Expand Down
43 changes: 30 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { CarWriter } from '@ipld/car'
import { filesFromPaths } from 'files-from-path'
import * as Account from './account.js'
import { spaceAccess } from '@web3-storage/w3up-client/capability/access'
import { AgentData } from '@web3-storage/access'
import * as W3Space from '@web3-storage/w3up-client/space'
import { AgentData, StoreMemory } from '@web3-storage/access'
import * as Space from './space.js'
import {
getClient,
Expand All @@ -30,6 +31,7 @@ export * as Coupon from './coupon.js'
export * as Bridge from './bridge.js'
export { Account, Space }
import ago from 's-ago'
import { accountAccess } from '@web3-storage/access/access'

/**
*
Expand Down Expand Up @@ -333,17 +335,33 @@ Providers: ${providers || chalk.dim('none')}

/**
* @param {string} audienceDID
* @param {object} opts
* @param {string[]|string} opts.can
* @param {string} [opts.name]
* @param {string} [opts.type]
* @param {number} [opts.expiration]
* @param {string} [opts.output]
* @param {string} [opts.with]
* @param {boolean} [opts.base64]
* @param {{
* can: string | string[],
* name?: string,
* type?: string,
* expiration?: number,
* output?: string,
* with?: string,
* base64?: boolean,
* 'use-space-recovery-key'?: string
* }} opts
*/
export async function createDelegation(audienceDID, opts) {
const client = await getClient()
let client
const recoveryKey = opts['use-space-recovery-key']
if (recoveryKey) {
const space = await W3Space.fromMnemonic(recoveryKey, { name: '' })

// create a client with an in-memory store and the space ID as the principal
client = await getClient({ principal: ed25519.format(space.signer), store: new StoreMemory() })

// "add" the space so that we don't get an error when trying to create a delegation later
// TODO: should we update the client so that this is unnecessary? maybe the client should warn but continue
// since it is possible to create a delegation from the root with no proofs?
await client.addSpace(await space.createAuthorization(client.agent, { access: accountAccess }))
} else {
client = await getClient()
}

if (client.currentSpace() == null) {
throw new Error('no current space, use `w3 space register` to create one.')
Expand Down Expand Up @@ -453,7 +471,7 @@ export async function revokeDelegation(delegationCid, opts) {
process.exit(1)
}
const result = await client.revokeDelegation(
/** @type {import('@ucanto/interface').UCANLink} */ (cid),
/** @type {import('@ucanto/interface').UCANLink} */(cid),
{ proofs: proof ? [proof] : [] }
)
if (result.ok) {
Expand Down Expand Up @@ -532,8 +550,7 @@ export async function listProofs(opts) {
}
console.log(
chalk.dim(
`# ${proofs.length} proof${
proofs.length === 1 ? '' : 's'
`# ${proofs.length} proof${proofs.length === 1 ? '' : 's'
} for ${client.agent.did()}`
)
)
Expand Down
19 changes: 15 additions & 4 deletions lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,27 @@ export function filesizeMB(bytes) {
return `${(bytes / 1000 / 1000).toFixed(1)}MB`
}

/** Get a configured w3up store used by the CLI. */
/**
* @typedef {import('@web3-storage/access/drivers/types').Driver<import('@web3-storage/access').AgentDataExport>} Store
*/

/**
* Get a configured w3up store used by the CLI.
* @returns {Store}
*/
export function getStore() {
return new StoreConf({ profile: process.env.W3_STORE_NAME ?? 'w3cli' })
}

/**
* Get a new API client configured from env vars.
* @param {{
* principal?: string
* store?: Store
* }} options
*/
export function getClient() {
const store = getStore()
export function getClient(options = {}) {
const store = options.store || getStore()

if (process.env.W3_ACCESS_SERVICE_URL || process.env.W3_UPLOAD_SERVICE_URL) {
console.warn(
Expand Down Expand Up @@ -132,7 +143,7 @@ export function getClient() {
/** @type {import('@web3-storage/w3up-client/types').ClientFactoryOptions} */
const createConfig = { store, serviceConf }

const principal = process.env.W3_PRINCIPAL
const principal = options.principal ?? process.env.W3_PRINCIPAL
if (principal) {
createConfig.principal = Signer.parse(principal)
}
Expand Down