diff --git a/packages/access-api/test/space-info.test.js b/packages/access-api/test/space-info.test.js index 85a6b5cf0..0db09b59b 100644 --- a/packages/access-api/test/space-info.test.js +++ b/packages/access-api/test/space-info.test.js @@ -2,6 +2,9 @@ import * as Space from '@web3-storage/capabilities/space' import assert from 'assert' import { context } from './helpers/context.js' import { createSpace } from './helpers/utils.js' +import { parseLink } from '@ucanto/core' +import * as Store from '@web3-storage/capabilities/store' +import * as Upload from '@web3-storage/capabilities/upload' // @ts-ignore import isSubset from 'is-subset' @@ -72,4 +75,215 @@ describe('space/info', function () { ) } }) + + it('should return space info with store/add as proof', async function () { + const { issuer, service, conn } = ctx + + const { space, delegation } = await createSpace( + issuer, + service, + conn, + 'space-info@dag.house' + ) + + const inv = await Space.info + .invoke({ + issuer, + audience: service, + with: space.did(), + proofs: [ + await Store.add.delegate({ + audience: issuer, + issuer: space, + with: space.did(), + proofs: [delegation], + nb: { + size: 1000, + link: parseLink('bafkqaaa'), + }, + }), + ], + }) + .execute(conn) + + if (inv?.error) { + assert.fail(inv.message) + } else { + assert.deepEqual(inv.did, space.did()) + } + }) + + it('should return space info with store/list as proof', async function () { + const { issuer, service, conn } = ctx + + const { space, delegation } = await createSpace( + issuer, + service, + conn, + 'space-info@dag.house' + ) + + const inv = await Space.info + .invoke({ + issuer, + audience: service, + with: space.did(), + proofs: [ + await Store.list.delegate({ + audience: issuer, + issuer: space, + with: space.did(), + proofs: [delegation], + }), + ], + }) + .execute(conn) + + if (inv?.error) { + assert.fail(inv.message) + } else { + assert.deepEqual(inv.did, space.did()) + } + }) + + it('should return space info with store/remove as proof', async function () { + const { issuer, service, conn } = ctx + + const { space, delegation } = await createSpace( + issuer, + service, + conn, + 'space-info@dag.house' + ) + + const inv = await Space.info + .invoke({ + issuer, + audience: service, + with: space.did(), + proofs: [ + await Store.remove.delegate({ + audience: issuer, + issuer: space, + with: space.did(), + proofs: [delegation], + nb: { + link: parseLink('bafkqaaa'), + }, + }), + ], + }) + .execute(conn) + + if (inv?.error) { + assert.fail(inv.message) + } else { + assert.deepEqual(inv.did, space.did()) + } + }) + + it('should return space info with upload/add as proof', async function () { + const { issuer, service, conn } = ctx + + const { space, delegation } = await createSpace( + issuer, + service, + conn, + 'space-info@dag.house' + ) + + const inv = await Space.info + .invoke({ + issuer, + audience: service, + with: space.did(), + proofs: [ + await Upload.add.delegate({ + audience: issuer, + issuer: space, + with: space.did(), + proofs: [delegation], + nb: { + root: parseLink('bafkqaaa'), + }, + }), + ], + }) + .execute(conn) + + if (inv?.error) { + assert.fail(inv.message) + } else { + assert.deepEqual(inv.did, space.did()) + } + }) + + it('should return space info with upload/list as proof', async function () { + const { issuer, service, conn } = ctx + + const { space, delegation } = await createSpace( + issuer, + service, + conn, + 'space-info@dag.house' + ) + + const inv = await Space.info + .invoke({ + issuer, + audience: service, + with: space.did(), + proofs: [ + await Upload.list.delegate({ + audience: issuer, + issuer: space, + with: space.did(), + proofs: [delegation], + }), + ], + }) + .execute(conn) + + if (inv?.error) { + assert.fail(inv.message) + } else { + assert.deepEqual(inv.did, space.did()) + } + }) + + it('should return space info with upload/remove as proof', async function () { + const { issuer, service, conn } = ctx + + const { space, delegation } = await createSpace( + issuer, + service, + conn, + 'space-info@dag.house' + ) + + const inv = await Space.info + .invoke({ + issuer, + audience: service, + with: space.did(), + proofs: [ + await Upload.remove.delegate({ + audience: issuer, + issuer: space, + with: space.did(), + proofs: [delegation], + nb: { + root: parseLink('bafkqaaa'), + }, + }), + ], + }) + .execute(conn) + + if (inv?.error) { + assert.fail(inv.message) + } else { + assert.deepEqual(inv.did, space.did()) + } + }) }) diff --git a/packages/capabilities/src/space.js b/packages/capabilities/src/space.js index b2447881c..28ec42b18 100644 --- a/packages/capabilities/src/space.js +++ b/packages/capabilities/src/space.js @@ -10,9 +10,10 @@ */ import { top } from './top.js' -import { store } from './store.js' +import * as Store from './store.js' import { capability, URI } from '@ucanto/validator' import { canDelegateURI, equalWith, fail } from './utils.js' +import * as Upload from './upload.js' export { top } from './top.js' @@ -32,14 +33,21 @@ const base = top.or(space) * capability that has matching `with`. This allows store service * to identify account based on any user request. */ -export const info = base.or(store).derive({ - to: capability({ - can: 'space/info', - with: URI.match({ protocol: 'did:' }), +export const info = base + .or(Store.add) + .or(Store.list) + .or(Store.remove) + .or(Upload.add) + .or(Upload.list) + .or(Upload.remove) + .derive({ + to: capability({ + can: 'space/info', + with: URI.match({ protocol: 'did:' }), + derives: equalWith, + }), derives: equalWith, - }), - derives: equalWith, -}) + }) export const recoverValidation = base.derive({ to: capability({