diff options
| author | John Barratt <[email protected]> | 2023-02-28 13:55:59 -0800 |
|---|---|---|
| committer | John Barratt <[email protected]> | 2023-02-28 13:55:59 -0800 |
| commit | e47d50a443f0a396321716a506e1df325dd4a1fb (patch) | |
| tree | 1c010c5970e9cbfbf8671e6f00a97d6518446fdd /lib | |
| parent | 58e996a4ac227162f171e84530fe898cb504e045 (diff) | |
| parent | e4702b4d13e4d966d735c2ba4657e10d7c436a57 (diff) | |
| download | coinos-server-e47d50a443f0a396321716a506e1df325dd4a1fb.tar.gz coinos-server-e47d50a443f0a396321716a506e1df325dd4a1fb.zip | |
Merge branch 'master' of https://github.com/coinos/coinos-server into notifications
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/auth.js | 20 | ||||
| -rw-r--r-- | lib/db.js | 15 | ||||
| -rw-r--r-- | lib/invoices.js | 17 | ||||
| -rw-r--r-- | lib/nostr.js | 42 | ||||
| -rw-r--r-- | lib/payments.js | 28 | ||||
| -rw-r--r-- | lib/register.js | 25 | ||||
| -rw-r--r-- | lib/sockets.js | 2 | ||||
| -rw-r--r-- | lib/upload.js | 2 | ||||
| -rw-r--r-- | lib/utils.js | 2 | ||||
| -rw-r--r-- | lib/webhooks.js | 9 |
10 files changed, 98 insertions, 64 deletions
diff --git a/lib/auth.js b/lib/auth.js index f3cfd1e9..0533de31 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -7,17 +7,17 @@ export const optional = { preValidation: fastifyPassport.authenticate( "jwt", { session: false }, - function (req, res, err, user, info) { + function(req, res, err, user, info) { req.user = user; } - ), + ) }; export const auth = { preValidation: fastifyPassport.authenticate("jwt", { authInfo: false, - session: false, - }), + session: false + }) }; export const requirePin = async ({ body, user }) => { @@ -29,13 +29,17 @@ export const jwtStrategy = new jwt.Strategy( { jwtFromRequest: jwt.ExtractJwt.fromExtractors([ jwt.ExtractJwt.fromAuthHeaderAsBearerToken(), - (req) => (req.cookies ? req.cookies.token : null), + req => (req.cookies ? req.cookies.token : null) ]), - secretOrKey: config.jwt, + secretOrKey: config.jwt }, async (payload, next) => { - let user = await g(`user:${payload.id}`); - if (typeof user === "string") await g(`user:${user}`); + let user; + if (payload.id) { + user = await g(`user:${payload.id}`); + if (typeof user === "string") await g(`user:${user}`); + } + next(null, user); } ); @@ -1,6 +1,7 @@ import config from "$config"; import { sleep } from "$lib/utils"; import { createClient } from "redis"; +import { warn } from "$lib/logging"; export const db = createClient({ url: config.db }); try { @@ -15,11 +16,17 @@ export let g = async k => { let v = await db.get(k); try { return JSON.parse(v); - } catch(e) { + } catch (e) { return v; - } -} -export let s = (k, v) => db.set(k, JSON.stringify(v)); + } +}; +export let s = (k, v) => { + if (k === "user:null" || k === "user:undefined") { + warn("###### NULL USER #######"); + console.trace(); + } + db.set(k, JSON.stringify(v)); +}; let retries = {}; export let t = async (k, f) => { diff --git a/lib/invoices.js b/lib/invoices.js index bab48515..f64cf409 100644 --- a/lib/invoices.js +++ b/lib/invoices.js @@ -16,10 +16,9 @@ export let generate = async ({ invoice, user, sender, memo }) => { tip = parseInt(tip || 0); if (amount < 0) fail("amount out of range"); - if (tip > 5 * amount || tip < 0) fail("tip amount out of range"); if (!user) user = sender; - let uid = await g(`user:${user.username}`); + let uid = await g(`user:${user.username.toLowerCase()}`); user = await g(`user:${uid}`); if (!user) fail("user not provided"); @@ -30,9 +29,8 @@ export let generate = async ({ invoice, user, sender, memo }) => { let hash, text; if (type === types.lightning) { - let amt = amount ? `${amount + tip}sat` : "any"; let r = await ln.invoice( - amt, + amount ? `${amount + tip}sat` : "any", new Date(), memo || "", 3600, @@ -55,16 +53,17 @@ export let generate = async ({ invoice, user, sender, memo }) => { } invoice = { - ...invoice, amount, - hash, - text, + created: Date.now(), currency, + hash, rate, + received: 0, + request_id, + text, tip, + type, uid, - received: 0, - created: Date.now() }; l("creating invoice", user.username, amount, tip, currency, invoice.hash); diff --git a/lib/nostr.js b/lib/nostr.js index 065fafb0..604d207d 100644 --- a/lib/nostr.js +++ b/lib/nostr.js @@ -1,16 +1,17 @@ import config from "$config"; import { Relay, RelayPool } from "nostr"; -import { broadcast } from "$lib/sockets"; +import { broadcast, emit } from "$lib/sockets"; import store from "$lib/store"; import { g, s, db } from "$lib/db"; import { nada, wait } from "$lib/utils"; +export let coinos; export let pool; export let fillPool = () => { pool = RelayPool(config.relays); pool.on("open", relay => { - if (relay.url.includes(config.relay)) coinos = relay; + if (relay.url.includes(config.nostr)) coinos = relay; relay.subscribe("live", { limit: 1 }); }); @@ -39,6 +40,13 @@ export let fillPool = () => { // coinos.send(["EVENT", ev]); ev.user = await getUser(pubkey); // broadcast("event", ev); + + if (ev.kind === 4) { + let uid = await g(`user:${ev.tags[0][1]}`); + if (uid) ev.recipient = await g(`user:${uid}`); + ev.author = ev.user; + emit(uid, "event", ev); + } } } else if (sub.includes("profile")) { let { pubkey } = ev; @@ -59,9 +67,13 @@ export let fillPool = () => { await s(`user:${pubkey}`, JSON.stringify(user)); coinos.send(ev); + } else if (sub.includes("messages")) { + let pubkey = sub.split(":")[0]; + await db.sAdd(`${pubkey}:messages`, ev.id); + await s(`ev:${ev.id}`, ev); } else if (sub.includes("follows")) { let pubkey = sub.split(":")[0]; - await s(`${pubkey}:follows`, JSON.stringify(ev.tags)); + await s(`${pubkey}:follows`, ev.tags); for (let f of ev.tags) { let [_, followPubkey] = f; await db.sAdd(`${followPubkey}:followers`, pubkey); @@ -75,7 +87,7 @@ export let fillPool = () => { } else if (sub.includes("notes")) { let pubkey = sub.split(":")[0]; await db.sAdd(pubkey, ev.id); - await s(`ev:${ev.id}`, JSON.stringify(ev)); + await s(`ev:${ev.id}`, ev); } } catch (e) { console.log(e); @@ -83,7 +95,6 @@ export let fillPool = () => { }); }; -export let coinos; let now = () => Math.round(Date.now() / 1000); let timeouts = {}; @@ -96,8 +107,8 @@ export let q = async ( let start = Date.now(); let seen = []; let rejected; - query.since = await g(`since:${sub}`); - if (now() - query.since < since) return r(); + // query.since = await g(`since:${sub}`); + // if (now() - query.since < since) return r(); let done = { [sub]: [] }; @@ -156,9 +167,14 @@ export let q = async ( let seen = []; -let getUser = async pubkey => - JSON.parse(await g(`user:${pubkey}`)) || { - username: pubkey.substr(0, 6), - pubkey, - anon: true - }; +let getUser = async pubkey => { + let id = await g(`user:${pubkey}`); + let user = await g(`user:${id}`); + return ( + user || { + username: pubkey.substr(0, 6), + pubkey, + anon: true + } + ); +}; diff --git a/lib/payments.js b/lib/payments.js index 2c0eb0c0..aaf39210 100644 --- a/lib/payments.js +++ b/lib/payments.js @@ -4,7 +4,7 @@ import { emit } from "$lib/sockets"; import { v4 } from "uuid"; import { notify } from "$lib/notifications"; import { db, g, s, t } from "$lib/db"; -import { l, err } from "$lib/logging"; +import { l, err, warn } from "$lib/logging"; import { fail } from "$lib/utils"; import { callWebhook } from "$lib/webhooks"; @@ -13,7 +13,7 @@ export const types = { bitcoin: "bitcoin", lightning: "lightning", pot: "pot", - classic: "classic", + classic: "classic" }; export let debit = async ( @@ -25,9 +25,11 @@ export let debit = async ( type = types.internal, id = v4() ) => { - let ref; + let ref, tip; let invoice = await g(`invoice:${hash}`); - if (invoice) ref = invoice.uid; + if (invoice) { + ref = invoice.uid; + } let { id: uid, currency, username } = user; @@ -44,16 +46,21 @@ export let debit = async ( let covered = Math.min(credit, ourfee) || 0; ourfee -= covered; - l("debiting", user.username, balance, amount, ourfee, amount + ourfee); - if (balance < amount + ourfee) fail("Insufficient funds"); + l("debiting", user.username, balance, amount, fee, ourfee, amount + fee + ourfee); + if (balance < amount + fee + ourfee) fail("Insufficient funds"); await db .multi() .decrBy(`credit:${type}:${uid}`, covered) - .decrBy(`balance:${uid}`, amount + ourfee) + .decrBy(`balance:${uid}`, amount + fee + ourfee) .exec(); }); }); + if (invoice?.tip) { + tip = invoice.tip; + amount -= tip; + } + let p = { id, amount: -amount, @@ -66,7 +73,8 @@ export let debit = async ( currency, type, ref, - created: Date.now(), + tip, + created: Date.now() }; await s(`payment:${id}`, p); @@ -81,7 +89,7 @@ export let debit = async ( export let credit = async (hash, amount, memo, ref, type = types.internal) => { amount = parseInt(amount); let invoice = await g(`invoice:${hash}`); - if (!invoice) return; + if (!invoice) return warn("failed to credit", hash, ", invoice not found"); if (!memo) ({ memo } = invoice); let user = await g(`user:${invoice.uid}`); @@ -98,7 +106,7 @@ export let credit = async (hash, amount, memo, ref, type = types.internal) => { ref, type, confirmed: true, - created: Date.now(), + created: Date.now() }; let { tip } = invoice; diff --git a/lib/register.js b/lib/register.js index c55d2f9d..22c36b4c 100644 --- a/lib/register.js +++ b/lib/register.js @@ -2,7 +2,7 @@ import countries from "$lib/countries"; import config from "$config"; import { authenticator } from "otplib"; import bcrypt from "bcrypt"; -import { l } from "$lib/logging"; +import { l, warn } from "$lib/logging"; import { v4 } from "uuid"; import { s, g } from "$lib/db"; import { got } from "got"; @@ -17,7 +17,7 @@ export default async (user, ip, requireChallenge) => { let id = v4(); user.id = id; - let exists = await g(`user:${username}`); + let exists = await g(`user:${username.toLowerCase()}`); if (exists) throw new Error(`Username ${username} taken`); if (password) { @@ -25,19 +25,20 @@ export default async (user, ip, requireChallenge) => { } user.currency = "USD"; - if (config.ipxapi) { - let countryCode = "US"; - + if (config.ipregistry) { try { - let r = await got(`https://ipxapi.com/api/ip?ip=${ip}`, { - headers: { authorization: `Bearer ${config.ipxapi}` } - }).json(); - if (r.success) ({ countryCode } = r); + let { + location: { + country: { code } + } + } = await got( + `https://api.ipregistry.co/${ip}?key=${config.ipregistry}&fields=location.country.code` + ).json(); + + user.currency = countries[code]; } catch (e) { - console.log(e); + warn("unable to detect country from IP", username); } - - user.currency = countries[countryCode]; } user.currencies = [...new Set([user.currency, "CAD", "USD"])]; diff --git a/lib/sockets.js b/lib/sockets.js index 11d8ea9e..458c77a9 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -130,6 +130,8 @@ export async function socketServer(app) { } }); + ws.on("error", console.log); + ws.on("close", function(code, reason) { try { const uid = users[id]; diff --git a/lib/upload.js b/lib/upload.js index 954e8d4d..50c26cbf 100644 --- a/lib/upload.js +++ b/lib/upload.js @@ -12,7 +12,7 @@ export default async (req, res) => { params: { type }, user } = req; - console.log("TYPE", type); + if (!["banner", "profile"].includes(type)) throw new Error("invalid upload"); let data = await req.file(); diff --git a/lib/utils.js b/lib/utils.js index 8c3852e8..45353e8e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -22,6 +22,8 @@ export const fail = msg => { throw new Error(msg); }; +export const bail = (res, msg) => res.code(500).send(msg); + export const SATS = 100000000; export const sats = n => Math.round(n * SATS); export const btc = n => parseFloat((n / SATS).toFixed(8)); diff --git a/lib/webhooks.js b/lib/webhooks.js index c071eccb..1158fe9d 100644 --- a/lib/webhooks.js +++ b/lib/webhooks.js @@ -9,23 +9,18 @@ export const callWebhook = async (invoice, payment) => { let { address, received, text, webhook } = invoice; if (webhook) { - let { amount, confirmed, hash, memo, account } = payment; - let { asset } = account; - let secret = config.webhooks[webhook]; + let { amount, confirmed, hash, memo } = payment; l("calling webhook", webhook, amount, hash, address, text); let res = await got(webhook, { - headers: { "x-webhook": secret }, json: { address, amount, - asset, confirmed, hash, memo, received, - text, - webhook + text } }).res(); return res; |
