diff --git a/src/databases/events.js b/src/databases/events.js index 328183e..1ddfe87 100644 --- a/src/databases/events.js +++ b/src/databases/events.js @@ -7,7 +7,6 @@ * @augments module:Databases~Database */ import Database from '../database.js' -import { toPayload, fromPayload } from './utils/payload.js' const type = 'events' @@ -16,7 +15,7 @@ const type = 'events' * @return {module:Databases.Databases-Events} A Events function. * @memberof module:Databases */ -const Events = () => async ({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate, encrypt }) => { +const Events = () => async ({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate }) => { const database = await Database({ ipfs, identity, address, name, access, directory, meta, headsStorage, entryStorage, indexStorage, referencesCount, syncAutomatically, onUpdate }) const { addOperation, log } = database @@ -30,8 +29,7 @@ const Events = () => async ({ ipfs, identity, address, name, access, directory, * @instance */ const add = async (value) => { - const payload = await toPayload('ADD', null, value, { encrypt }) - return addOperation(payload) + return addOperation({ op: 'ADD', key: null, value }) } /** @@ -44,9 +42,7 @@ const Events = () => async ({ ipfs, identity, address, name, access, directory, */ const get = async (hash) => { const entry = await log.get(hash) - const { value } = await fromPayload(entry.payload, { encrypt }) - - return value + return entry.payload.value } /** @@ -70,8 +66,7 @@ const Events = () => async ({ ipfs, identity, address, name, access, directory, const it = log.iterator({ gt, gte, lt, lte, amount }) for await (const event of it) { const hash = event.hash - const payload = await fromPayload(event.payload, { encrypt }) - const value = payload.value + const value = event.payload.value yield { hash, value } } } diff --git a/src/databases/utils/payload.js b/src/databases/utils/payload.js deleted file mode 100644 index e872371..0000000 --- a/src/databases/utils/payload.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - - */ -const toPayload = async (op, key, value, { encrypt }) => { - let payload = { op, key, value } - - if (encrypt) { - if (encrypt.data) { - payload.value = await encrypt.data.encryptFn(value) - } - - if (encrypt.op) { - payload = await encrypt.op.encryptFn(JSON.stringify(payload)) - } - } - - return payload -} - -const fromPayload = async (payload, { encrypt }) => { - if (encrypt) { - if (encrypt.op) { - payload = JSON.parse(await encrypt.op.decryptFn(payload)) - } - - if (encrypt.data) { - payload.value = await encrypt.data.decryptFn(payload.value) - } - } - - const { op, key, value } = payload - - return { op, key, value } -} - -export { - toPayload, - fromPayload -} diff --git a/src/oplog/log.js b/src/oplog/log.js index fc6e819..54624ed 100644 --- a/src/oplog/log.js +++ b/src/oplog/log.js @@ -56,7 +56,7 @@ const DefaultAccessController = async () => { * @memberof module:Log * @instance */ -const Log = async (identity, { logId, logHeads, access, entryStorage, headsStorage, indexStorage, sortFn } = {}) => { +const Log = async (identity, { logId, logHeads, access, entryStorage, headsStorage, indexStorage, sortFn, encryption } = {}) => { /** * @namespace Log * @description The instance returned by {@link module:Log} @@ -83,6 +83,9 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora // Conflict-resolution sorting function sortFn = NoZeroes(sortFn || LastWriteWins) + encryption = encryption || {} + const { encryptPayloadFn, decryptPayloadFn } = encryption + // Internal queues for processing appends and joins in their call-order const appendQueue = new PQueue({ concurrency: 1 }) const joinQueue = new PQueue({ concurrency: 1 }) @@ -139,6 +142,10 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora if (bytes) { const entry = await Entry.decode(bytes) + if (decryptPayloadFn) { + entry.payload = JSON.parse(await decryptPayloadFn(entry.payload)) + } + return entry } } @@ -172,6 +179,10 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora // (skips the heads which are covered by the next field) const refs = await getReferences(heads_, options.referencesCount + heads_.length) + if (encryptPayloadFn) { + data = await encryptPayloadFn(JSON.stringify(data)) + } + // Create the entry const entry = await Entry.create( identity, diff --git a/test/oplog/log.test.js b/test/oplog/log.test.js index 9466701..c6b54ff 100644 --- a/test/oplog/log.test.js +++ b/test/oplog/log.test.js @@ -3,6 +3,7 @@ import { rimraf } from 'rimraf' import { copy } from 'fs-extra' import { Log, Entry, Identities, KeyStore, MemoryStorage } from '../../src/index.js' import testKeysPath from '../fixtures/test-keys-path.js' +import { encrypt, decrypt } from '../utils/encrypt.js' const { create } = Entry @@ -142,5 +143,34 @@ describe('Log', function () { strictEqual(values[1].payload, 'hello2') strictEqual(values[2].payload, 'hello3') }) + + it('encrypts a log entry when the payload is a string', async () => { + const keys = await keystore.createKey('hello1') + + const privateKey = await keystore.getKey('hello1') + const publicKey = await keystore.getPublic(keys) + + const encryptPayloadFn = encrypt({ publicKey }) + const decryptPayloadFn = decrypt({ privateKey }) + const log = await Log(testIdentity, { encryption: { encryptPayloadFn, decryptPayloadFn } }) + const entry = await log.append('hello1') + const value = await log.get(entry.hash) + strictEqual(value.payload, 'hello1') + }) + + it('encrypts a log entry when the payload is an object', async () => { + const keys = await keystore.createKey('hello1') + + const privateKey = await keystore.getKey('hello1') + const publicKey = await keystore.getPublic(keys) + + const encryptPayloadFn = encrypt({ publicKey }) + const decryptPayloadFn = decrypt({ privateKey }) + const log = await Log(testIdentity, { encryption: { encryptPayloadFn, decryptPayloadFn } }) + const entry = await log.append({ test: 'hello1' }) + const value = await log.get(entry.hash) + + deepStrictEqual(value.payload, { test: 'hello1' }) + }) }) })