-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Use Indexing Service when feature flag is present (#132)
storacha/project-tracking#140 Depends on storacha/blob-fetcher#19 and storacha/upload-service#57 When `ff=indexing-service` is given in the gateway URL, Freeway will use the Indexing Service to locate blobs.
- Loading branch information
Showing
15 changed files
with
2,235 additions
and
1,115 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
declare module '@web3-storage/w3cli/lib.js' { | ||
import { Client } from '@web3-storage/w3up-client' | ||
declare module '@storacha/cli/lib.js' { | ||
import { Client } from '@storacha/client' | ||
export declare function getClient(): Promise<Client> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,137 @@ | ||
import sade from 'sade' | ||
import { getClient } from '@web3-storage/w3cli/lib.js' | ||
import { Schema } from '@ucanto/core' | ||
import { getClient } from '@storacha/cli/lib.js' | ||
import { Space } from '@web3-storage/capabilities' | ||
import * as serve from '../src/capabilities/serve.js' | ||
|
||
const cli = sade('delegate-serve.js [space] [token] [accountDID] [gatewayDID]') | ||
const MailtoDID = | ||
/** @type {import('@ucanto/validator').StringSchema<`did:mailto:${string}:${string}`, unknown>} */ ( | ||
Schema.text({ pattern: /^did:mailto:.*:.*$/ }) | ||
) | ||
|
||
cli | ||
.option('--space', 'The space DID to delegate. If not provided, a new space will be created.') | ||
.option('--token', 'The auth token to use. If not provided, the delegation will not be authenticated.') | ||
sade('delegate-serve.js [space]') | ||
.option( | ||
'--token', | ||
'The auth token to use. If not provided, the delegation will not be authenticated.' | ||
) | ||
.option('--accountDID', 'The account DID to use when creating a new space.') | ||
.option('--gatewayDID', 'The gateway DID to use when delegating the space/content/serve capability. Defaults to did:web:staging.w3s.link.') | ||
.option( | ||
'--gatewayDID', | ||
'The gateway DID to use when delegating the space/content/serve capability. Defaults to did:web:staging.w3s.link.' | ||
) | ||
.describe( | ||
`Delegates ${Space.contentServe.can} to the Gateway for a test space generated by the script, with an optional auth token. Outputs a base64url string suitable for the stub_delegation query parameter. Pipe the output to pbcopy or similar for the quickest workflow.` | ||
`Delegates ${Space.contentServe.can} to the Gateway for a test space generated by the script, with an optional auth token. Outputs a base64url string suitable for the stub_delegation query parameter.` | ||
) | ||
.action(async (space, token, accountDID, gatewayDID, options) => { | ||
const { space: spaceOption, token: tokenOption, accountDID: accountDIDOption, gatewayDID: gatewayDIDOption } = options | ||
space = spaceOption || undefined | ||
token = tokenOption || undefined | ||
accountDID = accountDIDOption || undefined | ||
gatewayDID = gatewayDIDOption || 'did:web:staging.w3s.link' | ||
const client = await getClient() | ||
.action( | ||
/** | ||
* @param {string} [space] | ||
* @param {object} [options] | ||
* @param {string} [options.token] | ||
* @param {string} [options.accountDID] | ||
* @param {string} [options.gatewayDID] | ||
*/ | ||
async ( | ||
space, | ||
{ token, accountDID, gatewayDID = 'did:web:staging.w3s.link' } = {} | ||
) => { | ||
const client = await getClient() | ||
|
||
space ??= await createSpace(client, accountDID) | ||
|
||
let spaceDID | ||
let proofs = [] | ||
if (!space) { | ||
const provider = /** @type {`did:web:${string}`} */ (client.defaultProvider()) | ||
const account = client.accounts()[accountDID] | ||
const newSpace = await client.agent.createSpace('test') | ||
const provision = await account.provision(newSpace.did(), { provider }) | ||
if (provision.error) throw provision.error | ||
await newSpace.save() | ||
const authProof = await newSpace.createAuthorization(client.agent) | ||
proofs = [authProof] | ||
spaceDID = newSpace.did() | ||
} else { | ||
client.addSpace(space) | ||
spaceDID = space | ||
proofs = client.proofs([ | ||
if (!Schema.did({}).is(space)) { | ||
throw new Error(`Invalid space DID: ${space}`) | ||
} | ||
|
||
const proofs = client.proofs([ | ||
{ | ||
can: Space.contentServe.can, | ||
with: spaceDID | ||
with: space | ||
} | ||
]) | ||
} | ||
|
||
/** @type {import('@ucanto/client').Principal<`did:${string}:${string}`>} */ | ||
const gatewayIdentity = { | ||
did: () => gatewayDID | ||
} | ||
if (proofs.length === 0) { | ||
throw new Error( | ||
`No proofs found. Are you authorized to ${serve.star.can} ${space}?` | ||
) | ||
} | ||
|
||
if (!Schema.did({}).is(gatewayDID)) { | ||
throw new Error(`Invalid gateway DID: ${gatewayDID}`) | ||
} | ||
|
||
// @ts-expect-error - The client still needs to be updated to support the capability type | ||
const delegation = await client.createDelegation(gatewayIdentity, [Space.contentServe.can], { | ||
expiration: Infinity, | ||
proofs | ||
}) | ||
const gatewayIdentity = { | ||
did: () => gatewayDID | ||
} | ||
|
||
await client.capability.access.delegate({ | ||
delegations: [delegation] | ||
}) | ||
// NOTE: This type assertion is wrong. It's a hack to let us use this | ||
// ability. `client.createDelegation` currently only accepts abilities it | ||
// knows about. That should probably be expanded, but this little script | ||
// isn't going to be the reason to go change that, as it involves updating | ||
// multiple packages. | ||
const ability = /** @type {"*"} */ (Space.contentServe.can) | ||
|
||
client.setCurrentSpace(space) | ||
const delegation = await client.createDelegation( | ||
gatewayIdentity, | ||
[ability], | ||
{ | ||
expiration: Infinity, | ||
proofs | ||
} | ||
) | ||
|
||
await client.capability.access.delegate({ | ||
delegations: [delegation] | ||
}) | ||
|
||
const carResult = await delegation.archive() | ||
if (carResult.error) throw carResult.error | ||
const base64Url = Buffer.from(carResult.ok).toString('base64url') | ||
process.stdout.write( | ||
`Agent Proofs: ${proofs | ||
.flatMap((p) => p.capabilities) | ||
.map((c) => `${c.can} with ${c.with}`) | ||
.join('\n')}\n` | ||
) | ||
process.stdout.write(`Issuer: ${client.agent.issuer.did()}\n`) | ||
process.stdout.write(`Audience: ${gatewayIdentity.did()}\n`) | ||
process.stdout.write(`Space: ${space}\n`) | ||
process.stdout.write(`Token: ${token ?? 'none'}\n`) | ||
process.stdout.write( | ||
`Delegation: ${delegation.capabilities | ||
.map((c) => `${c.can} with ${c.with}`) | ||
.join('\n')}\n` | ||
) | ||
process.stdout.write( | ||
`Stubs: stub_space=${space}&stub_delegation=${base64Url}&authToken=${ | ||
token ?? '' | ||
}\n` | ||
) | ||
} | ||
) | ||
.parse(process.argv) | ||
|
||
const carResult = await delegation.archive() | ||
if (carResult.error) throw carResult.error | ||
const base64Url = Buffer.from(carResult.ok).toString('base64url') | ||
process.stdout.write(`Agent Proofs: ${proofs.flatMap(p => p.capabilities).map(c => `${c.can} with ${c.with}`).join('\n')}\n`) | ||
process.stdout.write(`Issuer: ${client.agent.issuer.did()}\n`) | ||
process.stdout.write(`Audience: ${gatewayIdentity.did()}\n`) | ||
process.stdout.write(`Space: ${spaceDID}\n`) | ||
process.stdout.write(`Token: ${token ?? 'none'}\n`) | ||
process.stdout.write(`Delegation: ${delegation.capabilities.map(c => `${c.can} with ${c.with}`).join('\n')}\n`) | ||
process.stdout.write(`Stubs: stub_space=${spaceDID}&stub_delegation=${base64Url}&authToken=${token ?? ''}\n`) | ||
}) | ||
/** | ||
* @param {import('@storacha/client').Client} client | ||
* @param {string} [accountDID] | ||
*/ | ||
async function createSpace (client, accountDID) { | ||
const provider = client.defaultProvider() | ||
if (!Schema.did({ method: 'web' }).is(provider)) { | ||
throw new Error(`Invalid provider DID: ${provider}`) | ||
} | ||
if (!accountDID) { | ||
throw new Error('Must provide an account DID to create a space') | ||
} | ||
|
||
cli.parse(process.argv) | ||
if (!MailtoDID.is(accountDID)) { | ||
throw new Error(`Invalid account DID: ${accountDID}`) | ||
} | ||
const account = client.accounts()[accountDID] | ||
const newSpace = await client.agent.createSpace('test') | ||
const provision = await account.provision(newSpace.did(), { provider }) | ||
if (provision.error) throw provision.error | ||
await newSpace.save() | ||
await newSpace.createAuthorization(client.agent) | ||
return newSpace.did() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.