IPFSAccessController = ({ write, storage } = {}) => async ({ orbitdb, identities, address }) => {
  storage = storage || await ComposedStorage(
    await LRUStorage({ size: 1000 }),
    await IPFSBlockStorage({ ipfs: orbitdb.ipfs, pin: true })
  )
  write = write || [orbitdb.identity.id]

  if (address) {
    const manifestBytes = await storage.get(address.replaceAll('/ipfs/', ''))
    const { value } = await Block.decode({ bytes: manifestBytes, codec, hasher })
    write = value.write
  } else {
    address = await AccessControlList({ storage, type, params: { write } })
    address = pathJoin('/', type, address)
  }

  /**
   * Verifies the write permission of an entry.
   * @param {module:Log~Entry} entry An entry to verify.
   * @return {boolean} True if the entry's identity has write permission,
   * false otherwise.
   * @memberof module:AccessControllers.AccessControllers-IPFS
   */
  const canAppend = async (entry) => {
    const writerIdentity = await identities.getIdentity(entry.identity)
    if (!writerIdentity) {
      return false
    }
    const { id } = writerIdentity
    // Allow if the write access list contain the writer's id or is '*'
    if (write.includes(id) || write.includes('*')) {
      // Check that the identity is valid
      return await identities.verifyIdentity(writerIdentity)
    }
    return false
  }

  return {
    type,
    address,
    write,
    canAppend
  }
}
Defines an IPFS access controller.
@param {Object} options Various options for configuring the
IPFSAccessController.
@param {Array} [params.write] An array of identity ids who can write to the
database.
@param {module:Storage} [params.storage] An instance of a compatible storage.
@return {module:AccessControllers.AccessControllers-IPFS} An
IPFSAccessController function.
@memberof module:AccessControllers