mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-03-30 15:08:28 +00:00

Fix sync Fix linter Fix tests Clean up Set default references count to 0 Fix sync Use address instead of databaseId Sync protocol Keep references to open databases in OrbitDB Fix append benchmark Initial version of heads exchange Remove Feed Fix KeyValuePersisted iterator Refactor OrbitDBAddress a bit more Add rest of the database types Refactor OrbitDB addresses Initial version for the full circle Initial structure and tests for new OrbitDB Make sure KeyStore is open when a Database is created Re-organize OrbitDB Use new databases and Log More clean up Add 'drop' event to Database Clean up OrbitDB Remove id from OrbitDB Use new KeyStore and Identities Remove storage from OrbitDB Remove migrations from OrbitDB Remove caches from OrbitDB Remove pubsub from OrbitDB
232 lines
7.5 KiB
JavaScript
232 lines
7.5 KiB
JavaScript
import assert from 'assert'
|
|
import rmrf from 'rimraf'
|
|
import OrbitDB from '../../src/OrbitDB.js'
|
|
import IdentityProvider from 'orbit-db-identity-provider'
|
|
import Keystore from 'orbit-db-keystore'
|
|
import AccessControllers from 'orbit-db-access-controllers'
|
|
import * as io from 'orbit-db-io'
|
|
// Include test utilities
|
|
import {
|
|
config,
|
|
startIpfs,
|
|
stopIpfs,
|
|
testAPIs,
|
|
connectPeers
|
|
} from 'orbit-db-test-utils'
|
|
|
|
const dbPath1 = './orbitdb/tests/orbitdb-access-controller-integration/1'
|
|
const dbPath2 = './orbitdb/tests/orbitdb-access-controller-integration/2'
|
|
|
|
Object.keys(testAPIs).forEach(API => {
|
|
describe(`orbit-db - OrbitDBAccessController Integration (${API})`, function () {
|
|
this.timeout(config.timeout)
|
|
|
|
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
|
let orbitdb1, orbitdb2
|
|
|
|
before(async () => {
|
|
rmrf.sync(dbPath1)
|
|
rmrf.sync(dbPath2)
|
|
ipfsd1 = await startIpfs(API, config.daemon1)
|
|
ipfsd2 = await startIpfs(API, config.daemon2)
|
|
ipfs1 = ipfsd1.api
|
|
ipfs2 = ipfsd2.api
|
|
|
|
// Connect the peers manually to speed up test times
|
|
const isLocalhostAddress = (addr) => addr.toString().includes('127.0.0.1')
|
|
await connectPeers(ipfs1, ipfs2, { filter: isLocalhostAddress })
|
|
|
|
const keystore1 = new Keystore(dbPath1 + '/keys')
|
|
const keystore2 = new Keystore(dbPath2 + '/keys')
|
|
|
|
id1 = await IdentityProvider.createIdentity({ id: 'A', keystore: keystore1 })
|
|
id2 = await IdentityProvider.createIdentity({ id: 'B', keystore: keystore2 })
|
|
|
|
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
|
AccessControllers,
|
|
directory: dbPath1,
|
|
identity: id1
|
|
})
|
|
|
|
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
|
AccessControllers,
|
|
directory: dbPath2,
|
|
identity: id2
|
|
})
|
|
})
|
|
|
|
after(async () => {
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
|
|
if (orbitdb2) {
|
|
await orbitdb2.stop()
|
|
}
|
|
|
|
if (ipfsd1) {
|
|
await stopIpfs(ipfsd1)
|
|
}
|
|
|
|
if (ipfsd2) {
|
|
await stopIpfs(ipfsd2)
|
|
}
|
|
})
|
|
|
|
describe('OrbitDB Integration', function () {
|
|
let db, db2
|
|
let dbManifest, acManifest
|
|
|
|
before(async () => {
|
|
db = await orbitdb1.feed('AABB', {
|
|
identity: id1,
|
|
accessController: {
|
|
type: 'orbitdb',
|
|
write: [id1.id]
|
|
}
|
|
})
|
|
|
|
db2 = await orbitdb2.feed(db.address, { identity: id2 })
|
|
await db2.load()
|
|
|
|
dbManifest = await io.read(ipfs1, db.address.root)
|
|
const hash = dbManifest.accessController.split('/').pop()
|
|
acManifest = await io.read(ipfs1, hash)
|
|
})
|
|
|
|
it('has the correct access rights after creating the database', async () => {
|
|
assert.deepStrictEqual(db.access.capabilities, {
|
|
admin: new Set([id1.id]),
|
|
write: new Set([id1.id])
|
|
})
|
|
})
|
|
|
|
it('makes database use the correct access controller', async () => {
|
|
assert.strictEqual(acManifest.params.address, db.access._db.address.toString())
|
|
})
|
|
|
|
it('saves database manifest file locally', async () => {
|
|
assert.notStrictEqual(dbManifest, null)
|
|
})
|
|
|
|
it('saves access controller manifest file locally', async () => {
|
|
assert.notStrictEqual(acManifest, null)
|
|
})
|
|
|
|
describe('database manifest', () => {
|
|
it('has correct name', async () => {
|
|
assert.strictEqual(dbManifest.name, 'AABB')
|
|
})
|
|
|
|
it('has correct type', async () => {
|
|
assert.strictEqual(dbManifest.type, 'feed')
|
|
})
|
|
|
|
it('has correct address', async () => {
|
|
assert.notStrictEqual(dbManifest.accessController, null)
|
|
assert.strictEqual(dbManifest.accessController.indexOf('/ipfs'), 0)
|
|
})
|
|
})
|
|
|
|
describe('access controller manifest', () => {
|
|
it('has correct type', async () => {
|
|
assert.strictEqual(acManifest.type, 'orbitdb')
|
|
})
|
|
|
|
it('has correct address', async () => {
|
|
assert.strictEqual(acManifest.params.address.indexOf('/orbitdb'), 0)
|
|
assert.strictEqual(acManifest.params.address.split('/').pop(), '_access')
|
|
})
|
|
})
|
|
|
|
describe('access controls', () => {
|
|
it('granting access enables to write to the database', async () => {
|
|
let err
|
|
try {
|
|
await db2.add('hello?')
|
|
assert.strictEqual('Should not end here', false)
|
|
} catch (e) {
|
|
err = e.toString()
|
|
}
|
|
|
|
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
|
|
|
const doChanges = () => {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
// Wait for the second user's AC to notify it was updated
|
|
db2.access.once('updated', async () => {
|
|
// Wait for the first user's db to replicate the update
|
|
db.events.once('replicated', () => {
|
|
// FIXME: timeout to get rid of the "libp2p node not started yet" errors
|
|
setTimeout(() => resolve(), 1000)
|
|
})
|
|
// Try adding something again
|
|
await db2.add('hello!')
|
|
})
|
|
// Give access to the second user
|
|
db.access.grant('write', id2.id)
|
|
} catch (e) {
|
|
reject(e)
|
|
}
|
|
})
|
|
}
|
|
await doChanges()
|
|
const res1 = await db.iterator().collect().map(e => e.payload.value)
|
|
const res2 = await db2.iterator().collect().map(e => e.payload.value)
|
|
assert.deepStrictEqual(res1, ['hello!'])
|
|
assert.deepStrictEqual(res2, ['hello!'])
|
|
})
|
|
|
|
it('can\'t grant access if doesn\'t have write access', async () => {
|
|
let err
|
|
try {
|
|
await db2.access.grant('write', id2.id)
|
|
} catch (e) {
|
|
err = e.toString()
|
|
}
|
|
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
|
})
|
|
|
|
it('can\'t revoke access if doesn\'t have write access', async () => {
|
|
let err
|
|
try {
|
|
await db2.access.revoke('write', id1.id)
|
|
} catch (e) {
|
|
err = e.toString()
|
|
}
|
|
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
|
})
|
|
|
|
it('revoking access disables ability to write to the database', async () => {
|
|
const getError = () => {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
// Wait for the second user's AC to notify it was updated
|
|
db2.access.once('updated', async () => {
|
|
let err
|
|
try {
|
|
// Try adding something again
|
|
await db2.add('hello?')
|
|
} catch (e) {
|
|
err = e.toString()
|
|
}
|
|
resolve(err)
|
|
})
|
|
// Revoke user's access
|
|
db.access.revoke('write', id2.id)
|
|
} catch (e) {
|
|
reject(e)
|
|
}
|
|
})
|
|
}
|
|
const err = await getError()
|
|
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
// TODO: use two separate peers for testing the AC
|
|
// TODO: add tests for revocation correctness with a database (integration tests)
|
|
})
|