handle other possible base64-like string encodings
This commit is contained in:
parent
a9ade0354d
commit
fe0d960208
@ -6,12 +6,11 @@ import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor'
|
|||||||
import lnpr from 'bolt11'
|
import lnpr from 'bolt11'
|
||||||
import { SELECT } from './item'
|
import { SELECT } from './item'
|
||||||
import { lnAddrOptions } from '../../lib/lnurl'
|
import { lnAddrOptions } from '../../lib/lnurl'
|
||||||
import { msatsToSats, msatsToSatsDecimal } from '../../lib/format'
|
import { msatsToSats, msatsToSatsDecimal, ensureB64 } from '../../lib/format'
|
||||||
import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '../../lib/validate'
|
import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '../../lib/validate'
|
||||||
import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT } from '../../lib/constants'
|
import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT } from '../../lib/constants'
|
||||||
import { datePivot } from '../../lib/time'
|
import { datePivot } from '../../lib/time'
|
||||||
import assertGofacYourself from './ofac'
|
import assertGofacYourself from './ofac'
|
||||||
import { HEX_REGEX } from '../../lib/macaroon'
|
|
||||||
|
|
||||||
export async function getInvoice (parent, { id }, { me, models, lnd }) {
|
export async function getInvoice (parent, { id }, { me, models, lnd }) {
|
||||||
const inv = await models.invoice.findUnique({
|
const inv = await models.invoice.findUnique({
|
||||||
@ -408,13 +407,9 @@ export default {
|
|||||||
return { id }
|
return { id }
|
||||||
},
|
},
|
||||||
upsertWalletLND: async (parent, { settings, ...data }, { me, models }) => {
|
upsertWalletLND: async (parent, { settings, ...data }, { me, models }) => {
|
||||||
// store hex inputs as base64
|
// make sure inputs are base64
|
||||||
if (HEX_REGEX.test(data.macaroon)) {
|
data.macaroon = ensureB64(data.macaroon)
|
||||||
data.macaroon = Buffer.from(data.macaroon, 'hex').toString('base64')
|
data.cert = ensureB64(data.cert)
|
||||||
}
|
|
||||||
if (HEX_REGEX.test(data.cert)) {
|
|
||||||
data.cert = Buffer.from(data.cert, 'hex').toString('base64')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await upsertWallet(
|
return await upsertWallet(
|
||||||
{
|
{
|
||||||
|
@ -53,3 +53,42 @@ export const msatsToSatsDecimal = msats => {
|
|||||||
}
|
}
|
||||||
return fixedDecimal(Number(msats) / 1000.0, 3)
|
return fixedDecimal(Number(msats) / 1000.0, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const hexToB64 = hexstring => {
|
||||||
|
return btoa(hexstring.match(/\w{2}/g).map(function (a) {
|
||||||
|
return String.fromCharCode(parseInt(a, 16))
|
||||||
|
}).join(''))
|
||||||
|
}
|
||||||
|
|
||||||
|
// some base64 encoders get fancy and remove padding
|
||||||
|
export const ensureB64Padding = str => {
|
||||||
|
return str + Array((4 - str.length % 4) % 4 + 1).join('=')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const B64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/
|
||||||
|
export const B64_URL_REGEX = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2}[.=]{2}|[A-Za-z0-9_-]{3}[.=])?$/
|
||||||
|
export const HEX_REGEX = /^[0-9a-fA-F]+$/
|
||||||
|
|
||||||
|
export const ensureB64 = hexOrB64Url => {
|
||||||
|
if (HEX_REGEX.test(hexOrB64Url)) {
|
||||||
|
return hexToB64(hexOrB64Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
hexOrB64Url = ensureB64Padding(hexOrB64Url)
|
||||||
|
|
||||||
|
// some folks use url-safe base64
|
||||||
|
if (B64_URL_REGEX.test(hexOrB64Url)) {
|
||||||
|
// Convert from URL-safe base64 to regular base64
|
||||||
|
hexOrB64Url = hexOrB64Url.replace(/-/g, '+').replace(/_/g, '/').replace(/\./g, '=')
|
||||||
|
switch (hexOrB64Url.length % 4) {
|
||||||
|
case 2: hexOrB64Url += '=='; break
|
||||||
|
case 3: hexOrB64Url += '='; break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (B64_REGEX.test(hexOrB64Url)) {
|
||||||
|
return hexOrB64Url
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('not a valid hex or base64 url or base64 encoded string')
|
||||||
|
}
|
||||||
|
@ -2,20 +2,11 @@ import { importMacaroon, base64ToBytes } from 'macaroon'
|
|||||||
import { MacaroonId } from './macaroon-id'
|
import { MacaroonId } from './macaroon-id'
|
||||||
import isEqual from 'lodash/isEqual'
|
import isEqual from 'lodash/isEqual'
|
||||||
import isEqualWith from 'lodash/isEqualWith'
|
import isEqualWith from 'lodash/isEqualWith'
|
||||||
|
import { ensureB64 } from './format'
|
||||||
export const B64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/
|
|
||||||
export const HEX_REGEX = /^[0-9a-fA-F]+$/
|
|
||||||
|
|
||||||
function decodeMacaroon (macaroon) {
|
function decodeMacaroon (macaroon) {
|
||||||
if (HEX_REGEX.test(macaroon)) {
|
macaroon = ensureB64(macaroon)
|
||||||
return importMacaroon(Buffer.from(macaroon, 'hex'))
|
return importMacaroon(Buffer.from(macaroon, 'base64'))
|
||||||
}
|
|
||||||
|
|
||||||
if (B64_REGEX.test(macaroon)) {
|
|
||||||
return importMacaroon(Buffer.from(macaroon, 'base64'))
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('invalid macaroon encoding')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function macaroonOPs (macaroon) {
|
function macaroonOPs (macaroon) {
|
||||||
|
@ -6,10 +6,10 @@ import {
|
|||||||
} from './constants'
|
} from './constants'
|
||||||
import { SUPPORTED_CURRENCIES } from './currency'
|
import { SUPPORTED_CURRENCIES } from './currency'
|
||||||
import { NOSTR_MAX_RELAY_NUM, NOSTR_PUBKEY_BECH32, NOSTR_PUBKEY_HEX } from './nostr'
|
import { NOSTR_MAX_RELAY_NUM, NOSTR_PUBKEY_BECH32, NOSTR_PUBKEY_HEX } from './nostr'
|
||||||
import { msatsToSats, numWithUnits, abbrNum } from './format'
|
import { msatsToSats, numWithUnits, abbrNum, ensureB64 } from './format'
|
||||||
import * as usersFragments from '../fragments/users'
|
import * as usersFragments from '../fragments/users'
|
||||||
import * as subsFragments from '../fragments/subs'
|
import * as subsFragments from '../fragments/subs'
|
||||||
import { B64_REGEX, HEX_REGEX, isInvoicableMacaroon, isInvoiceMacaroon } from './macaroon'
|
import { isInvoicableMacaroon, isInvoiceMacaroon } from './macaroon'
|
||||||
import { parseNwcUrl } from './url'
|
import { parseNwcUrl } from './url'
|
||||||
|
|
||||||
const { SUB } = subsFragments
|
const { SUB } = subsFragments
|
||||||
@ -154,10 +154,18 @@ const lightningAddressValidator = process.env.NODE_ENV === 'development'
|
|||||||
'address is no good')
|
'address is no good')
|
||||||
: string().email('address is no good')
|
: string().email('address is no good')
|
||||||
|
|
||||||
const hexOrBase64Validator = string().or([
|
const hexOrBase64Validator = string().test({
|
||||||
string().matches(HEX_REGEX),
|
name: 'hex-or-base64',
|
||||||
string().matches(B64_REGEX)
|
message: 'invalid encoding',
|
||||||
], 'invalid encoding')
|
test: (val) => {
|
||||||
|
try {
|
||||||
|
ensureB64(val)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
async function usernameExists (name, { client, models }) {
|
async function usernameExists (name, { client, models }) {
|
||||||
if (!client && !models) {
|
if (!client && !models) {
|
||||||
@ -313,7 +321,7 @@ export function LNDAutowithdrawSchema ({ me } = {}) {
|
|||||||
macaroon: hexOrBase64Validator.required('required').test({
|
macaroon: hexOrBase64Validator.required('required').test({
|
||||||
name: 'macaroon',
|
name: 'macaroon',
|
||||||
test: v => isInvoiceMacaroon(v) || isInvoicableMacaroon(v),
|
test: v => isInvoiceMacaroon(v) || isInvoicableMacaroon(v),
|
||||||
message: 'not an invoice macaroon'
|
message: 'not an invoice macaroon or an invoicable macaroon'
|
||||||
}),
|
}),
|
||||||
cert: hexOrBase64Validator,
|
cert: hexOrBase64Validator,
|
||||||
...autowithdrawSchemaMembers({ me })
|
...autowithdrawSchemaMembers({ me })
|
||||||
|
Loading…
x
Reference in New Issue
Block a user