diff --git a/packages/w3up-client/src/client.js b/packages/w3up-client/src/client.js index 956cf2732..f906cc434 100644 --- a/packages/w3up-client/src/client.js +++ b/packages/w3up-client/src/client.js @@ -254,9 +254,6 @@ export class Client extends Base { * * @typedef {object} CreateOptions * @property {Account.Account} [account] - * @property {boolean} [unauthorizeGateway] - If true, the gateway will not be authorized to serve content from the space. - * @property {`did:web:${string}`} [gateway] - The gateway to be authorized to serve content from the space. If not provided, the default did:web:w3s.link gateway will be authorized. - * @property {number} [gatewayExpiration] - The time in seconds to expire the gateway authorization. * * @param {string} name * @param {CreateOptions} options @@ -296,13 +293,6 @@ export class Client extends Base { } } - if (!options.unauthorizeGateway) { - await this.authorizeGateway(space, { - gateway: options.gateway, - expiration: options.gatewayExpiration, - }) - } - return space } @@ -315,25 +305,23 @@ export class Client extends Base { * @param {object} [options] - Options for the authorization. * @param {`did:web:${string}`} [options.gateway] - The Web DID of the gateway to authorize. If not provided, the default `did:web:w3s.link` gateway will be authorized. * @param {number} [options.expiration] - The time in seconds to expire the authorization. - * @returns {Promise} + * @returns {Promise>} Resolves with the AgentDelegation instance once the gateway is successfully authorized. */ async authorizeGateway(space, options = {}) { const currentSpace = this.currentSpace() try { - if (currentSpace && currentSpace.did() !== space.did()) { - // Set the current space to the space we are authorizing the gateway for - await this.setCurrentSpace(space.did()) - } + // Set the current space to the space we are authorizing the gateway for + await this.setCurrentSpace(space.did()) - // Authorize the agent to access the space const authProof = await space.createAuthorization(this.agent) - // Create a delegation for the Gateway to serve content from the space + /** @type {import('@ucanto/client').Principal<`did:${string}:${string}`>} */ + const gateway = { + did: () => options.gateway ?? `did:web:w3s.link`, + } + const delegation = await this.createDelegation( - /** @type {import('@ucanto/client').Principal<`did:${string}:${string}`>} */ - { - did: () => options.gateway ?? `did:web:w3s.link`, - }, + gateway, [SpaceCapabilities.contentServe.can], { expiration: options.expiration ?? Infinity, @@ -341,11 +329,11 @@ export class Client extends Base { } ) - // Authorize the gateway to serve content from the space const result = await this.capability.access.delegate({ delegations: [delegation], }) + /* c8 ignore next 8 - can't mock error */ if (result.error) { throw new Error( `failed to authorize gateway: ${result.error.message}`, @@ -356,10 +344,9 @@ export class Client extends Base { } // TODO: save the delegation into the DelegationsStore - // delegation + return delegation } finally { - // Reset the current space to the original space - if (currentSpace && currentSpace.did() !== space.did()) { + if (currentSpace) { await this.setCurrentSpace(currentSpace.did()) } } diff --git a/packages/w3up-client/test/capability/space.test.js b/packages/w3up-client/test/capability/space.test.js index b288b8afc..d25f447db 100644 --- a/packages/w3up-client/test/capability/space.test.js +++ b/packages/w3up-client/test/capability/space.test.js @@ -142,7 +142,7 @@ export const SpaceClient = Test.withContext({ assert.equal(egressRecord.bytes, car.size, 'bytes should be the same') assert.equal( new Date(egressRecord.servedAt).getTime(), - Math.floor(new Date(egressData.servedAt).getTime() / 1000) * 1000, + Math.floor(new Date(egressData.servedAt).getTime() / 1000), 'servedAt should be the same' ) assert.ok(egressRecord.cause.toString(), 'cause should be a link') @@ -252,7 +252,7 @@ export const SpaceClient = Test.withContext({ assert.equal(egressRecord.bytes, car.size, 'bytes should be the same') assert.equal( new Date(egressRecord.servedAt).getTime(), - Math.floor(new Date(egressData.servedAt).getTime() / 1000) * 1000, + Math.floor(new Date(egressData.servedAt).getTime() / 1000), 'servedAt should be the same' ) assert.ok(egressRecord.cause.toString(), 'cause should be a link') @@ -364,7 +364,7 @@ export const SpaceClient = Test.withContext({ assert.equal(egressRecord.bytes, car.size, 'bytes should be the same') assert.equal( new Date(egressRecord.servedAt).getTime(), - Math.floor(new Date(egressData.servedAt).getTime() / 1000) * 1000, + Math.floor(new Date(egressData.servedAt).getTime() / 1000), 'servedAt should be the same' ) assert.ok(egressRecord.cause.toString(), 'cause should be a link') @@ -476,7 +476,7 @@ export const SpaceClient = Test.withContext({ assert.equal(egressRecord.bytes, car.size, 'bytes should be the same') assert.equal( new Date(egressRecord.servedAt).getTime(), - Math.floor(new Date(egressData.servedAt).getTime() / 1000) * 1000, + Math.floor(new Date(egressData.servedAt).getTime() / 1000), 'servedAt should be the same' ) assert.ok(egressRecord.cause.toString(), 'cause should be a link') diff --git a/packages/w3up-client/test/client.test.js b/packages/w3up-client/test/client.test.js index 7869aa2f0..df137dddf 100644 --- a/packages/w3up-client/test/client.test.js +++ b/packages/w3up-client/test/client.test.js @@ -15,6 +15,7 @@ import { receiptsEndpoint } from './helpers/utils.js' import { Absentee } from '@ucanto/principal' import { DIDMailto } from '../src/capability/access.js' import { confirmConfirmationUrl } from '../../upload-api/test/helpers/utils.js' +import * as SpaceCapability from '@web3-storage/capabilities/space' /** @type {Test.Suite} */ export const testClient = { @@ -528,6 +529,45 @@ export const testClient = { ) }, }), + authorizeGateway: Test.withContext({ + 'should authorize a gateway to serve content from a space': async ( + assert, + { client, mail, grantAccess } + ) => { + // Step 1: Create a client for Alice and login + const aliceEmail = 'alice@web.mail' + const aliceLogin = client.login(aliceEmail) + const message = await mail.take() + assert.deepEqual(message.to, aliceEmail) + await grantAccess(message) + const aliceAccount = await aliceLogin + + // Step 2: Alice creates a space + const spaceA = await client.createSpace('authorize-gateway-space', { + account: aliceAccount, + }) + assert.ok(spaceA) + await client.setCurrentSpace(spaceA.did()) + + // Step 3: Authorize the gateway to serve content from the space + const delegation = await client.authorizeGateway(spaceA, { + gateway: 'did:web:staging.w3s.link', + expiration: Infinity, + }) + assert.ok(delegation) + + // Step 4: Find the delegation for the default gateway + assert.equal(delegation.audience.did(), 'did:web:staging.w3s.link') + assert.ok( + delegation.capabilities.some( + // @ts-expect-error + (c) => + c.can === SpaceCapability.contentServe.can && + c.with === spaceA.did() + ) + ) + }, + }), proofs: { 'should get proofs': async (assert) => { const alice = new Client(await AgentData.create())