From 0ebe097a70569d8d2a350da677f9c5df98b6c1f0 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Fri, 5 Jul 2024 21:37:12 +0200 Subject: [PATCH] Fix noisy changes in lib/validate I moved the schema for lnbits, nwc and lnc out of lib/validate only to put them back in there later. This commit should make the changeset cleaner by removing noise. --- components/wallet/lnbits.js | 4 +- components/wallet/lnc.js | 4 +- components/wallet/nwc.js | 4 +- lib/validate.js | 136 ++++++++++++++++++------------------ 4 files changed, 74 insertions(+), 74 deletions(-) diff --git a/components/wallet/lnbits.js b/components/wallet/lnbits.js index 2002f809..c1bd0cd1 100644 --- a/components/wallet/lnbits.js +++ b/components/wallet/lnbits.js @@ -1,4 +1,4 @@ -import { LNbitsSchema } from '@/lib/validate' +import { lnbitsSchema } from '@/lib/validate' export const name = 'lnbits' @@ -27,7 +27,7 @@ export async function validate ({ logger, url, adminKey }) { logger.ok('wallet found') } -export const schema = LNbitsSchema +export const schema = lnbitsSchema export async function sendPayment ({ bolt11, url, adminKey }) { const response = await postPayment(url, adminKey, bolt11) diff --git a/components/wallet/lnc.js b/components/wallet/lnc.js index 492e59dc..54f9ab14 100644 --- a/components/wallet/lnc.js +++ b/components/wallet/lnc.js @@ -5,7 +5,7 @@ import CancelButton from '@/components/cancel-button' import { InvoiceCanceledError, InvoiceExpiredError } from '@/components/payment' import { bolt11Tags } from '@/lib/bolt11' import { Status } from '@/components/wallet' -import { LNCSchema } from '@/lib/validate' +import { lncSchema } from '@/lib/validate' export const name = 'lnc' @@ -57,7 +57,7 @@ export async function validate ({ me, logger, pairingPhrase, password }) { } } -export const schema = LNCSchema +export const schema = lncSchema const mutex = new Mutex() diff --git a/components/wallet/nwc.js b/components/wallet/nwc.js index be335580..3773be77 100644 --- a/components/wallet/nwc.js +++ b/components/wallet/nwc.js @@ -1,5 +1,5 @@ import { parseNwcUrl } from '@/lib/url' -import { NWCSchema } from '@/lib/validate' +import { nwcSchema } from '@/lib/validate' import { Relay, finalizeEvent, nip04 } from 'nostr-tools' export const name = 'nwc' @@ -18,7 +18,7 @@ export const card = { badges: ['send only', 'non-custodialish'] } -export const schema = NWCSchema +export const schema = nwcSchema export async function validate ({ logger, nwcUrl }) { const { relayUrl, walletPubkey } = parseNwcUrl(nwcUrl) diff --git a/lib/validate.js b/lib/validate.js index b693ae3e..aac6d3a1 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -10,10 +10,10 @@ import { msatsToSats, numWithUnits, abbrNum, ensureB64, B64_URL_REGEX } from './ import * as usersFragments from '@/fragments/users' import * as subsFragments from '@/fragments/subs' import { isInvoicableMacaroon, isInvoiceMacaroon } from './macaroon' +import { TOR_REGEXP, parseNwcUrl } from './url' import { datePivot } from './time' import { decodeRune } from '@/lib/cln' -import { TOR_REGEXP, parseNwcUrl } from '@/lib/url' -import bip39Words from '@/lib/bip39-words' +import bip39Words from './bip39-words' const { SUB } = subsFragments const { NAME_QUERY } = usersFragments @@ -305,72 +305,6 @@ export function advSchema (args) { }) } -export const LNbitsSchema = object({ - url: process.env.NODE_ENV === 'development' - ? string() - .or([string().matches(/^(http:\/\/)?localhost:\d+$/), string().url()], 'invalid url') - .required('required').trim() - : string().url().required('required').trim() - .test(async (url, context) => { - if (TOR_REGEXP.test(url)) { - // allow HTTP and HTTPS over Tor - if (!/^https?:\/\//.test(url)) { - return context.createError({ message: 'http or https required' }) - } - return true - } - try { - // force HTTPS over clearnet - await string().https().validate(url) - } catch (err) { - return context.createError({ message: err.message }) - } - return true - }), - adminKey: string().length(32) -}) - -export const NWCSchema = object({ - nwcUrl: string() - .required('required') - .test(async (nwcUrl, context) => { - // run validation in sequence to control order of errors - // inspired by https://github.com/jquense/yup/issues/851#issuecomment-1049705180 - try { - await string().required('required').validate(nwcUrl) - await string().matches(/^nostr\+?walletconnect:\/\//, { message: 'must start with nostr+walletconnect://' }).validate(nwcUrl) - let relayUrl, walletPubkey, secret - try { - ({ relayUrl, walletPubkey, secret } = parseNwcUrl(nwcUrl)) - } catch { - // invalid URL error. handle as if pubkey validation failed to not confuse user. - throw new Error('pubkey must be 64 hex chars') - } - await string().required('pubkey required').trim().matches(NOSTR_PUBKEY_HEX, 'pubkey must be 64 hex chars').validate(walletPubkey) - await string().required('relay url required').trim().wss('relay must use wss://').validate(relayUrl) - await string().required('secret required').trim().matches(/^[0-9a-fA-F]{64}$/, 'secret must be 64 hex chars').validate(secret) - } catch (err) { - return context.createError({ message: err.message }) - } - return true - }) -}) - -export const LNCSchema = object({ - pairingPhrase: array() - .transform(function (value, originalValue) { - if (this.isType(value) && value !== null) { - return value - } - return originalValue ? originalValue.split(/[\s]+/) : [] - }) - .of(string().trim().oneOf(bip39Words, ({ value }) => `'${value}' is not a valid pairing phrase word`)) - .min(2, 'needs at least two words') - .max(10, 'max 10 words') - .required('required'), - password: string() -}) - export function lnAddrAutowithdrawSchema ({ me } = {}) { return object({ address: lightningAddressValidator.required('required').test({ @@ -666,6 +600,72 @@ export const lnAddrSchema = ({ payerData, min, max, commentAllowed } = {}) => return accum }, {}))) +export const lnbitsSchema = object({ + url: process.env.NODE_ENV === 'development' + ? string() + .or([string().matches(/^(http:\/\/)?localhost:\d+$/), string().url()], 'invalid url') + .required('required').trim() + : string().url().required('required').trim() + .test(async (url, context) => { + if (TOR_REGEXP.test(url)) { + // allow HTTP and HTTPS over Tor + if (!/^https?:\/\//.test(url)) { + return context.createError({ message: 'http or https required' }) + } + return true + } + try { + // force HTTPS over clearnet + await string().https().validate(url) + } catch (err) { + return context.createError({ message: err.message }) + } + return true + }), + adminKey: string().length(32) +}) + +export const nwcSchema = object({ + nwcUrl: string() + .required('required') + .test(async (nwcUrl, context) => { + // run validation in sequence to control order of errors + // inspired by https://github.com/jquense/yup/issues/851#issuecomment-1049705180 + try { + await string().required('required').validate(nwcUrl) + await string().matches(/^nostr\+?walletconnect:\/\//, { message: 'must start with nostr+walletconnect://' }).validate(nwcUrl) + let relayUrl, walletPubkey, secret + try { + ({ relayUrl, walletPubkey, secret } = parseNwcUrl(nwcUrl)) + } catch { + // invalid URL error. handle as if pubkey validation failed to not confuse user. + throw new Error('pubkey must be 64 hex chars') + } + await string().required('pubkey required').trim().matches(NOSTR_PUBKEY_HEX, 'pubkey must be 64 hex chars').validate(walletPubkey) + await string().required('relay url required').trim().wss('relay must use wss://').validate(relayUrl) + await string().required('secret required').trim().matches(/^[0-9a-fA-F]{64}$/, 'secret must be 64 hex chars').validate(secret) + } catch (err) { + return context.createError({ message: err.message }) + } + return true + }) +}) + +export const lncSchema = object({ + pairingPhrase: array() + .transform(function (value, originalValue) { + if (this.isType(value) && value !== null) { + return value + } + return originalValue ? originalValue.split(/[\s]+/) : [] + }) + .of(string().trim().oneOf(bip39Words, ({ value }) => `'${value}' is not a valid pairing phrase word`)) + .min(2, 'needs at least two words') + .max(10, 'max 10 words') + .required('required'), + password: string() +}) + export const bioSchema = object({ bio: string().required('required').trim() })