mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-06-06 14:16:37 +00:00
feat: Expose identity provider managers. (#75)
* feat: Expose identity provider managers. * refactor: Remove unnecessary provider tools. * refactor: Match AC management to other management mechanisms (e.g. Identity Providers).
This commit is contained in:
parent
794136c762
commit
b9e573dc6d
@ -21,12 +21,12 @@ import IPFSAccessController from './ipfs.js'
|
||||
import OrbitDBAccessController from './orbitdb.js'
|
||||
|
||||
/**
|
||||
* An array of available access controller types.
|
||||
* @name types
|
||||
* An array of available access controllers.
|
||||
* @name accessControllers
|
||||
* @†ype []
|
||||
* @return [] An array of access controller types.
|
||||
* @return [] An array of access controllers.
|
||||
*/
|
||||
const types = {
|
||||
const accessControllers = {
|
||||
ipfs: IPFSAccessController,
|
||||
orbitdb: OrbitDBAccessController
|
||||
}
|
||||
@ -36,25 +36,15 @@ const types = {
|
||||
* @param {string} type A valid access controller type.
|
||||
* @return {AccessController} The access controller module.
|
||||
*/
|
||||
const get = (type) => {
|
||||
if (!isSupported(type)) {
|
||||
const getAccessController = (type) => {
|
||||
if (!Object.keys(accessControllers).includes(type)) {
|
||||
throw new Error(`AccessController type '${type}' is not supported`)
|
||||
}
|
||||
return types[type]
|
||||
return accessControllers[type]
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the access controller exists.
|
||||
* @param {string} type A valid access controller type.
|
||||
* @return {boolean} True if the access controller exists, false otherwise.
|
||||
*/
|
||||
const isSupported = type => {
|
||||
return Object.keys(types).includes(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an access controller module to the list of supported access controller
|
||||
* types.
|
||||
* Adds an access controller module to the list of supported access controller.
|
||||
* @param {AccessController} accessController A compatible access controller
|
||||
* module.
|
||||
* @throws Access controller `type` already added if the access controller is
|
||||
@ -62,8 +52,8 @@ const isSupported = type => {
|
||||
* @throws Given AccessController class needs to implement: type if the access
|
||||
* controller module does not implement a type property.
|
||||
*/
|
||||
const add = (accessController) => {
|
||||
if (types[accessController.type]) {
|
||||
const addAccessController = (accessController) => {
|
||||
if (accessControllers[accessController.type]) {
|
||||
throw new Error(`Access controller '${accessController.type}' already added.`)
|
||||
}
|
||||
|
||||
@ -71,21 +61,20 @@ const add = (accessController) => {
|
||||
throw new Error('Given AccessController class needs to implement: type.')
|
||||
}
|
||||
|
||||
types[accessController.type] = accessController
|
||||
accessControllers[accessController.type] = accessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an access controller from the types list.
|
||||
* Removes an access controller from the list.
|
||||
* @param {string} type A valid access controller type.
|
||||
*/
|
||||
const remove = type => {
|
||||
delete types[type]
|
||||
const removeAccessController = type => {
|
||||
delete accessControllers[type]
|
||||
}
|
||||
|
||||
export {
|
||||
types,
|
||||
get,
|
||||
isSupported,
|
||||
add,
|
||||
remove
|
||||
accessControllers,
|
||||
getAccessController,
|
||||
addAccessController,
|
||||
removeAccessController
|
||||
}
|
||||
|
@ -4,9 +4,8 @@
|
||||
* Identities provides a framework for generating and managing identity
|
||||
* details and providers.
|
||||
*/
|
||||
|
||||
import Identity, { isIdentity, isEqual, decodeIdentity } from './identity.js'
|
||||
import { PublicKeyIdentityProvider } from './providers/index.js'
|
||||
import { getProviderFor } from './providers/index.js'
|
||||
// import DIDIdentityProvider from './identity-providers/did.js'
|
||||
// import EthIdentityProvider from './identity-providers/ethereum.js'
|
||||
import KeyStore, { signMessage, verifyMessage } from '../key-store.js'
|
||||
@ -14,13 +13,8 @@ import { LRUStorage, IPFSBlockStorage, MemoryStorage, ComposedStorage } from '..
|
||||
import pathJoin from '../utils/path-join.js'
|
||||
|
||||
const DefaultProviderType = 'publickey'
|
||||
const DefaultIdentityKeysPath = pathJoin('./orbitdb', 'identities')
|
||||
|
||||
const supportedTypes = {
|
||||
publickey: PublicKeyIdentityProvider
|
||||
// [DIDIdentityProvider.type]: DIDIdentityProvider,
|
||||
// [EthIdentityProvider.type]: EthIdentityProvider
|
||||
}
|
||||
const DefaultIdentityKeysPath = pathJoin('./orbitdb', 'identities')
|
||||
|
||||
/**
|
||||
* Creates an instance of Identities.
|
||||
@ -167,68 +161,6 @@ const Identities = async ({ keystore, path, storage, ipfs } = {}) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an identity provider is supported.
|
||||
* @param {string} type The identity provider type.
|
||||
* @return {boolean} True if the identity provider is supported, false
|
||||
* otherwise.
|
||||
* @static
|
||||
*/
|
||||
const isProviderSupported = (type) => {
|
||||
return Object.keys(supportedTypes).includes(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an identity provider.
|
||||
* @param {string} type The identity provider type.
|
||||
* @return {IdentityProvider} The IdentityProvider module corresponding to
|
||||
* type.
|
||||
* @throws IdentityProvider type is not supported if the identity provider is
|
||||
* not supported.
|
||||
* @static
|
||||
*/
|
||||
const getProviderFor = (type) => {
|
||||
if (!isProviderSupported(type)) {
|
||||
throw new Error(`IdentityProvider type '${type}' is not supported`)
|
||||
}
|
||||
|
||||
return supportedTypes[type]
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an identity provider.
|
||||
* @param {IdentityProvider} IdentityProvider The identity provider to add.
|
||||
* @throws IdentityProvider must be given as an argument if no module is
|
||||
* provided.
|
||||
* @throws 'Given IdentityProvider doesn't have a field 'type' if the
|
||||
* IdentityProvider does not include a type property.
|
||||
* @static
|
||||
*/
|
||||
const addIdentityProvider = (IdentityProvider) => {
|
||||
if (!IdentityProvider) {
|
||||
throw new Error('IdentityProvider must be given as an argument')
|
||||
}
|
||||
|
||||
if (!IdentityProvider.type ||
|
||||
typeof IdentityProvider.type !== 'string') {
|
||||
throw new Error('Given IdentityProvider doesn\'t have a field \'type\'')
|
||||
}
|
||||
|
||||
supportedTypes[IdentityProvider.type] = IdentityProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an identity provider.
|
||||
* @param {string} type The identity provider type.
|
||||
* @static
|
||||
*/
|
||||
const removeIdentityProvider = (type) => {
|
||||
delete supportedTypes[type]
|
||||
}
|
||||
|
||||
export {
|
||||
Identities as default,
|
||||
isProviderSupported,
|
||||
addIdentityProvider,
|
||||
removeIdentityProvider
|
||||
Identities as default
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
* @description
|
||||
* An identity.
|
||||
*/
|
||||
|
||||
import * as Block from 'multiformats/block'
|
||||
import * as dagCbor from '@ipld/dag-cbor'
|
||||
import { sha256 } from 'multiformats/hashes/sha2'
|
||||
|
@ -1,9 +1,4 @@
|
||||
export {
|
||||
default as Identities,
|
||||
addIdentityProvider,
|
||||
removeIdentityProvider,
|
||||
isProviderSupported
|
||||
} from './identities.js'
|
||||
export { default as Identities } from './identities.js'
|
||||
|
||||
export {
|
||||
default as Identity,
|
||||
@ -11,4 +6,8 @@ export {
|
||||
isEqual
|
||||
} from './identity.js'
|
||||
|
||||
export { PublicKeyIdentityProvider } from './providers/index.js'
|
||||
export {
|
||||
PublicKeyIdentityProvider,
|
||||
addIdentityProvider,
|
||||
identityProviders
|
||||
} from './providers/index.js'
|
||||
|
@ -46,7 +46,68 @@
|
||||
*
|
||||
* where my-custom-identity-provider is the custom module.
|
||||
*/
|
||||
import * as PublicKeyIdentityProvider from './publickey.js'
|
||||
|
||||
const identityProviders = {
|
||||
publickey: PublicKeyIdentityProvider
|
||||
// [DIDIdentityProvider.type]: DIDIdentityProvider,
|
||||
// [EthIdentityProvider.type]: EthIdentityProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an identity provider is supported.
|
||||
* @param {string} type The identity provider type.
|
||||
* @return {boolean} True if the identity provider is supported, false
|
||||
* otherwise.
|
||||
* @static
|
||||
*/
|
||||
const isProviderSupported = (type) => {
|
||||
return Object.keys(identityProviders).includes(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an identity provider.
|
||||
* @param {string} type The identity provider type.
|
||||
* @return {IdentityProvider} The IdentityProvider module corresponding to
|
||||
* type.
|
||||
* @throws IdentityProvider type is not supported if the identity provider is
|
||||
* not supported.
|
||||
* @static
|
||||
*/
|
||||
const getProviderFor = (type) => {
|
||||
if (!isProviderSupported(type)) {
|
||||
throw new Error(`IdentityProvider type '${type}' is not supported`)
|
||||
}
|
||||
|
||||
return identityProviders[type]
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an identity provider.
|
||||
* @param {IdentityProvider} IdentityProvider The identity provider to add.
|
||||
* @throws IdentityProvider must be given as an argument if no module is
|
||||
* provided.
|
||||
* @throws 'Given IdentityProvider doesn't have a field 'type' if the
|
||||
* IdentityProvider does not include a type property.
|
||||
* @static
|
||||
*/
|
||||
const addIdentityProvider = (IdentityProvider) => {
|
||||
if (!IdentityProvider) {
|
||||
throw new Error('IdentityProvider must be given as an argument')
|
||||
}
|
||||
|
||||
if (!IdentityProvider.type ||
|
||||
typeof IdentityProvider.type !== 'string') {
|
||||
throw new Error('Given IdentityProvider doesn\'t have a field \'type\'')
|
||||
}
|
||||
|
||||
if (identityProviders[IdentityProvider.type]) {
|
||||
throw new Error(`Type already added: ${IdentityProvider.type}`)
|
||||
}
|
||||
|
||||
identityProviders[IdentityProvider.type] = IdentityProvider
|
||||
}
|
||||
|
||||
// export { default as DIDIdentityProvider } from './did.js'
|
||||
// export { default as EthIdentityProvider } from './ethereum.js'
|
||||
export * as PublicKeyIdentityProvider from './publickey.js'
|
||||
export { identityProviders, addIdentityProvider, getProviderFor, PublicKeyIdentityProvider }
|
||||
|
41
src/index.js
41
src/index.js
@ -1,8 +1,39 @@
|
||||
export { default as OrbitDB } from './orbitdb.js'
|
||||
export { databaseTypes, addDatabaseType } from './orbitdb.js'
|
||||
export { default as OrbitDBAddress, isValidAddress, parseAddress } from './address.js'
|
||||
export {
|
||||
default as OrbitDB,
|
||||
databaseTypes,
|
||||
addDatabaseType
|
||||
} from './orbitdb.js'
|
||||
|
||||
export {
|
||||
default as OrbitDBAddress,
|
||||
isValidAddress,
|
||||
parseAddress
|
||||
} from './address.js'
|
||||
|
||||
export { Log, Entry, DefaultAccessController } from './oplog/index.js'
|
||||
|
||||
export { default as Database } from './database.js'
|
||||
|
||||
export { default as KeyStore } from './key-store.js'
|
||||
export { Identities, isIdentity } from './identities/index.js'
|
||||
export { IPFSBlockStorage, LevelStorage, LRUStorage, MemoryStorage, ComposedStorage } from './storage/index.js'
|
||||
|
||||
export {
|
||||
addAccessController,
|
||||
removeAccessController,
|
||||
getAccessController,
|
||||
accessControllers
|
||||
} from './access-controllers/index.js'
|
||||
|
||||
export {
|
||||
Identities,
|
||||
isIdentity,
|
||||
identityProviders,
|
||||
addIdentityProvider
|
||||
} from './identities/index.js'
|
||||
|
||||
export {
|
||||
IPFSBlockStorage,
|
||||
LevelStorage,
|
||||
LRUStorage,
|
||||
MemoryStorage,
|
||||
ComposedStorage
|
||||
} from './storage/index.js'
|
||||
|
@ -35,7 +35,7 @@ import OrbitDBAddress, { isValidAddress } from './address.js'
|
||||
import Manifests from './manifest.js'
|
||||
import { createId } from './utils/index.js'
|
||||
import pathJoin from './utils/path-join.js'
|
||||
import * as AccessControllers from './access-controllers/index.js'
|
||||
import { getAccessController } from './access-controllers/index.js'
|
||||
import IPFSAccessController from './access-controllers/ipfs.js'
|
||||
|
||||
/**
|
||||
@ -168,7 +168,7 @@ const OrbitDB = async ({ ipfs, id, identity, keystore, directory } = {}) => {
|
||||
manifest = await manifests.get(addr.path)
|
||||
const acType = manifest.accessController.split('/', 2).pop()
|
||||
const acAddress = manifest.accessController.replaceAll(`/${acType}/`, '')
|
||||
AccessController = AccessControllers.get(acType)()
|
||||
AccessController = getAccessController(acType)()
|
||||
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities, address: acAddress })
|
||||
name = manifest.name
|
||||
type = type || manifest.type
|
||||
@ -234,4 +234,4 @@ const OrbitDB = async ({ ipfs, id, identity, keystore, directory } = {}) => {
|
||||
}
|
||||
}
|
||||
|
||||
export { OrbitDB as default, OrbitDBAddress, addDatabaseType, databaseTypes, AccessControllers }
|
||||
export { OrbitDB as default, OrbitDBAddress, addDatabaseType, databaseTypes }
|
||||
|
48
test/fixtures/providers.js
vendored
Normal file
48
test/fixtures/providers.js
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
const customIdentityProvider = () => {
|
||||
const verifyIdentity = async (data) => { return true }
|
||||
|
||||
const CustomIdentityProvider = () => {
|
||||
const getId = () => { return 'custom' }
|
||||
|
||||
const signIdentity = (data) => { return `signature '${data}'` }
|
||||
|
||||
return {
|
||||
getId,
|
||||
signIdentity,
|
||||
type: 'custom'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
default: CustomIdentityProvider,
|
||||
type: 'custom',
|
||||
verifyIdentity
|
||||
}
|
||||
}
|
||||
|
||||
const fakeIdentityProvider = () => {
|
||||
const verifyIdentity = async (data) => { return false }
|
||||
|
||||
const FakeIdentityProvider = () => {
|
||||
const getId = () => { return 'pubKey' }
|
||||
|
||||
const signIdentity = (data) => { return `false signature '${data}'` }
|
||||
|
||||
return {
|
||||
getId,
|
||||
signIdentity,
|
||||
type: 'fake'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
default: FakeIdentityProvider,
|
||||
verifyIdentity,
|
||||
type: 'fake'
|
||||
}
|
||||
}
|
||||
|
||||
const CustomIdentityProvider = customIdentityProvider()
|
||||
const FakeIdentityProvider = fakeIdentityProvider()
|
||||
|
||||
export { CustomIdentityProvider, FakeIdentityProvider }
|
@ -3,8 +3,9 @@ import rmrf from 'rimraf'
|
||||
import { copy } from 'fs-extra'
|
||||
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
||||
import KeyStore, { signMessage, verifyMessage } from '../../src/key-store.js'
|
||||
import { Identities, addIdentityProvider, Identity, PublicKeyIdentityProvider } from '../../src/identities/index.js'
|
||||
import { Identities, identityProviders, addIdentityProvider, Identity, PublicKeyIdentityProvider } from '../../src/identities/index.js'
|
||||
import testKeysPath from '../fixtures/test-keys-path.js'
|
||||
import { CustomIdentityProvider, FakeIdentityProvider } from '../fixtures/providers.js'
|
||||
|
||||
const type = PublicKeyIdentityProvider.type
|
||||
const keysPath = './testkeys'
|
||||
@ -14,6 +15,15 @@ describe('Identities', function () {
|
||||
await copy(testKeysPath, keysPath)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
// reset the identityProviders.
|
||||
for (const [key] of Object.entries(identityProviders)) {
|
||||
if (key !== 'publickey') {
|
||||
delete identityProviders[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await rmrf(keysPath)
|
||||
})
|
||||
@ -213,30 +223,8 @@ describe('Identities', function () {
|
||||
})
|
||||
|
||||
it('false signature doesn\'t verify', async () => {
|
||||
const IP = () => {
|
||||
const verifyIdentity = async (data) => { return false }
|
||||
|
||||
const FakeIdentityProvider = () => {
|
||||
const getId = () => { return 'pubKey' }
|
||||
|
||||
const signIdentity = (data) => { return `false signature '${data}'` }
|
||||
|
||||
return {
|
||||
getId,
|
||||
signIdentity,
|
||||
type: 'fake'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
default: FakeIdentityProvider,
|
||||
verifyIdentity,
|
||||
type: 'fake'
|
||||
}
|
||||
}
|
||||
|
||||
addIdentityProvider(IP())
|
||||
identity = await identities.createIdentity({ type: IP().type })
|
||||
addIdentityProvider(FakeIdentityProvider)
|
||||
identity = await identities.createIdentity({ type: FakeIdentityProvider.type })
|
||||
const verified = await identities.verifyIdentity(identity)
|
||||
assert.strictEqual(verified, false)
|
||||
})
|
||||
@ -345,4 +333,16 @@ describe('Identities', function () {
|
||||
assert.strictEqual(verified, false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('manage identity providers', () => {
|
||||
it('has default identity providers', () => {
|
||||
assert.deepStrictEqual(identityProviders, { publickey: PublicKeyIdentityProvider })
|
||||
})
|
||||
|
||||
it('can add an identity provider', () => {
|
||||
addIdentityProvider(CustomIdentityProvider)
|
||||
|
||||
assert.deepStrictEqual(identityProviders, { publickey: PublicKeyIdentityProvider, custom: CustomIdentityProvider })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { strictEqual, deepStrictEqual, notStrictEqual } from 'assert'
|
||||
import rmrf from 'rimraf'
|
||||
import * as IPFS from 'ipfs-core'
|
||||
import OrbitDB, { AccessControllers } from '../src/orbitdb.js'
|
||||
import OrbitDB from '../src/orbitdb.js'
|
||||
import { accessControllers, addAccessController, removeAccessController } from '../src/access-controllers/index.js'
|
||||
import config from './config.js'
|
||||
import pathJoin from '../src/utils/path-join.js'
|
||||
|
||||
@ -38,7 +39,7 @@ describe('Add a custom access controller', function () {
|
||||
}
|
||||
|
||||
// Remove the added custom database type from OrbitDB import
|
||||
AccessControllers.remove(type)
|
||||
removeAccessController(type)
|
||||
|
||||
await rmrf('./orbitdb')
|
||||
await rmrf('./ipfs1')
|
||||
@ -51,7 +52,7 @@ describe('Add a custom access controller', function () {
|
||||
'orbitdb'
|
||||
]
|
||||
|
||||
deepStrictEqual(Object.keys(AccessControllers.types), expected)
|
||||
deepStrictEqual(Object.keys(accessControllers), expected)
|
||||
})
|
||||
|
||||
it('throws and error if custom access controller hasn\'t been added', async () => {
|
||||
@ -71,7 +72,7 @@ describe('Add a custom access controller', function () {
|
||||
|
||||
describe('Custom access controller', function () {
|
||||
before(() => {
|
||||
AccessControllers.add(CustomAccessController)
|
||||
addAccessController(CustomAccessController)
|
||||
})
|
||||
|
||||
it('create a database with the custom access controller', async () => {
|
||||
@ -83,7 +84,7 @@ describe('Add a custom access controller', function () {
|
||||
it('throws and error if custom access controller already exists', async () => {
|
||||
let err
|
||||
try {
|
||||
AccessControllers.add(CustomAccessController)
|
||||
addAccessController(CustomAccessController)
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
@ -98,7 +99,7 @@ describe('Add a custom access controller', function () {
|
||||
type
|
||||
]
|
||||
|
||||
deepStrictEqual(Object.keys(AccessControllers.types), expected)
|
||||
deepStrictEqual(Object.keys(accessControllers), expected)
|
||||
})
|
||||
|
||||
it('can be removed from supported access controllers', async () => {
|
||||
@ -107,9 +108,9 @@ describe('Add a custom access controller', function () {
|
||||
'orbitdb'
|
||||
]
|
||||
|
||||
AccessControllers.remove(type)
|
||||
removeAccessController(type)
|
||||
|
||||
deepStrictEqual(Object.keys(AccessControllers.types), expected)
|
||||
deepStrictEqual(Object.keys(accessControllers), expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user