Merge branch 'master' into feature/ln-ux

This commit is contained in:
boufni95 2020-07-28 19:54:45 +02:00
commit 582f2baeb1
18 changed files with 688 additions and 228 deletions

21
.github/workflows/main.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: Update Wizard
on:
push:
branches: [ 'feature/synchronized-wizard-builds' ]
pull_request:
branches: [ 'feature/synchronized-wizard-builds' ]
jobs:
dispatch:
strategy:
matrix:
repo: ['shocknet/Wizard']
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: ${{ matrix.repo }}
event-type: api-update

View file

@ -1 +0,0 @@
{}

View file

@ -324,6 +324,18 @@ const authenticate = async (alias, pass, __user) => {
API.Jobs.onAcceptedRequests(_user, mySEA)
API.Jobs.onOrders(_user, gun, mySEA)
API.Jobs.lastSeenNode(_user)
API.Events.onAvatar(() => {}, user)()
API.Events.onBio(() => {}, user)
API.Events.onBlacklist(() => {}, user)
API.Events.onChats(() => {})()
API.Events.onCurrentHandshakeAddress(() => {}, user)()
API.Events.onDisplayName(() => {}, user)()
API.Events.onOutgoing(() => {})()
API.Events.onSeedBackup(() => {}, user, mySEA)
API.Events.onSimplerReceivedRequests(() => {})()
API.Events.onSimplerSentRequests(() => {})()
return _user._.sea.pub
}
@ -372,6 +384,17 @@ const authenticate = async (alias, pass, __user) => {
API.Jobs.onOrders(_user, gun, mySEA)
API.Jobs.lastSeenNode(_user)
API.Events.onAvatar(() => {}, user)()
API.Events.onBio(() => {}, user)
API.Events.onBlacklist(() => {}, user)
API.Events.onChats(() => {})()
API.Events.onCurrentHandshakeAddress(() => {}, user)()
API.Events.onDisplayName(() => {}, user)()
API.Events.onOutgoing(() => {})()
API.Events.onSeedBackup(() => {}, user, mySEA)
API.Events.onSimplerReceivedRequests(() => {})()
API.Events.onSimplerSentRequests(() => {})()
return ack.sea.pub
} else {
logger.error(

View file

@ -372,50 +372,13 @@ const cleanup = async pub => {
const outGoingID = await Utils.recipientToOutgoingID(pub)
await new Promise((res, rej) => {
user
.get(Key.USER_TO_INCOMING)
.get(pub)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
const promises = []
await new Promise((res, rej) => {
user
.get(Key.RECIPIENT_TO_OUTGOING)
.get(pub)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
await new Promise((res, rej) => {
user
.get(Key.USER_TO_LAST_REQUEST_SENT)
.get(pub)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
if (outGoingID) {
await new Promise((res, rej) => {
promises.push(
new Promise((res, rej) => {
user
.get(Key.OUTGOINGS)
.get(outGoingID)
.get(Key.USER_TO_INCOMING)
.get(pub)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
@ -424,7 +387,56 @@ const cleanup = async pub => {
}
})
})
)
promises.push(
new Promise((res, rej) => {
user
.get(Key.RECIPIENT_TO_OUTGOING)
.get(pub)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
)
promises.push(
new Promise((res, rej) => {
user
.get(Key.USER_TO_LAST_REQUEST_SENT)
.get(pub)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
)
if (outGoingID) {
promises.push(
new Promise((res, rej) => {
user
.get(Key.OUTGOINGS)
.get(outGoingID)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
)
}
await Promise.all(promises)
}
/**
@ -631,9 +643,9 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => {
* @param {string} body
* @param {UserGUNNode} user
* @param {ISEA} SEA
* @returns {Promise<string>} The message id.
* @returns {Promise<import('shock-common').Schema.ChatMessage>} The message id.
*/
const sendMessage = async (recipientPublicKey, body, user, SEA) => {
const sendMessageNew = async (recipientPublicKey, body, user, SEA) => {
if (!user.is) {
throw new Error(ErrorCode.NOT_AUTH)
}
@ -691,12 +703,28 @@ const sendMessage = async (recipientPublicKey, body, user, SEA) => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res(msgNode._.get)
res({
body,
id: msgNode._.get,
outgoing: true,
timestamp: newMessage.timestamp
})
}
})
})
}
/**
* Returns the message id.
* @param {string} recipientPublicKey
* @param {string} body
* @param {UserGUNNode} user
* @param {ISEA} SEA
* @returns {Promise<string>} The message id.
*/
const sendMessage = async (recipientPublicKey, body, user, SEA) =>
(await sendMessageNew(recipientPublicKey, body, user, SEA)).id
/**
* @param {string} recipientPub
* @param {string} msgID
@ -1211,9 +1239,7 @@ const disconnect = async pub => {
throw new Error('No handshake exists for this pub')
}
await cleanup(pub)
await generateHandshakeAddress()
await Promise.all([cleanup(pub), generateHandshakeAddress()])
}
/**
@ -1589,5 +1615,6 @@ module.exports = {
deletePost,
follow,
unfollow,
initWall
initWall,
sendMessageNew
}

View file

@ -329,7 +329,11 @@ const getCurrentOutgoings = () => currentOutgoings
const outgoingsListeners = new Set()
outgoingsListeners.add(o => {
logger.info(`new outgoings: ${JSON.stringify(o, null, 4)}`)
const values = Object.values(o)
const nulls = values.filter(x => x === null).length
const nonNulls = values.length - nulls
logger.info(`new outgoings, ${nulls} nulls and ${nonNulls} nonNulls`)
})
const notifyOutgoingsListeners = () => {
@ -452,7 +456,7 @@ const getChats = () => currentChats
const chatsListeners = new Set()
chatsListeners.add(c => {
logger.info(`new Chats: ${JSON.stringify(c, null, 4)}`)
logger.info(`Chats: ${c.length}`)
})
const notifyChatsListeners = () => {

View file

@ -2,6 +2,7 @@
const debounce = require('lodash/debounce')
const logger = require('winston')
const { Schema } = require('shock-common')
const size = require('lodash/size')
const Key = require('../key')
const Streams = require('../streams')
@ -50,6 +51,7 @@ const react = debounce(() => {
for (const [id, req] of Object.entries(currAddressData)) {
const inContact = Array.isArray(pubToFeed[req.from])
const isDisconnected = pubToFeed[req.from] === 'disconnected'
if (typeof pubToAvatar[req.from] === 'undefined') {
// eslint-disable-next-line no-empty-function
@ -60,7 +62,7 @@ const react = debounce(() => {
Streams.onDisplayName(() => {}, req.from)()
}
if (!inContact) {
if (!inContact && !isDisconnected) {
newReceivedReqsMap[req.from] = {
id,
requestorAvatar: pubToAvatar[req.from] || null,
@ -95,8 +97,7 @@ const listenerForAddr = addr => data => {
}
}
logger.info('data for address: ' + addr)
logger.info(JSON.stringify(data, null, 4))
logger.info('data for address length: ' + size(addr))
react()
}

View file

@ -1,6 +1,7 @@
/** @format */
const debounce = require('lodash/debounce')
const logger = require('winston')
const size = require('lodash/size')
const Streams = require('../streams')
/**
@ -29,7 +30,7 @@ const listeners = new Set()
let currentReqs = []
listeners.add(() => {
logger.info(`new sent reqs: ${JSON.stringify(currentReqs)}`)
logger.info(`new sent reqs length: ${size(currentReqs)}`)
})
const getCurrentSentReqs = () => currentReqs
@ -55,9 +56,7 @@ const react = debounce(() => {
// pk to display name
const pubToDN = Streams.getPubToDn()
logger.info(
`pubToLastSentREqID: ${JSON.stringify(pubToLastSentReqID, null, 4)}`
)
logger.info(`pubToLastSentREqID length: ${size(pubToLastSentReqID)}`)
for (const storedReq of storedReqs) {
const { handshakeAddress, recipientPub, sentReqID, timestamp } = storedReq

View file

@ -28,6 +28,7 @@ exports.currentFollows = async () => {
return true
}
// load sometimes returns an empty set on the first try
if (size(v) === 0) {
return true
}

View file

@ -9,6 +9,7 @@ const Utils = require('../utils')
const Wall = require('./wall')
const Feed = require('./feed')
const User = require('./user')
const { size } = require('lodash')
/**
* @param {string} pub
@ -51,7 +52,18 @@ exports.userToIncomingID = async pub => {
const getMyUser = async () => {
const oldProfile = await Utils.tryAndWait(
(_, user) => new Promise(res => user.get(Key.PROFILE).load(res)),
v => typeof v !== 'object'
v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
}
)
const bio = await Utils.tryAndWait(

View file

@ -2,6 +2,7 @@
* @format
*/
const Common = require('shock-common')
const size = require('lodash/size')
const Key = require('../key')
const Utils = require('../utils')
@ -72,7 +73,18 @@ module.exports.getAnUser = getAnUser
const getMyUser = async () => {
const oldProfile = await Utils.tryAndWait(
(_, user) => new Promise(res => user.get(Key.PROFILE).load(res)),
v => typeof v !== 'object'
v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
}
)
const bio = await Utils.tryAndWait(

View file

@ -6,6 +6,7 @@ const {
Constants: { ErrorCode },
Schema
} = require('shock-common')
const size = require('lodash/size')
const Key = require('../key')
const Utils = require('../utils')
@ -39,24 +40,31 @@ const onAcceptedRequests = (user, SEA) => {
logger.info(
`------------------------------------\nPROCID:${procid} (used for debugging memory leaks in jobs)\n---------------------------------------`
)
const mySecret = require('../../Mediator').getMySecret()
try {
if (!Schema.isStoredRequest(storedReq)) {
logger.warn(
throw new Error(
'Stored request not an StoredRequest, instead got: ' +
JSON.stringify(storedReq) +
' this can be due to nulling out an old request (if null) or something else happened (please look at the output)'
)
return
}
// get the recipient pub from the stored request to avoid an attacker
// overwriting the handshake request in the root graph
const recipientPub = await SEA.decrypt(storedReq.recipientPub, mySecret)
if (typeof recipientPub !== 'string') {
throw new TypeError()
throw new TypeError(
`Expected storedReq.recipientPub to be an string, instead got: ${recipientPub}`
)
}
if (await Utils.successfulHandshakeAlreadyExists(recipientPub)) {
return
}
const requestAddress = await SEA.decrypt(
storedReq.handshakeAddress,
mySecret
@ -99,9 +107,9 @@ const onAcceptedRequests = (user, SEA) => {
return
}
// The response can be decrypted with the same secret regardless of who
// wrote to it last (see HandshakeRequest definition).
// This could be our feed ID for the recipient, or the recipient's feed
// The response can be decrypted with the same secret regardless
// of who wrote to it last (see HandshakeRequest definition). This
// could be our feed ID for the recipient, or the recipient's feed
// id if he accepted the request.
const feedID = await SEA.decrypt(sentReq.response, ourSecret)
@ -126,8 +134,8 @@ const onAcceptedRequests = (user, SEA) => {
res(feed)
})
}),
// retry on undefined, might be a false negative
v => typeof v === 'undefined'
// @ts-ignore
v => size(v) === 0
)
const feedIDExistsOnRecipientsOutgoings =

View file

@ -1,5 +1,6 @@
/** @format */
const logger = require('winston')
const size = require('lodash/size')
const Key = require('../key')
/**
@ -13,7 +14,7 @@ const pubToAddress = {}
const listeners = new Set()
listeners.add(() => {
logger.info(`pubToAddress: ${JSON.stringify(pubToAddress, null, 4)}`)
logger.info(`pubToAddress length: ${size(pubToAddress)}`)
})
const notify = () => listeners.forEach(l => l())

View file

@ -3,6 +3,7 @@ const uuidv1 = require('uuid/v1')
const logger = require('winston')
const debounce = require('lodash/debounce')
const { Schema, Utils: CommonUtils } = require('shock-common')
const size = require('lodash/size')
const Key = require('../key')
const Utils = require('../utils')
@ -29,7 +30,7 @@ let pubToFeed = {}
const getPubToFeed = () => pubToFeed
feedsListeners.add(() => {
logger.info(`new pubToFeed: ${JSON.stringify(getPubToFeed())}`)
logger.info(`new pubToFeed length: ${size(getPubToFeed())}`)
})
/** @param {Feeds} ptf */

View file

@ -3,6 +3,7 @@ const uuidv1 = require('uuid/v1')
const debounce = require('lodash/debounce')
const logger = require('winston')
const { Utils: CommonUtils } = require('shock-common')
const size = require('lodash/size')
const { USER_TO_INCOMING } = require('../key')
/** @typedef {import('../SimpleGUN').OpenListenerData} OpenListenerData */
@ -30,9 +31,7 @@ const setPubToIncoming = pti => {
let latestUpdate = uuidv1()
listeners.add(() => {
logger.info(
`new pubToIncoming: ${JSON.stringify(getPubToIncoming(), null, 4)}`
)
logger.info(`new pubToIncoming length: ${size(getPubToIncoming())}`)
})
const onOpen = debounce(async uti => {

View file

@ -14,6 +14,7 @@ const uuid = require("uuid/v4");
const Common = require('shock-common')
const isARealUsableNumber = require('lodash/isFinite')
const Big = require('big.js')
const size = require('lodash/size')
const getListPage = require("../utils/paginate");
const auth = require("../services/auth/auth");
@ -23,7 +24,8 @@ const LightningServices = require("../utils/lightningServices");
const GunDB = require("../services/gunDB/Mediator");
const { unprotectedRoutes, nonEncryptedRoutes } = require("../utils/protectedRoutes");
const GunActions = require("../services/gunDB/contact-api/actions")
const GunGetters = require('../services/gunDB/contact-api/getters');
const GunGetters = require('../services/gunDB/contact-api/getters')
const GunKey = require('../services/gunDB/contact-api/key')
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
const SESSION_ID = uuid();
@ -273,8 +275,6 @@ module.exports = async (
app.use(async (req, res, next) => {
try {
logger.info("Route:", req.path)
if (unprotectedRoutes[req.method][req.path]) {
next();
return;
@ -438,76 +438,6 @@ module.exports = async (
});
/*
const feedObj = {
feed: [
{
id:'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
paragraphs:[
"SOme text and stuff 12"
"SOme text and stuff"
],
profilePic:"",
username:"bobni",
media:[
{
type:'VIDEO',
ratio_x: 1024,
ratio_y: 436,
magnetUri:'magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=Sintel&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fsintel.torrent',
},
]
},
{
id:'3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
paragraphs:[
"SOme text and stuff"
],
profilePic:"",
username:"bobni",
media:[
{
type:'VIDEO',
ratio_x: 1920,
ratio_y: 804,
magnetUri:'magnet:?xt=urn:btih:c9e15763f722f23e98a29decdfae341b98d53056&dn=Cosmos+Laundromat&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fcosmos-laundromat.torrent',
},
]
},
{
id:'58694a0f-3da1-471f-bd96-145571e29d72',
paragraphs:[
"SOme text and stuff"
],
profilePic:"",
username:"bobni",
media:[
{
type:'VIDEO',
ratio_x: 1920,
ratio_y: 1080,
magnetUri:'magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c&dn=Big+Buck+Bunny&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fbig-buck-bunny.torrent',
},
]
}
]
}
user.get("FEED_POC").put(JSON.stringify(feedObj), ack => {
if (ack.err) {
//rej(new Error(ack.err))
}*/
const feedObj = {
feed :{}
}
user.get("FEED_POC").put(feedObj, ack => {
if (ack.err) {
//rej(ack.err)
logger.log(ack.err)
} else {
logger.log(ack.err)
}
})
//register to listen for channel backups
const onNewChannelBackup = () => {
logger.warn("Subscribing to channel backup ...")
@ -1748,49 +1678,12 @@ module.exports = async (
const Events = require('../services/gunDB/contact-api/events')
app.get(`/api/gun/${GunEvent.ON_RECEIVED_REQUESTS}`, (_, res) => {
try {
// spinup
Events.onSimplerReceivedRequests(() => {})()
const data = Events.getCurrentReceivedReqs()
res.json({
data,
})
} catch (err) {
logger.info('Error in Received Requests poll:')
logger.error(err)
res.status(err.message === 'NON_AUTH' ? 401 : 500).json({
errorMessage: typeof err === 'string' ? err : err.message
})
}
})
app.get(`/api/gun/${GunEvent.ON_SENT_REQUESTS}`, (_, res) => {
try {
// spinup
Events.onSimplerSentRequests(() => {})()
const data = Events.getCurrentSentReqs()
logger.info(`Sent requests poll: ${JSON.stringify(data, null, 4)}`)
res.json({
data,
})
} catch (err) {
logger.info('Error in sentRequests poll:')
logger.error(err)
res.status(err.message === 'NON_AUTH' ? 401 : 500).json({
errorMessage: typeof err === 'string' ? err : err.message
})
}
})
app.get(`/api/gun/${GunEvent.ON_CHATS}`, (_, res) => {
try {
// spinup
Events.onChats(() => {})()
const data = Events.getChats()
logger.info(`Chats polled: ${JSON.stringify(data, null, 4)}`)
logger.info(`Chats polled: ${data.length}`)
res.json({
data
data,
})
} catch (err) {
logger.info('Error in Chats poll:')
@ -1805,7 +1698,7 @@ module.exports = async (
try {
const user = require('../services/gunDB/Mediator').getUser()
const data = await timeout5(user.get(Key.PROFILE).get(Key.AVATAR).then())
logger.info(`avatar poll:${data}`)
logger.info(`avatar poll:${(data || '').length} chars`)
res.json({
data
})
@ -2058,8 +1951,13 @@ module.exports = async (
* @type {RequestHandler<{}>}
*/
const apiGunMePut = async (req, res) => {
/**
* @typedef {Omit<Common.Schema.User, 'publicKey'>} UserWithoutPK
* @typedef {{ handshakeAddress: boolean }} HasHandshakeAddress
* @typedef {UserWithoutPK & HasHandshakeAddress} MePutBody
*/
try {
const { avatar, bio , displayName} = /** @type {Partial<Omit<Common.Schema.User, 'publicKey'>>} */ (req.body)
const { avatar, bio , displayName, handshakeAddress } = /** @type {Partial<MePutBody>} */ (req.body)
if (avatar) {
await GunActions.setAvatar(avatar, require('../services/gunDB/Mediator').getUser())
@ -2073,6 +1971,10 @@ module.exports = async (
await GunActions.setDisplayName(displayName, require('../services/gunDB/Mediator').getUser())
}
if (handshakeAddress) {
await GunActions.generateHandshakeAddress();
}
return res.status(200).json({
ok: true
})
@ -2087,6 +1989,440 @@ module.exports = async (
ap.get(`/api/gun/me`, apiGunMeGet)
ap.put(`/api/gun/me`, apiGunMePut)
/**
* @typedef {object} ChatsRouteParams
* @prop {(string|undefined)=} publicKey
*/
/**
* @type {RequestHandler<ChatsRouteParams>}
*/
const apiGunChatsPost = async (req, res) => {
const { publicKey } = req.params
const { body } = req.body
if (!publicKey) {
return res.status(400).json({
errorMessage: `Must specify a publicKey route param for POSTing a message`
})
}
try {
const user = GunDB.getUser()
const SEA = GunDB.mySEA
return res.status(200).json(
await GunActions.sendMessageNew(publicKey,body, user, SEA)
)
} catch (err) {
logger.error(err)
return res.status(500).json({
errorMessage: err.message
})
}
}
/**
* @type {RequestHandler<ChatsRouteParams>}
*/
const apiGunChatsDelete = async (req, res) => {
const { publicKey } = req.params
if (!publicKey) {
return res.status(400).json({
errorMessage: `Must specify a publicKey route param for DELETING a chat`
})
}
try {
await GunActions.disconnect(publicKey)
return res.status(200).json({
ok: true
})
} catch (err) {
logger.error(err)
return res.status(500).json({
errorMessage: err.message
})
}
}
ap.post(`/api/gun/chats/:publicKey?`, apiGunChatsPost)
ap.delete(`/api/gun/chats/:publicKey?`, apiGunChatsDelete)
/**
* @typedef {object} RequestsRouteParams
* @prop {(string|undefined)=} requestID
*/
/**
* @type {RequestHandler<{}>}
*/
const apiGunRequestsReceivedGet = (_, res) => {
try {
const data = Events.getCurrentReceivedReqs()
res.json({
data,
})
} catch (err) {
logger.error(err)
return res.status(500).json({
errorMessage: err.message
})
}
}
/**
* @type {RequestHandler<{}>}
*/
const apiGunRequestsSentGet = (_, res) => {
try {
const data = Events.getCurrentSentReqs()
res.json({
data,
})
} catch (err) {
logger.error(err)
return res.status(500).json({
errorMessage: err.message
})
}
}
/**
* @typedef {object} RequestsRoutePOSTBody
* @prop {string=} initialMsg
* @prop {string} publicKey
*/
/**
* @type {RequestHandler<{}>}
*/
const apiGunRequestsPost = async (req, res) => {
const { initialMsg, publicKey } = /** @type {RequestsRoutePOSTBody} */(req.body)
if (!publicKey) {
return res.status(400).json({
errorMessage: `Must specify a publicKey route param for POSTing a message`
})
}
try {
const gun = require('../services/gunDB/Mediator').getGun()
const user = require('../services/gunDB/Mediator').getUser()
const SEA = require('../services/gunDB/Mediator').mySEA
if (initialMsg) {
await GunActions.sendHRWithInitialMsg(initialMsg, publicKey, gun, user, SEA)
} else {
await GunActions.sendHandshakeRequest(publicKey, gun, user, SEA)
}
return res.status(200).json({
ok: true
})
} catch (err) {
logger.error(err);
return res.status(500).json({
errorMessage: err.message
})
}
}
/**
* @typedef {object} RequestsRoutePUTBody
* @prop {boolean=} accept
*/
/**
* @type {RequestHandler<RequestsRouteParams>}
*/
const apiGunRequestsPut = async (req, res) => {
const { requestID } = req.params
const { accept } = /** @type {RequestsRoutePUTBody} */(req.body)
if (!requestID) {
return res.status(400).json({
errorMessage: `Must specify a requestID route param for accepting a request`
})
}
if (!accept) {
return res.status(200).json({
ok: true
})
}
try {
const gun = require('../services/gunDB/Mediator').getGun()
const user = require('../services/gunDB/Mediator').getUser()
const SEA = require('../services/gunDB/Mediator').mySEA
await GunActions.acceptRequest(requestID, gun, user, SEA)
return res.status(200).json({
ok: true
})
} catch (err) {
logger.error(err);
return res.status(500).json({
errorMessage: err.message
})
}
}
ap.get(`/api/gun/${GunEvent.ON_RECEIVED_REQUESTS}`, apiGunRequestsReceivedGet)
ap.get(`/api/gun/${GunEvent.ON_SENT_REQUESTS}`, apiGunRequestsSentGet)
ap.get(`/api/gun/requests/received`, apiGunRequestsReceivedGet)
ap.get(`/api/gun/requests/sent`, apiGunRequestsSentGet)
ap.post('/api/gun/requests/', apiGunRequestsPost)
ap.put(`/api/gun/requests/:requestID?`, apiGunRequestsPut)
ap.get(`/api/gun/dev/userToIncoming`, async (_, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((_, u) => new Promise(res => {
u.get(GunKey.USER_TO_INCOMING).load(data => {
res(data)
})
}), v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/recipientToOutgoing`, async (_, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((_, u) => new Promise(res => {
u.get(GunKey.RECIPIENT_TO_OUTGOING).load(data => {
res(data)
})
}), v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/outgoings`, async (_, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((_, u) => new Promise(res => {
u.get(GunKey.OUTGOINGS).load(data => {
res(data)
})
}), v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/currentHandshakeAddress`, async (_, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((_, u) => u.get(GunKey.CURRENT_HANDSHAKE_ADDRESS).then())
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/handshakeNodes/:handshakeAddress`, async (req, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((g) =>
new Promise((res) => {
g.get(GunKey.HANDSHAKE_NODES).get(req.params.handshakeAddress).load(data => {
res(data)
})
})
, v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/user/:publicKey`, async (req, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((g) =>
new Promise((res) => {
g.user(req.params.publicKey).load(data => {
res(data)
})
})
, v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/storedReqs`, async (req, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((_, u) =>
new Promise((res) => u.get(Key.STORED_REQS).load(res))
, v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/dev/userToLastReqSent`, async (req, res) => {
try {
const {tryAndWait} = require('../services/gunDB/contact-api/utils')
const data = await tryAndWait((_, u) =>
new Promise((res) => u.get(Key.USER_TO_LAST_REQUEST_SENT).load(res))
, v => {
if (typeof v !== 'object') {
return true
}
if (v === null) {
return true
}
// load sometimes returns an empty set on the first try
return size(v) === 0
})
return res.status(200).json({
data
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message
})
}
})
ap.get(`/api/gun/auth`, (_, res) => {
const { isAuthenticated } = require('../services/gunDB/Mediator')
return res.status(200).json({
data: isAuthenticated()
})
})
/**
* Return app so that it can be used by express.
*/

View file

@ -195,31 +195,34 @@ const server = program => {
})
app.use((req, res, next) => {
if (sensitiveRoutes[req.method][req.path]) {
logger.info(
JSON.stringify({
time: new Date(),
ip: req.ip,
method: req.method,
path: req.path,
sessionId: req.sessionId
})
)
} else {
logger.info(
JSON.stringify({
time: new Date(),
ip: req.ip,
method: req.method,
path: req.path,
body: req.body,
query: req.query,
sessionId: req.sessionId
})
)
if (process.env.ROUTE_LOGGING === 'true') {
if (sensitiveRoutes[req.method][req.path]) {
logger.info(
JSON.stringify({
time: new Date(),
ip: req.ip,
method: req.method,
path: req.path,
sessionId: req.sessionId
})
)
} else {
logger.info(
JSON.stringify({
time: new Date(),
ip: req.ip,
method: req.method,
path: req.path,
body: req.body,
query: req.query,
sessionId: req.sessionId
})
)
}
}
next()
})
app.use(
session({
secret: defaults.sessionSecret,

View file

@ -7,7 +7,9 @@ module.exports = {
"/favicon.ico": true,
"/api/lnd/connect": true,
"/api/lnd/wallet/status": true,
"/api/lnd/auth": true
"/api/lnd/auth": true,
//
"/api/gun/auth": true
},
POST: {
"/api/lnd/connect": true,
@ -28,5 +30,5 @@ module.exports = {
PUT: {},
DELETE: {}
},
nonEncryptedRoutes: ['/api/security/exchangeKeys', '/healthz', '/ping', '/api/lnd/wallet/status']
nonEncryptedRoutes: ['/api/security/exchangeKeys', '/healthz', '/ping', '/api/lnd/wallet/status', '/api/gun/auth']
}

View file

@ -377,10 +377,10 @@
"@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^13.0.0"
"@peculiar/asn1-schema@^2.0.1", "@peculiar/asn1-schema@^2.0.3":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.0.5.tgz#ba6c5a107eec16a23804d0176a3595837b53c0e9"
integrity sha512-VIKJjsgMkv+yyWx3C+D4xo6/NeCg0XFBgNlavtkxELijV+aKAq53du5KkOJbeZtm1nn9CinQKny2PqL8zCfpeA==
"@peculiar/asn1-schema@^2.0.1", "@peculiar/asn1-schema@^2.0.8":
version "2.0.8"
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.0.8.tgz#bafb74388590f6ec3d53d1b2a4fdbe66d44224a4"
integrity sha512-D8ZqT61DdzuXfrILNvtdf7MUcTY2o9WHwmF0WgTKPEGNY5SDxNAjBY3enuwV9SXcSuCAwWac9c9v0vsswB1NIw==
dependencies:
"@types/asn1js" "^0.0.1"
asn1js "^2.0.26"
@ -388,22 +388,22 @@
tslib "^1.11.1"
"@peculiar/json-schema@^1.1.10":
version "1.1.10"
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.10.tgz#d772b4323c9a4b5352b5ad52dc821a07b0db4877"
integrity sha512-kbpnG9CkF1y6wwGkW7YtSA+yYK4X5uk4rAwsd1hxiaYE3Hkw2EsGlbGh/COkMLyFf+Fe830BoFiMSB3QnC/ItA==
version "1.1.12"
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339"
integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==
dependencies:
tslib "^1.11.1"
tslib "^2.0.0"
"@peculiar/webcrypto@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.1.1.tgz#4c7498e4861878e299ef058bce1208a4d063d0ff"
integrity sha512-Bu2XgOvzirnLcojZYs4KQ8hOLf2ETpa0NL6btQt5NgsAwctI6yVkzgYP+EcG7Mm579RBP+V0LM5rXyMlTVx23A==
version "1.1.2"
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.1.2.tgz#3114da877ddd9d2d0be10188371e15855aa71368"
integrity sha512-BkgD5iH2n3+Fdd/+xfhac8VbISo4MPvECPhK1kRpuYC7PnhxaJe2rpU7B4udvMeEL8lhJlvCWybo8Y7A29u/xQ==
dependencies:
"@peculiar/asn1-schema" "^2.0.3"
"@peculiar/asn1-schema" "^2.0.8"
"@peculiar/json-schema" "^1.1.10"
pvtsutils "^1.0.10"
tslib "^1.11.2"
webcrypto-core "^1.1.0"
tslib "^2.0.0"
webcrypto-core "^1.1.2"
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
@ -2921,9 +2921,15 @@ grpc@^1.21.1:
node-pre-gyp "^0.13.0"
protobufjs "^5.0.3"
<<<<<<< HEAD
"gun@git://github.com/amark/gun#3e678b8568a4a8a825b84b26759d4dd4f3b0988e":
version "0.2020.520"
resolved "git://github.com/amark/gun#3e678b8568a4a8a825b84b26759d4dd4f3b0988e"
=======
"gun@git://github.com/amark/gun#97aa976c97e6219a9f93095d32c220dcd371ca62":
version "0.2020.520"
resolved "git://github.com/amark/gun#97aa976c97e6219a9f93095d32c220dcd371ca62"
>>>>>>> master
dependencies:
ws "^7.2.1"
optionalDependencies:
@ -4298,7 +4304,7 @@ lodash@=4.17.4:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.5.0:
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5:
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
@ -6463,6 +6469,11 @@ tslib@^1.11.1, tslib@^1.11.2:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
tslib@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3"
integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
@ -6703,7 +6714,7 @@ wcwidth@^1.0.1:
dependencies:
defaults "^1.0.3"
webcrypto-core@^1.1.0:
webcrypto-core@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.1.2.tgz#c522a9e5596688f2b6bb19e2d336f68efa8bdd57"
integrity sha512-LxM/dTcXr/ZnwwKLox0tGEOIqvP7KIJ4Hk/fFPX20tr1EgqTmpEFZinmu4FzoGVbs6e4jI1priQKCDrOBD3L6w==