Fix OrbitDBAccessController address and return values

This commit is contained in:
haad 2023-07-29 08:41:13 +03:00
parent af57db4337
commit 5032415e01
5 changed files with 105 additions and 21 deletions

View File

@ -2,8 +2,8 @@
* @namespace AccessControllers-OrbitDB
* @memberof module:AccessControllers
*/
import ensureACAddress from '../utils/ensure-ac-address.js'
import IPFSAccessController from './ipfs.js'
import { createId } from '../utils/index.js'
const type = 'orbitdb'
@ -32,12 +32,12 @@ const type = 'orbitdb'
* IPFSAccessController function.
* @memberof module:AccessControllers
*/
const OrbitDBAccessController = ({ write } = {}) => async ({ orbitdb, identities, address }) => {
address = address || 'default-access-controller'
const OrbitDBAccessController = ({ write } = {}) => async ({ orbitdb, identities, address, name }) => {
address = address || name || await createId(64)
write = write || [orbitdb.identity.id]
// Force '<address>/_access' naming for the database
const db = await orbitdb.open(ensureACAddress(address), { type: 'keyvalue', AccessController: IPFSAccessController({ write }) })
// Open the database used for access information
const db = await orbitdb.open(address, { type: 'keyvalue', AccessController: IPFSAccessController({ write }) })
address = db.address
/**
@ -90,7 +90,7 @@ const OrbitDBAccessController = ({ write } = {}) => async ({ orbitdb, identities
..._capabilities,
// Add the root access controller's 'write' access list
// as admins on this controller
...{ admin: new Set([...(_capabilities.admin || []), ...write]) }
...{ admin: new Set([...(_capabilities.admin || []), ...db.access.write]) }
}).forEach(toSet)
return _capabilities
@ -117,6 +117,15 @@ const OrbitDBAccessController = ({ write } = {}) => async ({ orbitdb, identities
await db.close()
}
/**
* Drop the underlying access control database.
* @memberof module:AccessControllers.AccessControllers-OrbitDB
* @instance
*/
const drop = async () => {
await db.drop()
}
/**
* Checks whether an identity has a capability.
* @param {string} capability A capability (e.g. write).
@ -174,6 +183,7 @@ const OrbitDBAccessController = ({ write } = {}) => async ({ orbitdb, identities
grant,
revoke,
close,
drop,
events: db.events
}
}

View File

@ -164,6 +164,9 @@ const Database = async ({ ipfs, identity, address, name, access, directory, meta
await sync.stop()
await queue.onIdle()
await log.close()
if (access && access.close) {
await access.close()
}
events.emit('close')
}
@ -176,6 +179,9 @@ const Database = async ({ ipfs, identity, address, name, access, directory, meta
const drop = async () => {
await queue.onIdle()
await log.clear()
if (access && access.drop) {
await access.drop()
}
events.emit('drop')
}

View File

@ -116,9 +116,8 @@ const OrbitDB = async ({ ipfs, id, identities, directory } = {}) => {
const addr = OrbitDBAddress(address)
manifest = await manifestStore.get(addr.hash)
const acType = manifest.accessController.split('/', 2).pop()
const acAddress = manifest.accessController.replaceAll(`/${acType}/`, '')
AccessController = getAccessController(acType)()
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities, address: acAddress })
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities, address: manifest.accessController })
name = manifest.name
type = type || manifest.type
meta = manifest.meta
@ -126,7 +125,7 @@ const OrbitDB = async ({ ipfs, id, identities, directory } = {}) => {
// If the address given was not valid, eg. just the name of the database
type = type || DefaultDatabaseType
AccessController = AccessController || DefaultAccessController()
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities })
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities, name: address })
const m = await manifestStore.create({ name: address, type, accessController: accessController.address, meta })
manifest = m.manifest
address = OrbitDBAddress(m.hash)

View File

@ -1,8 +0,0 @@
import pathJoin from './path-join.js'
export default address => {
const suffix = address.toString().split('/').pop()
return suffix === '_access'
? address
: pathJoin(address, '/_access')
}

View File

@ -1,4 +1,4 @@
import { strictEqual } from 'assert'
import { strictEqual, notStrictEqual } from 'assert'
import rmrf from 'rimraf'
import path from 'path'
import * as IPFS from 'ipfs-core'
@ -185,7 +185,7 @@ describe('Write Permissions', function () {
await db2.close()
})
it('uses an OrbitDB access controller to manage access', async () => {
it('uses an OrbitDB access controller to manage access - one writer', async () => {
let connected = false
let updateCount = 0
@ -198,7 +198,48 @@ describe('Write Permissions', function () {
}
const db1 = await orbitdb1.open('write-test', { AccessController: OrbitDBAccessController() })
const db2 = await orbitdb2.open(db1.address, { AccessController: OrbitDBAccessController() })
const db2 = await orbitdb2.open(db1.address)
db2.events.on('join', onConnected)
db2.events.on('update', onUpdate)
await waitFor(() => connected, () => true)
await db1.add('record 1')
let err
try {
await db2.add('record 2')
} catch (e) {
err = e
}
await waitFor(() => updateCount === 1, () => true)
strictEqual((await db1.all()).length, (await db2.all()).length)
notStrictEqual(err, undefined)
strictEqual(err.toString().endsWith('is not allowed to write to the log'), true)
await db1.close()
await db2.close()
})
it('uses an OrbitDB access controller to manage access - two writers', async () => {
let connected = false
let updateCount = 0
const onConnected = async (peerId, heads) => {
connected = true
}
const onUpdate = async (entry) => {
++updateCount
}
const db1 = await orbitdb1.open('write-test', { AccessController: OrbitDBAccessController() })
const db2 = await orbitdb2.open(db1.address)
db2.events.on('join', onConnected)
db2.events.on('update', onUpdate)
@ -206,7 +247,6 @@ describe('Write Permissions', function () {
await waitFor(() => connected, () => true)
await db1.access.grant('write', db2.identity.id)
await db2.access.grant('write', db1.identity.id)
await db1.add('record 1')
await db2.add('record 2')
@ -218,4 +258,41 @@ describe('Write Permissions', function () {
await db1.close()
await db2.close()
})
it('OrbitDB access controller address is deterministic', async () => {
let connected = false
let updateCount = 0
const onConnected = async (peerId, heads) => {
connected = true
}
const onUpdate = async (entry) => {
++updateCount
}
let db1 = await orbitdb1.open('write-test', { AccessController: OrbitDBAccessController() })
let db2 = await orbitdb2.open(db1.address)
const addr = db1.address
db2.events.on('join', onConnected)
db2.events.on('update', onUpdate)
await waitFor(() => connected, () => true)
await db1.add('record 1')
await waitFor(() => updateCount === 1, () => true)
strictEqual((await db1.all()).length, (await db2.all()).length)
await db1.close()
await db2.close()
db1 = await orbitdb1.open('write-test', { AccessController: OrbitDBAccessController() })
db2 = await orbitdb2.open(db1.address)
strictEqual(db1.address, addr)
})
})