Update dependencies
Add access-controllers, identity Update build command Add static createInstance
This commit is contained in:
parent
4e07e9299d
commit
6226842691
6134
package-lock.json
generated
6134
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
@ -9,45 +9,51 @@
|
||||
"url": "https://github.com/orbitdb/orbit-db"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"main": "src/OrbitDB.js",
|
||||
"dependencies": {
|
||||
"cids": "^0.5.7",
|
||||
"ipfs-pubsub-1on1": "~0.0.4",
|
||||
"ipld-dag-pb": "0.14.11",
|
||||
"localstorage-down": "^0.6.7",
|
||||
"logplease": "^1.2.14",
|
||||
"multihashes": "^0.4.12",
|
||||
"orbit-db-access-controllers": "github:orbitdb/orbit-db-access-controllers",
|
||||
"orbit-db-cache": "~0.2.4",
|
||||
"orbit-db-counterstore": "~1.4.0",
|
||||
"orbit-db-docstore": "~1.4.3",
|
||||
"orbit-db-eventstore": "~1.4.0",
|
||||
"orbit-db-feedstore": "~1.4.0",
|
||||
"orbit-db-keystore": "~0.1.0",
|
||||
"orbit-db-kvstore": "~1.4.0",
|
||||
"orbit-db-counterstore": "github:orbitdb/orbit-db-counterstore",
|
||||
"orbit-db-docstore": "github:orbitdb/orbit-db-docstore",
|
||||
"orbit-db-eventstore": "github:orbitdb/orbit-db-eventstore",
|
||||
"orbit-db-feedstore": "github:orbitdb/orbit-db-feedstore",
|
||||
"orbit-db-identity-provider": "github:orbitdb/orbit-db-identity-provider",
|
||||
"orbit-db-io": "~0.0.1",
|
||||
"orbit-db-keystore": "github:orbitdb/orbit-db-keystore",
|
||||
"orbit-db-kvstore": "github:orbitdb/orbit-db-kvstore",
|
||||
"orbit-db-pubsub": "~0.5.5",
|
||||
"orbit-db-store": "~2.5.3"
|
||||
"orbit-db-store": "github:orbitdb/orbit-db-store",
|
||||
"pify": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"datastore-level": "~0.8.0",
|
||||
"go-ipfs-dep": "0.4.13",
|
||||
"ipfs": "~0.30.0",
|
||||
"ipfs-repo": "~0.22.1",
|
||||
"ipfsd-ctl": "^0.37.5",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"datastore-level": "~0.10.0",
|
||||
"go-ipfs-dep": "^0.4.18",
|
||||
"ipfs": "^0.34.4",
|
||||
"ipfs-repo": "^0.26.2",
|
||||
"ipfsd-ctl": "^0.42.0",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"mocha": "^4.0.1",
|
||||
"mocha": "^5.2.0",
|
||||
"p-each-series": "^1.0.0",
|
||||
"p-map": "^1.2.0",
|
||||
"p-map-series": "^1.0.0",
|
||||
"p-whilst": "^1.0.0",
|
||||
"remark-cli": "^5.0.0",
|
||||
"remark-validate-links": "^7.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"uglifyjs-webpack-plugin": "^1.1.4",
|
||||
"webpack": "^3.8.1"
|
||||
"webpack": "^4.25.1",
|
||||
"webpack-cli": "^3.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"examples": "npm run examples:node",
|
||||
@ -61,6 +67,6 @@
|
||||
"build:dist": "webpack --config conf/webpack.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp dist/orbitdb.min.js examples/browser/lib/orbitdb.min.js",
|
||||
"build:debug": "webpack --config conf/webpack.debug.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp dist/orbitdb.js examples/browser/lib/orbitdb.js && cp dist/orbitdb.js.map examples/browser/lib/orbitdb.js.map",
|
||||
"build:docs/toc": "markdown-toc --no-first1 -i README.md && markdown-toc --no-first1 -i API.md && markdown-toc --no-first1 -i GUIDE.md && markdown-toc --no-first1 -i CHANGELOG.md && markdown-toc --no-first1 -i FAQ.md ",
|
||||
"build:es5": "babel src --out-dir ./dist/es5/ --presets babel-preset-es2015 --plugins babel-plugin-transform-runtime"
|
||||
"build:es5": "babel src --out-dir ./dist/es5/ --presets babel-preset-env --plugins babel-plugin-transform-runtime"
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,12 @@ const DocumentStore = require('orbit-db-docstore')
|
||||
const Pubsub = require('orbit-db-pubsub')
|
||||
const Cache = require('orbit-db-cache')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const AccessController = require('./ipfs-access-controller')
|
||||
const Identities = require('orbit-db-identity-provider')
|
||||
let AccessControllers = require('orbit-db-access-controllers')
|
||||
const OrbitDBAddress = require('./orbit-db-address')
|
||||
const createDBManifest = require('./db-manifest')
|
||||
const exchangeHeads = require('./exchange-heads')
|
||||
const { isDefined, io } = require('./utils')
|
||||
|
||||
const Logger = require('logplease')
|
||||
const logger = Logger.create("orbit-db")
|
||||
@ -28,18 +30,48 @@ let databaseTypes = {
|
||||
}
|
||||
|
||||
class OrbitDB {
|
||||
constructor(ipfs, directory, options = {}) {
|
||||
constructor(ipfs, identity, options = {}) {
|
||||
if (!isDefined(ipfs))
|
||||
throw new Error('IPFS is a required argument. See https://github.com/orbitdb/orbit-db/blob/master/API.md#createinstance')
|
||||
|
||||
if (!isDefined(identity))
|
||||
throw new Error('identity is a required argument. See https://github.com/orbitdb/orbit-db/blob/master/API.md#createinstance')
|
||||
|
||||
this._ipfs = ipfs
|
||||
this.id = options.peerId || (this._ipfs._peerInfo ? this._ipfs._peerInfo.id._idB58String : 'default')
|
||||
this.identity = identity
|
||||
this.id = options.peerId
|
||||
this._pubsub = options && options.broker
|
||||
? new options.broker(this._ipfs)
|
||||
: new Pubsub(this._ipfs, this.id)
|
||||
this.stores = {}
|
||||
this.directory = directory || './orbitdb'
|
||||
this.keystore = options.keystore || Keystore.create(path.join(this.directory, this.id, '/keystore'))
|
||||
this.directory = options.directory || './orbitdb'
|
||||
this.keystore = options.keystore
|
||||
this.cache = options.cache || Cache
|
||||
this.key = this.keystore.getKey(this.id) || this.keystore.createKey(this.id)
|
||||
this.stores = {}
|
||||
this._directConnections = {}
|
||||
// AccessControllers module can be passed in to enable
|
||||
// testing with orbit-db-access-controller
|
||||
AccessControllers = options.AccessControllers || AccessControllers
|
||||
}
|
||||
|
||||
static async createInstance (ipfs, options = {}) {
|
||||
if (!isDefined(ipfs))
|
||||
throw new Error('IPFS is a required argument. See https://github.com/orbitdb/orbit-db/blob/master/API.md#createinstance')
|
||||
|
||||
const { id } = await ipfs.id()
|
||||
const directory = options.directory || './orbitdb'
|
||||
const keystore = options.keystore || Keystore.create(path.join(directory, id, '/keystore'))
|
||||
|
||||
const identity = options.identity || await Identities.createIdentity({
|
||||
id: options.id || id,
|
||||
keystore: keystore,
|
||||
})
|
||||
options = Object.assign({}, options, {
|
||||
peerId: id ,
|
||||
directory: directory,
|
||||
keystore: keystore
|
||||
})
|
||||
const orbitdb = new OrbitDB(ipfs, identity, options)
|
||||
return orbitdb
|
||||
}
|
||||
|
||||
/* Databases */
|
||||
@ -48,7 +80,7 @@ class OrbitDB {
|
||||
return this.open(address, options)
|
||||
}
|
||||
|
||||
async log (address, options) {
|
||||
async log (address, options = {}) {
|
||||
options = Object.assign({ create: true, type: 'eventlog' }, options)
|
||||
return this.open(address, options)
|
||||
}
|
||||
@ -57,12 +89,12 @@ class OrbitDB {
|
||||
return this.log(address, options)
|
||||
}
|
||||
|
||||
async keyvalue (address, options) {
|
||||
async keyvalue (address, options = {}) {
|
||||
options = Object.assign({ create: true, type: 'keyvalue' }, options)
|
||||
return this.open(address, options)
|
||||
}
|
||||
|
||||
async kvstore (address, options) {
|
||||
async kvstore (address, options = {}) {
|
||||
return this.keyvalue(address, options)
|
||||
}
|
||||
|
||||
@ -121,8 +153,7 @@ class OrbitDB {
|
||||
|
||||
let accessController
|
||||
if (options.accessControllerAddress) {
|
||||
accessController = new AccessController(this._ipfs)
|
||||
await accessController.load(options.accessControllerAddress)
|
||||
accessController = await AccessControllers.resolve(this, options.accessControllerAddress, options.accessController)
|
||||
}
|
||||
|
||||
const cache = await this._loadCache(this.directory, address)
|
||||
@ -134,9 +165,8 @@ class OrbitDB {
|
||||
onClose: this._onClose.bind(this),
|
||||
})
|
||||
|
||||
const store = new Store(this._ipfs, this.id, address, opts)
|
||||
const store = new Store(this._ipfs, this.identity, address, opts)
|
||||
store.events.on('write', this._onWrite.bind(this))
|
||||
|
||||
// ID of the store is the address as a string
|
||||
const addr = address.toString()
|
||||
this.stores[addr] = store
|
||||
@ -211,25 +241,9 @@ class OrbitDB {
|
||||
if (OrbitDBAddress.isValid(name))
|
||||
throw new Error(`Given database name is an address. Please give only the name of the database!`)
|
||||
|
||||
// Create an AccessController
|
||||
const accessController = new AccessController(this._ipfs)
|
||||
/* Disabled temporarily until we do something with the admin keys */
|
||||
// Add admins of the database to the access controller
|
||||
// if (options && options.admin) {
|
||||
// options.admin.forEach(e => accessController.add('admin', e))
|
||||
// } else {
|
||||
// // Default is to add ourselves as the admin of the database
|
||||
// accessController.add('admin', this.key.getPublic('hex'))
|
||||
// }
|
||||
// Add keys that can write to the database
|
||||
if (options && options.write && options.write.length > 0) {
|
||||
options.write.forEach(e => accessController.add('write', e))
|
||||
} else {
|
||||
// Default is to add ourselves as the admin of the database
|
||||
accessController.add('write', this.key.getPublic('hex'))
|
||||
}
|
||||
// Save the Access Controller in IPFS
|
||||
const accessControllerAddress = await accessController.save(onlyHash)
|
||||
// Create an AccessController, use IPFS AC as the default
|
||||
options.accessController = Object.assign({}, { type: 'ipfs' }, options.accessController)
|
||||
const accessControllerAddress = await AccessControllers.create(this, options.accessController.type, options.accessController || {})
|
||||
|
||||
// Save the manifest to IPFS
|
||||
const manifestHash = await createDBManifest(this._ipfs, name, type, accessControllerAddress, onlyHash)
|
||||
@ -242,8 +256,7 @@ class OrbitDB {
|
||||
|
||||
/*
|
||||
options = {
|
||||
admin: [], // array of keys that are the admins of this database (same as write access)
|
||||
write: [], // array of keys that can write to this database
|
||||
accessController: { write: [] } // array of keys that can write to this database
|
||||
directory: './orbitdb', // directory in which to place the database files
|
||||
overwrite: false, // whether we should overwrite the existing database if it exists
|
||||
}
|
||||
@ -268,7 +281,7 @@ class OrbitDB {
|
||||
throw new Error(`Database '${dbAddress}' already exists!`)
|
||||
|
||||
// Save the database locally
|
||||
await this._saveDBManifest(directory, dbAddress)
|
||||
await this._addManifestToCache(directory, dbAddress)
|
||||
|
||||
logger.debug(`Created database '${dbAddress}'`)
|
||||
|
||||
@ -291,6 +304,7 @@ class OrbitDB {
|
||||
*/
|
||||
async open (address, options = {}) {
|
||||
logger.debug(`open()`)
|
||||
|
||||
options = Object.assign({ localOnly: false, create: false }, options)
|
||||
logger.debug(`Open database '${address}'`)
|
||||
|
||||
@ -319,6 +333,7 @@ class OrbitDB {
|
||||
|
||||
// Check if we have the database
|
||||
const haveDB = await this._haveLocalData(cache, dbAddress)
|
||||
|
||||
logger.debug((haveDB ? 'Found' : 'Didn\'t find') + ` database '${dbAddress}'`)
|
||||
|
||||
// If we want to try and open the database local-only, throw an error
|
||||
@ -331,8 +346,7 @@ class OrbitDB {
|
||||
logger.debug(`Loading Manifest for '${dbAddress}'`)
|
||||
|
||||
// Get the database manifest from IPFS
|
||||
const dag = await this._ipfs.object.get(dbAddress.root)
|
||||
const manifest = JSON.parse(dag.toJSON().data)
|
||||
const manifest = await io.read(this._ipfs, dbAddress.root)
|
||||
logger.debug(`Manifest for '${dbAddress}':\n${JSON.stringify(manifest, null, 2)}`)
|
||||
|
||||
// Make sure the type from the manifest matches the type that was given as an option
|
||||
@ -340,7 +354,7 @@ class OrbitDB {
|
||||
throw new Error(`Database '${dbAddress}' is type '${manifest.type}' but was opened as '${options.type}'`)
|
||||
|
||||
// Save the database locally
|
||||
await this._saveDBManifest(directory, dbAddress)
|
||||
await this._addManifestToCache(directory, dbAddress)
|
||||
|
||||
// Open the the database
|
||||
options = Object.assign({}, options, { accessControllerAddress: manifest.accessController })
|
||||
@ -348,13 +362,12 @@ class OrbitDB {
|
||||
}
|
||||
|
||||
// Save the database locally
|
||||
async _saveDBManifest (directory, dbAddress) {
|
||||
async _addManifestToCache (directory, dbAddress) {
|
||||
const cache = await this._loadCache(directory, dbAddress)
|
||||
await cache.set(path.join(dbAddress.toString(), '_manifest'), dbAddress.root)
|
||||
logger.debug(`Saved manifest to IPFS as '${dbAddress.root}'`)
|
||||
}
|
||||
|
||||
// Loads the locally saved database information (manifest, head hashes)
|
||||
async _loadCache (directory, dbAddress) {
|
||||
let cache
|
||||
try {
|
||||
|
@ -1,96 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
class AccessController {
|
||||
constructor () {
|
||||
this._access = {
|
||||
admin: [],
|
||||
write: [],
|
||||
read: [], // Not used atm
|
||||
}
|
||||
}
|
||||
|
||||
/* Overridable functions */
|
||||
async load (address) {}
|
||||
async save () {}
|
||||
|
||||
async canAppend(entry, identityProvider){
|
||||
//verify identity?
|
||||
if (this._access.write.includes('*'))
|
||||
return true
|
||||
|
||||
if (this._access.write.includes(entry.identity.publicKey))
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/* Properties */
|
||||
get admin () {
|
||||
return this._access.admin
|
||||
}
|
||||
|
||||
get write () {
|
||||
// Both admins and write keys can write
|
||||
return this._access.write.concat(this._access.admin)
|
||||
}
|
||||
|
||||
// Not used atm
|
||||
get read () {
|
||||
return this._access.read
|
||||
}
|
||||
|
||||
/* Public Methods */
|
||||
add (access, key) {
|
||||
// if(!Object.keys(this._access).includes(access))
|
||||
// throw new Error(`unknown access level: ${access}`)
|
||||
// if (!this._access[access].includes(key))
|
||||
// this._access[access].push(key)
|
||||
|
||||
// TODO: uniques only
|
||||
switch (access) {
|
||||
case 'admin':
|
||||
this._access.admin.push(key)
|
||||
break
|
||||
case 'write':
|
||||
this._access.write.push(key)
|
||||
break
|
||||
case 'read':
|
||||
this._access.read.push(key)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
remove (access, key) {
|
||||
const without = (arr, e) => {
|
||||
const reducer = (res, val) => {
|
||||
if (val !== key)
|
||||
res.push(val)
|
||||
return res
|
||||
}
|
||||
return arr.reduce(reducer, [])
|
||||
}
|
||||
|
||||
// if(!Object.keys(this._access).includes(access))
|
||||
// throw new Error(`unknown access level: ${access}`)
|
||||
// if (this._access[access].includes(key))
|
||||
// this._access[access] = without(this._access[access], key)
|
||||
|
||||
switch (access) {
|
||||
case 'admin':
|
||||
this._access.admin = without(this._access.admin, key)
|
||||
break
|
||||
case 'write':
|
||||
this._access.write = without(this._access.write, key)
|
||||
break
|
||||
case 'read':
|
||||
this._access.read = without(this._access.read, key)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AccessController
|
@ -1,5 +1,5 @@
|
||||
const path = require('path')
|
||||
const { DAGNode } = require('ipld-dag-pb')
|
||||
const io = require('orbit-db-io')
|
||||
|
||||
// Creates a DB manifest file and saves it in IPFS
|
||||
const createDBManifest = async (ipfs, name, type, accessControllerAddress, onlyHash) => {
|
||||
@ -8,21 +8,8 @@ const createDBManifest = async (ipfs, name, type, accessControllerAddress, onlyH
|
||||
type: type,
|
||||
accessController: path.join('/ipfs', accessControllerAddress),
|
||||
}
|
||||
let dag
|
||||
const manifestJSON = JSON.stringify(manifest)
|
||||
if (onlyHash) {
|
||||
dag = await new Promise(resolve => {
|
||||
DAGNode.create(Buffer.from(manifestJSON), (err, n) => {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
resolve(n)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
dag = await ipfs.object.put(Buffer.from(manifestJSON))
|
||||
}
|
||||
return dag.toJSON().multihash.toString()
|
||||
|
||||
return io.write(ipfs, 'dag-cbor', manifest, { onlyHash })
|
||||
}
|
||||
|
||||
module.exports = createDBManifest
|
||||
|
@ -1,53 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const AccessController = require('./access-controller')
|
||||
const { DAGNode } = require('ipld-dag-pb')
|
||||
|
||||
|
||||
class IPFSAccessController extends AccessController {
|
||||
constructor (ipfs) {
|
||||
super()
|
||||
this._ipfs = ipfs
|
||||
}
|
||||
|
||||
async load (address) {
|
||||
// Transform '/ipfs/QmPFtHi3cmfZerxtH9ySLdzpg1yFhocYDZgEZywdUXHxFU'
|
||||
// to 'QmPFtHi3cmfZerxtH9ySLdzpg1yFhocYDZgEZywdUXHxFU'
|
||||
if (address.indexOf('/ipfs') === 0)
|
||||
address = address.split('/')[2]
|
||||
|
||||
try {
|
||||
const dag = await this._ipfs.object.get(address)
|
||||
const obj = JSON.parse(dag.toJSON().data)
|
||||
this._access = obj
|
||||
} catch (e) {
|
||||
console.log("ACCESS ERROR:", e)
|
||||
}
|
||||
}
|
||||
|
||||
async save (onlyHash) {
|
||||
let hash
|
||||
try {
|
||||
const access = JSON.stringify(this._access, null, 2)
|
||||
let dag
|
||||
if (onlyHash) {
|
||||
dag = await new Promise(resolve => {
|
||||
DAGNode.create(Buffer.from(access), (err, n) => {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
resolve(n)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
dag = await this._ipfs.object.put(new Buffer(access))
|
||||
}
|
||||
hash = dag.toJSON().multihash.toString()
|
||||
} catch (e) {
|
||||
console.log("ACCESS ERROR:", e)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = IPFSAccessController
|
@ -1,7 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const multihash = require('multihashes')
|
||||
const CID = require('cids')
|
||||
|
||||
const notEmpty = e => e !== '' && e !== ' '
|
||||
|
||||
class OrbitDBAddress {
|
||||
constructor (root, path) {
|
||||
@ -14,14 +16,19 @@ class OrbitDBAddress {
|
||||
}
|
||||
|
||||
static isValid (address) {
|
||||
const containsProtocolPrefix = (e, i) => !((i === 0 || i === 1) && address.toString().indexOf('/orbit') === 0 && e === 'orbitdb')
|
||||
|
||||
const parts = address.toString()
|
||||
.split('/')
|
||||
.filter((e, i) => !((i === 0 || i === 1) && address.toString().indexOf('/orbit') === 0 && e === 'orbitdb'))
|
||||
.filter(e => e !== '' && e !== ' ')
|
||||
.filter(containsProtocolPrefix)
|
||||
.filter(notEmpty)
|
||||
|
||||
let accessControllerHash
|
||||
|
||||
const accessControllerHash = parts[0].indexOf('Qm') > -1 ? multihash.fromB58String(parts[0]) : null
|
||||
try {
|
||||
multihash.validate(accessControllerHash)
|
||||
accessControllerHash = (parts[0].indexOf('zd') > -1 || parts[0].indexOf('Qm') > -1)
|
||||
? new CID(parts[0]).toBaseEncodedString()
|
||||
: null
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
|
9
src/utils/index.js
Normal file
9
src/utils/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
const isDefined = require('./is-defined')
|
||||
const io = require('orbit-db-io')
|
||||
|
||||
module.exports = {
|
||||
isDefined,
|
||||
io
|
||||
}
|
5
src/utils/is-defined.js
Normal file
5
src/utils/is-defined.js
Normal file
@ -0,0 +1,5 @@
|
||||
'use strict'
|
||||
|
||||
const isDefined = (arg) => arg !== undefined && arg !== null
|
||||
|
||||
module.exports = isDefined
|
Loading…
x
Reference in New Issue
Block a user