-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: define
access/confirm
handler and use it in ucanto-test-utils…
… registerSpaces + validate-email handler (#530) Previously a lot of logic to handle `access/confirm` was in the `validate-email` flow, since that is the most common place we'd receive that invocation (after clicking email sent by `access/authorize` handler). However, this logic can be expressed as a `ServiceMethod` on invocation of `access/confirm`, and validate-email can call that. This allows us to also self-issue `access/confirm` in some tests, e.g. in ucanto-test-utils `registerSpaces` and send it to our service to handle, which is only enabled when node env is TEST for now. Benefits: * wherever we use ucanto-test-utils `registerSpaces`, we'll be accurately testing the `access/confirm` + `provider/add` flow (not old/deprecated `voucher/redeem`) --------- Co-authored-by: Travis Vachon <travis@dag.house>
- Loading branch information
Showing
12 changed files
with
295 additions
and
116 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import * as Ucanto from '@ucanto/interface' | ||
import * as ucanto from '@ucanto/core' | ||
import { Verifier, Absentee } from '@ucanto/principal' | ||
import { collect } from 'streaming-iterables' | ||
import * as Access from '@web3-storage/capabilities/access' | ||
import { delegationsToString } from '@web3-storage/access/encoding' | ||
import * as delegationsResponse from '../utils/delegations-response.js' | ||
|
||
/** | ||
* @typedef {import('@web3-storage/capabilities/types').AccessConfirmSuccess} AccessConfirmSuccess | ||
* @typedef {import('@web3-storage/capabilities/types').AccessConfirmFailure} AccessConfirmFailure | ||
*/ | ||
|
||
/** | ||
* @param {Ucanto.Invocation<import('@web3-storage/capabilities/src/types').AccessConfirm>} invocation | ||
*/ | ||
export function parse(invocation) { | ||
const capability = invocation.capabilities[0] | ||
// Create a absentee signer for the account that authorized the delegation | ||
const account = Absentee.from({ id: capability.nb.iss }) | ||
const agent = Verifier.parse(capability.nb.aud) | ||
return { | ||
account, | ||
agent, | ||
} | ||
} | ||
|
||
/** | ||
* @param {Ucanto.Invocation<import('@web3-storage/capabilities/src/types').AccessConfirm>} invocation | ||
* @param {import('../bindings').RouteContext} ctx | ||
* @returns {Promise<Ucanto.Result<AccessConfirmSuccess, AccessConfirmFailure>>} | ||
*/ | ||
export async function handleAccessConfirm(invocation, ctx) { | ||
const capability = invocation.capabilities[0] | ||
if (capability.with !== ctx.signer.did()) { | ||
throw new Error(`Not a valid access/confirm delegation`) | ||
} | ||
|
||
const { account, agent } = parse(invocation) | ||
|
||
// It the future we should instead render a page and allow a user to select | ||
// which delegations they wish to re-delegate. Right now we just re-delegate | ||
// everything that was requested for all of the resources. | ||
const capabilities = | ||
/** @type {ucanto.UCAN.Capabilities} */ | ||
( | ||
capability.nb.att.map(({ can }) => ({ | ||
can, | ||
with: /** @type {ucanto.UCAN.Resource} */ ('ucan:*'), | ||
})) | ||
) | ||
|
||
// create an delegation on behalf of the account with an absent signature. | ||
const delegation = await ucanto.delegate({ | ||
issuer: account, | ||
audience: agent, | ||
capabilities, | ||
expiration: Infinity, | ||
// We include all the delegations to the account so that the agent will | ||
// have delegation chains to all the delegated resources. | ||
// We should actually filter out only delegations that support delegated | ||
// capabilities, but for now we just include all of them since we only | ||
// implement sudo access anyway. | ||
proofs: await collect( | ||
ctx.models.delegations.find({ | ||
audience: account.did(), | ||
}) | ||
), | ||
}) | ||
|
||
const attestation = await Access.session.delegate({ | ||
issuer: ctx.signer, | ||
audience: agent, | ||
with: ctx.signer.did(), | ||
nb: { proof: delegation.cid }, | ||
expiration: Infinity, | ||
}) | ||
|
||
// Store the delegations so that they can be pulled with access/claim | ||
// The fact that we're storing proofs chains that we pulled from the | ||
// database is not great, but it's a tradeoff we're making for now. | ||
await ctx.models.delegations.putMany(delegation, attestation) | ||
|
||
const authorization = delegationsToString([delegation, attestation]) | ||
// Save delegations for the validation process | ||
await ctx.models.validations.putSession(authorization, agent.did()) | ||
|
||
return { | ||
delegations: delegationsResponse.encode([delegation, attestation]), | ||
} | ||
} |
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
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.