From d3323081049fb908c2bb47e5de076abccf8c2ea6 Mon Sep 17 00:00:00 2001 From: Powersource Date: Mon, 25 Mar 2024 16:45:08 +0100 Subject: [PATCH] Add db.account.del (#27) --- lib/index.js | 69 ++++++++++++++++++++++++++++++++++++++++ test/account-add.test.js | 26 +++------------ 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/lib/index.js b/lib/index.js index 7527b9e..7d4387e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -957,6 +957,74 @@ function initDB(peer, config) { }) } + /** + * Remove the given `keypair` (or the implicit config.global.keypair) from + * the given `account`. + * + * @param {{ + * account: string; + * keypair: KeypairPublicSlice; + * }} opts + * @param {CB} cb + */ + function delFromAccount(opts, cb) { + if (!opts) return cb(new Error('account.del() requires an `opts`')) + // prettier-ignore + if (!opts.account) return cb(new Error('account.del() requires a `account`')) + // prettier-ignore + if (!opts.keypair) return cb(new Error('account.del() requires a `keypair`')) + // prettier-ignore + if (!opts.keypair.public) return cb(new Error('account.del() requires a `keypair` with `public`')) + + const deldKeypair = opts.keypair + const signingKeypair = config.global.keypair + + // Verify powers of the signingKeypair: + const accountTangle = new DBTangle(opts.account, records(), get) + const signingPowers = getAccountPowers(accountTangle, signingKeypair) + if (!signingPowers.has('del')) { + // prettier-ignore + return cb(new Error('account.del() failed because the signing keypair does not have the "del" power')) + } + + const accountRoot = get(opts.account) + if (!accountRoot) { + // prettier-ignore + return cb(new Error(`account.del() failed because the account root "${opts.account}" is unknown`)) + } + + let msg + try { + msg = MsgV4.create({ + account: ACCOUNT_SELF, + accountTips: null, + domain: accountRoot.metadata.domain, + keypair: signingKeypair, + tangles: { + [opts.account]: accountTangle, + }, + data: { + action: 'del', + key: { + purpose: 'sig', + algorithm: 'ed25519', + bytes: deldKeypair.public, + }, + }, + }) + } catch (err) { + return cb(new Error('account.del() failed', { cause: err })) + } + const msgID = MsgV4.getMsgID(msg) + + logAppend(msgID, msg, (err, rec) => { + // prettier-ignore + if (err) return cb(new Error('account.del() failed to append the log', { cause: err })) + queueMicrotask(() => onRecordAdded.set(rec)) + cb(null, rec) + }) + } + /** * @param {{ * keypair?: Keypair; @@ -1277,6 +1345,7 @@ function initDB(peer, config) { create: createAccount, findOrCreate: findOrCreateAccount, add: addToAccount, + del: delFromAccount, consent: consentToAccount, has: accountHas, }, diff --git a/test/account-add.test.js b/test/account-add.test.js index c16db93..ae8e923 100644 --- a/test/account-add.test.js +++ b/test/account-add.test.js @@ -243,28 +243,10 @@ test('account.add()', async (t) => { }) const postMootRec = peer.db.feed.findMoot(account, 'post') - const tangle = new MsgV4.Tangle(account) - tangle.add(account, accountMsg0) - tangle.add(accountRec1.id, accountRec1.msg) - // can't publish() account msgs. and creating this manually for now until we have a .del() fn - const delMsg = MsgV4.create({ - account: 'self', - accountTips: null, - domain: accountMsg0.metadata.domain, - keypair: keypair1, - tangles: { - [account]: tangle, - }, - data: { - action: 'del', - key: { - purpose: 'sig', - algorithm: 'ed25519', - bytes: keypair2.public, - }, - }, + const delRec = await p(peer.db.account.del)({ + account, + keypair: keypair2, }) - await p(peer.db.add)(delMsg, account) const badRec = await p(peer.db.feed.publish)({ account, @@ -285,7 +267,7 @@ test('account.add()', async (t) => { await p(carol.db.add)(accountRec1.msg, account) await p(carol.db.add)(postMootRec.msg, postMootRec.id) await p(carol.db.add)(goodRec.msg, postMootRec.id) - await p(carol.db.add)(delMsg, account) + await p(carol.db.add)(delRec.msg, account) await assert.rejects( p(carol.db.add)(badRec.msg, postMootRec.id), /add\(\) failed to verify msg/,