Skip to content

Commit

Permalink
access/delegate checks hasStorageProvider(space) in a way that provid…
Browse files Browse the repository at this point in the history
…er/add allows access/delegate
  • Loading branch information
gobengo committed Mar 7, 2023
1 parent 3b3a391 commit dc0eb51
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 7 deletions.
20 changes: 13 additions & 7 deletions packages/access-api/src/service/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ import { providerAddProvider } from './provider-add.js'
* }
*/
export function service(ctx) {
/**
* @param {Ucanto.DID<'key'>} uri
*/
const hasStorageProvider = async (uri) => {
return Boolean(await ctx.models.spaces.get(uri))
}
return {
store: uploadApi.createStoreProxy(ctx),
upload: uploadApi.createUploadProxy(ctx),
Expand All @@ -53,7 +47,19 @@ export function service(ctx) {
}
return accessDelegateProvider({
delegations: ctx.models.delegations,
hasStorageProvider,
hasStorageProvider: async (space) => {
/** @type {import('./access-delegate.js').HasStorageProvider} */
const registeredViaVoucherRedeem = async (space) =>
Boolean(await ctx.models.spaces.get(space))
/** @type {import('./access-delegate.js').HasStorageProvider} */
// eslint-disable-next-line unicorn/consistent-function-scoping
const registeredViaProviderAdd = (space) =>
ctx.models.provisions.hasStorageProvider(space)
return Boolean(
(await registeredViaProviderAdd(space)) ||
(await registeredViaVoucherRedeem(space))
)
},
})(...args)
},
},
Expand Down
96 changes: 96 additions & 0 deletions packages/access-api/test/provider-add.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ for (const accessApiVariant of /** @type {const} */ ([
/** @type {{to:string, url:string}[]} */
const emails = []
const email = createEmail(emails)
const features = new Set(['provider/add', 'access/delegate'])
return {
spaceWithStorageProvider,
emails,
features,
...createTesterFromContext(
() =>
context({
Expand Down Expand Up @@ -97,6 +99,100 @@ for (const accessApiVariant of /** @type {const} */ ([
})
})
})

if (
['provider/add', 'access/delegate'].every((f) =>
accessApiVariant.features.has(f)
)
) {
it('provider/add allows for access/delegate', async () => {
const space = await principal.ed25519.generate()
const issuer = await accessApiVariant.issuer
const service = await accessApiVariant.audience
const accountDid = /** @type {const} */ ('did:mailto:example.com:foo')
const serviceSessionAttest = await ucanto.delegate({
issuer: service,
audience: issuer,
capabilities: [
{
can: 'provider/add',
with: accountDid,
},
{
can: 'access/delegate',
with: space.did(),
},
],
})
const sessionProofs = [
await ucanto.delegate({
issuer: service,
audience: issuer,
capabilities: [
{
can: 'ucan/attest',
with: accountDid,
nb: {
// note: whole delegation is also included in 'proofs'
proof: serviceSessionAttest.cid,
},
},
],
}),
serviceSessionAttest,
]
const addStorageProvider = await ucanto
.invoke({
issuer,
audience: service,
capability: {
can: 'provider/add',
with: accountDid,
nb: {
provider: 'did:web:web3.storage:providers:w3up-alpha',
consumer: space.did(),
},
},
proofs: [
// space says issuer can provider/add with this account
await ucanto.delegate({
issuer: space,
audience: issuer,
capabilities: [
{
can: 'provider/add',
with: accountDid,
},
],
}),
...sessionProofs,
],
})
.delegate()
const addStorageProviderResult = await accessApiVariant.invoke(
addStorageProvider
)
assertNotError(addStorageProviderResult)

// storage provider added. So we should be able to delegate now
const accessDelegate = await ucanto
.invoke({
issuer,
audience: service,
capability: {
can: 'access/delegate',
with: space.did(),
nb: {
delegations: {},
},
},
proofs: [...sessionProofs],
})
.delegate()
const accessDelegateResult = await accessApiVariant.invoke(accessDelegate)
assertNotError(accessDelegateResult)
})
}
}

/**
Expand Down

0 comments on commit dc0eb51

Please sign in to comment.