From 5c3c7fb1854028bdf8ba86386c48508168120a85 Mon Sep 17 00:00:00 2001 From: keyan Date: Wed, 14 Feb 2024 12:56:37 -0600 Subject: [PATCH] allow more restricted macroons fix #827 --- api/resolvers/wallet.js | 7 ++++++- components/info.js | 14 ++++++++++---- lib/macaroon.js | 14 ++++++++++++++ lib/validate.js | 4 ++-- pages/settings/wallets/lnd.js | 17 +++++++++++++++-- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index c2f79bc6..570edd39 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -408,7 +408,12 @@ export default { macaroon, socket }) - return await getIdentity({ lnd }) + return await createInvoice({ + description: 'SN connection test', + lnd, + tokens: 0, + expires_at: new Date() + }) } }, { settings, data }, { me, models }) diff --git a/components/info.js b/components/info.js index 338f5391..0c49b056 100644 --- a/components/info.js +++ b/components/info.js @@ -1,16 +1,22 @@ +import React from 'react' import InfoIcon from '../svgs/information-fill.svg' import { useShowModal } from './modal' -export default function Info ({ children, iconClassName = 'fill-theme-color' }) { +export default function Info ({ children, label, iconClassName = 'fill-theme-color' }) { const showModal = useShowModal() return ( - { e.preventDefault() showModal(onClose => children) }} - /> + className='pointer' + > + + {label && {label}} + ) } diff --git a/lib/macaroon.js b/lib/macaroon.js index 80bab88a..ab2798f3 100644 --- a/lib/macaroon.js +++ b/lib/macaroon.js @@ -46,6 +46,10 @@ function arrayCustomizer (value1, value2) { } } +export function isInvoicableMacaroon (macaroon) { + return isEqualWith(macaroonOPs(macaroon), INVOICABLE_MACAROON_OPS, arrayCustomizer) +} + export function isInvoiceMacaroon (macaroon) { return isEqualWith(macaroonOPs(macaroon), INVOICE_MACAROON_OPS, arrayCustomizer) } @@ -58,6 +62,16 @@ export function isReadOnlyMacaroon (macaroon) { return isEqualWith(macaroonOPs(macaroon), READ_ONLY_MACAROON_OPS, arrayCustomizer) } +const INVOICABLE_MACAROON_OPS = [ + { + entity: 'invoices', + actions: [ + 'read', + 'write' + ] + } +] + const INVOICE_MACAROON_OPS = [ { entity: 'address', diff --git a/lib/validate.js b/lib/validate.js index 06a72a81..7bbd8eee 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -9,7 +9,7 @@ import { NOSTR_MAX_RELAY_NUM, NOSTR_PUBKEY_BECH32, NOSTR_PUBKEY_HEX } from './no import { msatsToSats, numWithUnits, abbrNum } from './format' import * as usersFragments from '../fragments/users' import * as subsFragments from '../fragments/subs' -import { B64_REGEX, HEX_REGEX, isInvoiceMacaroon } from './macaroon' +import { B64_REGEX, HEX_REGEX, isInvoicableMacaroon, isInvoiceMacaroon } from './macaroon' const { SUB } = subsFragments const { NAME_QUERY } = usersFragments @@ -296,7 +296,7 @@ export function LNDAutowithdrawSchema ({ me } = {}) { socket: string().socket().required('required'), macaroon: hexOrBase64Validator.required('required').test({ name: 'macaroon', - test: isInvoiceMacaroon, + test: v => isInvoiceMacaroon(v) || isInvoicableMacaroon(v), message: 'not an invoice macaroon' }), cert: hexOrBase64Validator, diff --git a/pages/settings/wallets/lnd.js b/pages/settings/wallets/lnd.js index 99e306dc..2c8be748 100644 --- a/pages/settings/wallets/lnd.js +++ b/pages/settings/wallets/lnd.js @@ -9,6 +9,8 @@ import { LNDAutowithdrawSchema } from '../../../lib/validate' import { useRouter } from 'next/router' import { AutowithdrawSettings, autowithdrawInitial } from '../../../components/autowithdraw-shared' import { REMOVE_WALLET, UPSERT_WALLET_LND, WALLET_BY_TYPE } from '../../../fragments/wallet' +import Info from '../../../components/info' +import Text from '../../../components/text' const variables = { type: 'LND' } export const getServerSideProps = getGetServerSideProps({ query: WALLET_BY_TYPE, variables, authRequired: true }) @@ -62,19 +64,30 @@ export default function LND ({ ssrData }) { name='socket' hint='tor or clearnet' placeholder='55.5.555.55:10001' + clear required autoFocus /> invoice macaroon + + + {'We accept a prebaked ***invoice.macaroon*** for your convenience. To gain better privacy, generate a new macaroon as follows:\n\n```lncli bakemacaroon invoices:write invoices:read```'} + + + + } name='macaroon' + clear hint='hex or base64 encoded' placeholder='AgEDbG5kAlgDChCn7YgfWX7uTkQQgXZ2uahNEgEwGhYKB2FkZHJlc3MSBHJlYWQSBXdyaXRlGhcKCGludm9pY2VzEgRyZWFkEgV3cml0ZRoPCgdvbmNoYWluEgRyZWFkAAAGIJkMBrrDV0npU90JV0TGNJPrqUD8m2QYoTDjolaL6eBs' required /> cert optional if from CA (e.g. voltage)} + label={<>cert optional if from CA (e.g. voltage)} name='cert' + clear hint='hex or base64 encoded' placeholder='LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNNVENDQWRpZ0F3SUJBZ0lRSHBFdFdrcGJwZHV4RVF2eVBPc3NWVEFLQmdncWhrak9QUVFEQWpBdk1SOHcKSFFZRFZRUUtFeFpzYm1RZ1lYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3SGhjTgpNalF3TVRBM01qQXhORE0wV2hjTk1qVXdNekF6TWpBeE5ETTBXakF2TVI4d0hRWURWUVFLRXhac2JtUWdZWFYwCmIyZGxibVZ5WVhSbFpDQmpaWEowTVF3d0NnWURWUVFERXdOaWIySXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJUS3NMVk5oZnhqb1FLVDlkVVdDbzUzSmQwTnBuL1BtYi9LUE02M1JxbU52dFYvdFk4NjJJZwpSbE41cmNHRnBEajhUeFc2OVhIK0pTcHpjWDdlN3N0Um80SFZNSUhTTUE0R0ExVWREd0VCL3dRRUF3SUNwREFUCkJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVDAKMnh3V25GeHRUNzI0MWxwZlNoNm9FWi9UMWpCN0JnTlZIUkVFZERCeWdnTmliMktDQ1d4dlkyRnNhRzl6ZElJRApZbTlpZ2d4d2IyeGhjaTF1TVMxaWIyS0NGR2h2YzNRdVpHOWphMlZ5TG1sdWRHVnlibUZzZ2dSMWJtbDRnZ3AxCmJtbDRjR0ZqYTJWMGdnZGlkV1pqYjI1dWh3Ui9BQUFCaHhBQUFBQUFBQUFBQUFBQUFBQUFBQUFCaHdTc0VnQUQKTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUEwUTlkRXdoNXpPRnpwL3hYeHNpemh5SkxNVG5yazU1VWx1NHJPRwo4WW52QWlBVGt4U3p3Y3hZZnFscGx0UlNIbmd0NUJFcDBzcXlHL05nenBzb2pmMGNqQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K' />