Merge branch 'master' into feature/lnd-10
This commit is contained in:
commit
33e18bec2e
19 changed files with 1275 additions and 60 deletions
3
.dockerignore
Normal file
3
.dockerignore
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
**/.git
|
||||||
|
**/node_modules
|
||||||
|
**/radata
|
||||||
6
.env.example
Normal file
6
.env.example
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
DATA_FILE_NAME=data3
|
||||||
|
PEERS=["http://gun.shock.network:8765/gun"]
|
||||||
|
MS_TO_TOKEN_EXPIRATION=4500000
|
||||||
|
DISABLE_SHOCK_ENCRYPTION=false
|
||||||
|
CACHE_HEADERS_MANDATORY=true
|
||||||
|
SHOCK_CACHE=true
|
||||||
29
Dockerfile
Normal file
29
Dockerfile
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
FROM node:12.18.0-alpine3.9
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
|
||||||
|
ADD ./package.json /usr/src/app/package.json
|
||||||
|
ADD ./yarn.lock /usr/src/app/yarn.lock
|
||||||
|
#RUN useradd app && \
|
||||||
|
# mkdir -p /home/app/.lnd
|
||||||
|
RUN apk update && apk upgrade && \
|
||||||
|
apk add --no-cache bash git openssh
|
||||||
|
RUN yarn install
|
||||||
|
|
||||||
|
ADD . /usr/src/app
|
||||||
|
RUN ls /usr/src/app
|
||||||
|
|
||||||
|
RUN chmod +x ./docker-start.sh
|
||||||
|
#ADD ./tls.cert /usr/src/app/tls.cert
|
||||||
|
#ADD ./admin.macaroon /usr/src/app/admin.macaroon
|
||||||
|
|
||||||
|
# && \
|
||||||
|
# chown -R app:app /home/app && \
|
||||||
|
# chown -R app:app /usr/src/app && \
|
||||||
|
# chown -R app:app /start.sh
|
||||||
|
|
||||||
|
#ARG lnd_address
|
||||||
|
#ENV LND_ADDR=$lnd_address
|
||||||
|
EXPOSE 9835
|
||||||
|
CMD ["./docker-start.sh"]
|
||||||
5
docker-start.sh
Normal file
5
docker-start.sh
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/ash
|
||||||
|
node main -h 0.0.0.0 \
|
||||||
|
-m admin.macaroon \
|
||||||
|
-d tls.cert \
|
||||||
|
-l $LND_ADDR
|
||||||
|
|
@ -41,11 +41,12 @@
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"method-override": "^2.3.7",
|
"method-override": "^2.3.7",
|
||||||
"promise": "^8.0.1",
|
"promise": "^8.0.1",
|
||||||
|
"ramda": "^0.27.0",
|
||||||
"request": "^2.87.0",
|
"request": "^2.87.0",
|
||||||
"request-promise": "^4.2.2",
|
"request-promise": "^4.2.2",
|
||||||
"response-time": "^2.3.2",
|
"response-time": "^2.3.2",
|
||||||
"shelljs": "^0.8.2",
|
"shelljs": "^0.8.2",
|
||||||
"shock-common": "^0.0.1",
|
"shock-common": "4.0.1",
|
||||||
"socket.io": "2.1.1",
|
"socket.io": "2.1.1",
|
||||||
"text-encoding": "^0.7.0",
|
"text-encoding": "^0.7.0",
|
||||||
"tingodb": "^0.6.1",
|
"tingodb": "^0.6.1",
|
||||||
|
|
@ -61,6 +62,7 @@
|
||||||
"@types/jest": "^24.0.18",
|
"@types/jest": "^24.0.18",
|
||||||
"@types/jsonwebtoken": "^8.3.7",
|
"@types/jsonwebtoken": "^8.3.7",
|
||||||
"@types/lodash": "^4.14.141",
|
"@types/lodash": "^4.14.141",
|
||||||
|
"@types/ramda": "types/npm-ramda#dist",
|
||||||
"@types/socket.io": "^2.1.4",
|
"@types/socket.io": "^2.1.4",
|
||||||
"@types/uuid": "^3.4.5",
|
"@types/uuid": "^3.4.5",
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
|
|
@ -78,9 +80,12 @@
|
||||||
"typescript": "^3.6.3"
|
"typescript": "^3.6.3"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,ts}": [
|
"*.js": [
|
||||||
"prettier --check",
|
"prettier --check",
|
||||||
"eslint"
|
"eslint"
|
||||||
|
],
|
||||||
|
"*.ts": [
|
||||||
|
"prettier --check"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,20 @@
|
||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
const Gun = require('gun')
|
const Gun = require('gun')
|
||||||
|
// @ts-ignore
|
||||||
|
require('gun/nts')
|
||||||
const logger = require('winston')
|
const logger = require('winston')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
Gun.log = () => {}
|
Gun.log = () => {}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
require('gun/lib/open')
|
require('gun/lib/open')
|
||||||
|
// @ts-ignore
|
||||||
|
require('gun/lib/load')
|
||||||
const debounce = require('lodash/debounce')
|
const debounce = require('lodash/debounce')
|
||||||
const Encryption = require('../../../utils/encryptionStore')
|
const Encryption = require('../../../utils/encryptionStore')
|
||||||
|
|
||||||
|
const Key = require('../contact-api/key')
|
||||||
|
|
||||||
/** @type {import('../contact-api/SimpleGUN').ISEA} */
|
/** @type {import('../contact-api/SimpleGUN').ISEA} */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const SEAx = require('gun/sea')
|
const SEAx = require('gun/sea')
|
||||||
|
|
@ -265,6 +271,24 @@ const authenticate = async (alias, pass, __user) => {
|
||||||
if (typeof ack.err === 'string') {
|
if (typeof ack.err === 'string') {
|
||||||
throw new Error(ack.err)
|
throw new Error(ack.err)
|
||||||
} else if (typeof ack.sea === 'object') {
|
} else if (typeof ack.sea === 'object') {
|
||||||
|
// clock skew
|
||||||
|
await new Promise(res => setTimeout(res, 2000))
|
||||||
|
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
_user.get(Key.FOLLOWS).put(
|
||||||
|
{
|
||||||
|
unused: null
|
||||||
|
},
|
||||||
|
ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(`Error initializing follows: ${ack.err}`))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
return ack.sea.pub
|
return ack.sea.pub
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unknown error.')
|
throw new Error('Unknown error.')
|
||||||
|
|
@ -277,6 +301,25 @@ const authenticate = async (alias, pass, __user) => {
|
||||||
`Tried to re-authenticate with an alias different to that of stored one, tried: ${alias} - stored: ${_currentAlias}, logoff first if need to change aliases.`
|
`Tried to re-authenticate with an alias different to that of stored one, tried: ${alias} - stored: ${_currentAlias}, logoff first if need to change aliases.`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clock skew
|
||||||
|
await new Promise(res => setTimeout(res, 2000))
|
||||||
|
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
_user.get(Key.FOLLOWS).put(
|
||||||
|
{
|
||||||
|
unused: null
|
||||||
|
},
|
||||||
|
ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(`Error initializing follows: ${ack.err}`))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
// move this to a subscription; implement off() ? todo
|
// move this to a subscription; implement off() ? todo
|
||||||
API.Jobs.onAcceptedRequests(_user, mySEA)
|
API.Jobs.onAcceptedRequests(_user, mySEA)
|
||||||
API.Jobs.onOrders(_user, gun, mySEA)
|
API.Jobs.onOrders(_user, gun, mySEA)
|
||||||
|
|
@ -310,6 +353,21 @@ const authenticate = async (alias, pass, __user) => {
|
||||||
|
|
||||||
await new Promise(res => setTimeout(res, 5000))
|
await new Promise(res => setTimeout(res, 5000))
|
||||||
|
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
_user.get(Key.FOLLOWS).put(
|
||||||
|
{
|
||||||
|
unused: null
|
||||||
|
},
|
||||||
|
ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(`Error initializing follows: ${ack.err}`))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
API.Jobs.onAcceptedRequests(_user, mySEA)
|
API.Jobs.onAcceptedRequests(_user, mySEA)
|
||||||
API.Jobs.onOrders(_user, gun, mySEA)
|
API.Jobs.onOrders(_user, gun, mySEA)
|
||||||
API.Jobs.lastSeenNode(_user)
|
API.Jobs.lastSeenNode(_user)
|
||||||
|
|
@ -328,6 +386,17 @@ const logoff = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const instantiateGun = () => {
|
const instantiateGun = () => {
|
||||||
|
if (user) {
|
||||||
|
user.leave()
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
user = null
|
||||||
|
if (gun) {
|
||||||
|
gun.off()
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
gun = null
|
||||||
|
|
||||||
const _gun = /** @type {unknown} */ (new Gun({
|
const _gun = /** @type {unknown} */ (new Gun({
|
||||||
axe: false,
|
axe: false,
|
||||||
peers: Config.PEERS
|
peers: Config.PEERS
|
||||||
|
|
@ -1217,7 +1286,7 @@ const register = async (alias, pass) => {
|
||||||
|
|
||||||
if (typeof ack.err === 'string') {
|
if (typeof ack.err === 'string') {
|
||||||
throw new Error(ack.err)
|
throw new Error(ack.err)
|
||||||
} else if (typeof ack.pub === 'string') {
|
} else if (typeof ack.pub === 'string' || typeof user._.sea === 'object') {
|
||||||
const mySecret = await mySEA.secret(user._.sea.epub, user._.sea)
|
const mySecret = await mySEA.secret(user._.sea.epub, user._.sea)
|
||||||
_currentAlias = alias
|
_currentAlias = alias
|
||||||
_currentPass = await mySEA.encrypt(pass, mySecret)
|
_currentPass = await mySEA.encrypt(pass, mySecret)
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ export interface Soul {
|
||||||
export type OpenListenerData = Primitive | null | OpenListenerDataObj
|
export type OpenListenerData = Primitive | null | OpenListenerDataObj
|
||||||
export type OpenListener = (data: OpenListenerData, key: string) => void
|
export type OpenListener = (data: OpenListenerData, key: string) => void
|
||||||
|
|
||||||
|
export type LoadListenerData = OpenListenerData
|
||||||
|
export type LoadListener = (data: LoadListenerData, key: string) => void
|
||||||
|
|
||||||
export interface GUNNodeBase {
|
export interface GUNNodeBase {
|
||||||
_: Soul
|
_: Soul
|
||||||
|
|
||||||
|
|
@ -47,6 +50,9 @@ export interface GUNNodeBase {
|
||||||
once(this: GUNNode, cb?: Listener): GUNNode
|
once(this: GUNNode, cb?: Listener): GUNNode
|
||||||
|
|
||||||
open(this: GUNNode, cb?: OpenListener): GUNNode
|
open(this: GUNNode, cb?: OpenListener): GUNNode
|
||||||
|
load(this: GUNNode, cb?: OpenListener): GUNNode
|
||||||
|
|
||||||
|
load(this: GUNNode, cb?: LoadListener): GUNNode
|
||||||
|
|
||||||
off(): void
|
off(): void
|
||||||
user(): UserGUNNode
|
user(): UserGUNNode
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
*/
|
*/
|
||||||
const uuidv1 = require('uuid/v1')
|
const uuidv1 = require('uuid/v1')
|
||||||
const logger = require('winston')
|
const logger = require('winston')
|
||||||
const { Constants, Schema } = require('shock-common')
|
const Common = require('shock-common')
|
||||||
|
const { Constants, Schema } = Common
|
||||||
|
|
||||||
const { ErrorCode } = Constants
|
const { ErrorCode } = Constants
|
||||||
|
|
||||||
|
|
@ -1133,7 +1134,21 @@ const setBio = (bio, user) =>
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
}).then(
|
||||||
|
() =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
user
|
||||||
|
.get(Key.PROFILE)
|
||||||
|
.get(Key.BIO)
|
||||||
|
.put(bio, ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
reject(new Error(ack.err))
|
||||||
|
} else {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string[]} mnemonicPhrase
|
* @param {string[]} mnemonicPhrase
|
||||||
|
|
@ -1156,7 +1171,7 @@ const saveSeedBackup = async (mnemonicPhrase, user, SEA) => {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
user.get(Key.SEED_BACKUP).put(encryptedSeed, ack => {
|
user.get(Key.SEED_BACKUP).put(encryptedSeed, ack => {
|
||||||
if (ack.err) {
|
if (ack.err) {
|
||||||
rej(ack.err)
|
rej(new Error(ack.err))
|
||||||
} else {
|
} else {
|
||||||
res()
|
res()
|
||||||
}
|
}
|
||||||
|
|
@ -1179,7 +1194,7 @@ const saveChannelsBackup = async (backups, user, SEA) => {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
user.get(Key.CHANNELS_BACKUP).put(encryptBackups, ack => {
|
user.get(Key.CHANNELS_BACKUP).put(encryptBackups, ack => {
|
||||||
if (ack.err) {
|
if (ack.err) {
|
||||||
rej(ack.err)
|
rej(new Error(ack.err))
|
||||||
} else {
|
} else {
|
||||||
res()
|
res()
|
||||||
}
|
}
|
||||||
|
|
@ -1216,6 +1231,275 @@ const setLastSeenApp = () =>
|
||||||
res()
|
res()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}).then(
|
||||||
|
() =>
|
||||||
|
new Promise((res, rej) => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.PROFILE)
|
||||||
|
.get(Key.LAST_SEEN_APP)
|
||||||
|
.put(Date.now(), ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(ack.err))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} tags
|
||||||
|
* @param {string} title
|
||||||
|
* @param {Common.Schema.ContentItem[]} content
|
||||||
|
* @returns {Promise<Common.Schema.Post>}
|
||||||
|
*/
|
||||||
|
const createPost = async (tags, title, content) => {
|
||||||
|
if (content.length === 0) {
|
||||||
|
throw new Error(`A post must contain at least one paragraph/image/video`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const numOfPages = await (async () => {
|
||||||
|
const maybeNumOfPages = await Utils.tryAndWait(
|
||||||
|
(_, user) =>
|
||||||
|
user
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.NUM_OF_PAGES)
|
||||||
|
.then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
return typeof maybeNumOfPages === 'number' ? maybeNumOfPages : 0
|
||||||
|
})()
|
||||||
|
|
||||||
|
let pageIdx = Math.max(0, numOfPages - 1).toString()
|
||||||
|
|
||||||
|
const count = await (async () => {
|
||||||
|
if (numOfPages === 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const maybeCount = await Utils.tryAndWait(
|
||||||
|
(_, user) =>
|
||||||
|
user
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(pageIdx)
|
||||||
|
.get(Key.COUNT)
|
||||||
|
.then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
return typeof maybeCount === 'number' ? maybeCount : 0
|
||||||
|
})()
|
||||||
|
|
||||||
|
const shouldBeNewPage =
|
||||||
|
count >= Common.Constants.Misc.NUM_OF_POSTS_PER_WALL_PAGE
|
||||||
|
|
||||||
|
if (shouldBeNewPage) {
|
||||||
|
pageIdx = Number(pageIdx + 1).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(pageIdx)
|
||||||
|
.put(
|
||||||
|
{
|
||||||
|
[Key.COUNT]: shouldBeNewPage ? 1 : count + 1,
|
||||||
|
posts: {
|
||||||
|
unused: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(ack.err))
|
||||||
|
}
|
||||||
|
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @type {string} */
|
||||||
|
const postID = await new Promise((res, rej) => {
|
||||||
|
const _n = require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(pageIdx)
|
||||||
|
.get(Key.POSTS)
|
||||||
|
.set(
|
||||||
|
{
|
||||||
|
date: Date.now(),
|
||||||
|
status: 'publish',
|
||||||
|
tags: tags.join('-'),
|
||||||
|
title
|
||||||
|
},
|
||||||
|
ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(ack.err))
|
||||||
|
} else {
|
||||||
|
res(_n._.get)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (shouldBeNewPage || numOfPages === 0) {
|
||||||
|
await new Promise(res => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.NUM_OF_PAGES)
|
||||||
|
.put(numOfPages + 1, ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
throw new Error(ack.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentItems = require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(pageIdx)
|
||||||
|
.get(Key.POSTS)
|
||||||
|
.get(postID)
|
||||||
|
.get(Key.CONTENT_ITEMS)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all(
|
||||||
|
content.map(
|
||||||
|
ci =>
|
||||||
|
new Promise(res => {
|
||||||
|
// @ts-ignore
|
||||||
|
contentItems.set(ci, ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
throw new Error(ack.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
await new Promise(res => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(pageIdx)
|
||||||
|
.get(Key.POSTS)
|
||||||
|
.get(postID)
|
||||||
|
.put(null, ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
throw new Error(ack.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadedPost = await new Promise(res => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(pageIdx)
|
||||||
|
.get(Key.POSTS)
|
||||||
|
.get(postID)
|
||||||
|
.load(data => {
|
||||||
|
res(data)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @type {Common.Schema.User} */
|
||||||
|
const userForPost = await Getters.getMyUser()
|
||||||
|
|
||||||
|
/** @type {Common.Schema.Post} */
|
||||||
|
const completePost = {
|
||||||
|
...loadedPost,
|
||||||
|
author: userForPost,
|
||||||
|
id: postID
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Common.Schema.isPost(completePost)) {
|
||||||
|
throw new Error(
|
||||||
|
`completePost not a Post inside Actions.createPost(): ${JSON.stringify(
|
||||||
|
createPost
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return completePost
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} postId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const deletePost = async postId => {
|
||||||
|
await new Promise(res => {
|
||||||
|
res(postId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} publicKey
|
||||||
|
* @param {boolean} isPrivate Will overwrite previous private status.
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
const follow = (publicKey, isPrivate) => {
|
||||||
|
/** @type {import('shock-common').Schema.Follow} */
|
||||||
|
const newFollow = {
|
||||||
|
private: isPrivate,
|
||||||
|
status: 'ok',
|
||||||
|
user: publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.FOLLOWS)
|
||||||
|
.get(publicKey)
|
||||||
|
// @ts-ignore
|
||||||
|
.put(newFollow, ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(ack.err))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} publicKey
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const unfollow = publicKey =>
|
||||||
|
new Promise((res, rej) => {
|
||||||
|
require('../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.FOLLOWS)
|
||||||
|
.get(publicKey)
|
||||||
|
.put(null, ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
rej(new Error(ack.err))
|
||||||
|
} else {
|
||||||
|
res()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
@ -1236,5 +1520,9 @@ module.exports = {
|
||||||
saveSeedBackup,
|
saveSeedBackup,
|
||||||
saveChannelsBackup,
|
saveChannelsBackup,
|
||||||
disconnect,
|
disconnect,
|
||||||
setLastSeenApp
|
setLastSeenApp,
|
||||||
|
createPost,
|
||||||
|
deletePost,
|
||||||
|
follow,
|
||||||
|
unfollow
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
const Key = require('./key')
|
|
||||||
const Utils = require('./utils')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} pub
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
exports.currentOrderAddress = async (pub) => {
|
|
||||||
const currAddr = await Utils.tryAndWait((gun) => gun.user(pub).get(Key.CURRENT_ORDER_ADDRESS).then())
|
|
||||||
|
|
||||||
if (typeof currAddr !== 'string') {
|
|
||||||
throw new TypeError('Expected user.currentOrderAddress to be an string')
|
|
||||||
}
|
|
||||||
|
|
||||||
return currAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} pub
|
|
||||||
* @returns {Promise<string|null>}
|
|
||||||
*/
|
|
||||||
exports.userToIncomingID = async (pub) => {
|
|
||||||
const incomingID = await require('../Mediator').getUser().get(Key.USER_TO_INCOMING).get(pub).then()
|
|
||||||
|
|
||||||
if (typeof incomingID === 'string') return incomingID
|
|
||||||
|
|
||||||
return null
|
|
||||||
|
|
||||||
}
|
|
||||||
79
services/gunDB/contact-api/getters/feed.js
Normal file
79
services/gunDB/contact-api/getters/feed.js
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
const Common = require('shock-common')
|
||||||
|
const isFinite = require('lodash/isFinite')
|
||||||
|
const shuffle = require('lodash/shuffle')
|
||||||
|
const R = require('ramda')
|
||||||
|
|
||||||
|
const Follows = require('./follows')
|
||||||
|
const Wall = require('./wall')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} numberOfPublicKeyGroups
|
||||||
|
* @param {number} pageRequested
|
||||||
|
* @returns {[ number , number ]}
|
||||||
|
*/
|
||||||
|
const calculateFeedPage = (numberOfPublicKeyGroups, pageRequested) => {
|
||||||
|
// thanks to sebassdc
|
||||||
|
|
||||||
|
return [
|
||||||
|
(pageRequested - 1) % numberOfPublicKeyGroups,
|
||||||
|
Math.ceil(pageRequested / numberOfPublicKeyGroups)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} page
|
||||||
|
* @throws {TypeError}
|
||||||
|
* @throws {RangeError}
|
||||||
|
* @returns {Promise<Common.SchemaTypes.Post[]>}
|
||||||
|
*/
|
||||||
|
const getFeedPage = async page => {
|
||||||
|
if (!isFinite(page)) {
|
||||||
|
throw new TypeError(`Please provide an actual number for [page]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page <= 0) {
|
||||||
|
throw new RangeError(`Please provide only positive numbers for [page]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const subbedPublicKeys = Object.values(await Follows.currentFollows()).map(
|
||||||
|
f => f.user
|
||||||
|
)
|
||||||
|
|
||||||
|
if (subbedPublicKeys.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// say there are 20 public keys total
|
||||||
|
// page 1: page 1 from first 10 public keys
|
||||||
|
// page 2: page 1 from second 10 public keys
|
||||||
|
// page 3: page 2 from first 10 public keys
|
||||||
|
// page 4: page 2 from first 10 public keys
|
||||||
|
// etc
|
||||||
|
// thanks to sebassdc (github)
|
||||||
|
|
||||||
|
const pagedPublicKeys = R.splitEvery(10, shuffle(subbedPublicKeys))
|
||||||
|
|
||||||
|
const [publicKeyGroupIdx, pageToRequest] = calculateFeedPage(
|
||||||
|
pagedPublicKeys.length,
|
||||||
|
page
|
||||||
|
)
|
||||||
|
|
||||||
|
const publicKeys = pagedPublicKeys[publicKeyGroupIdx]
|
||||||
|
|
||||||
|
const fetchedPages = await Promise.all(
|
||||||
|
publicKeys.map(pk => Wall.getWallPage(pageToRequest, pk))
|
||||||
|
)
|
||||||
|
|
||||||
|
const fetchedPostsGroups = fetchedPages.map(wp => Object.values(wp.posts))
|
||||||
|
const fetchedPosts = R.flatten(fetchedPostsGroups)
|
||||||
|
const sortered = R.sort((a, b) => b.date - a.date, fetchedPosts)
|
||||||
|
|
||||||
|
return sortered
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getFeedPage
|
||||||
|
}
|
||||||
59
services/gunDB/contact-api/getters/follows.js
Normal file
59
services/gunDB/contact-api/getters/follows.js
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
const Common = require('shock-common')
|
||||||
|
const Logger = require('winston')
|
||||||
|
const size = require('lodash/size')
|
||||||
|
|
||||||
|
const Utils = require('../utils')
|
||||||
|
const Key = require('../key')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Common.Schema.Follow} Follow
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws {TypeError}
|
||||||
|
* @returns {Promise<Record<string, Common.Schema.Follow>>}
|
||||||
|
*/
|
||||||
|
exports.currentFollows = async () => {
|
||||||
|
/**
|
||||||
|
* @type {Record<string, Common.Schema.Follow>}
|
||||||
|
*/
|
||||||
|
const raw = await Utils.tryAndWait(
|
||||||
|
// @ts-ignore
|
||||||
|
(_, user) => new Promise(res => user.get(Key.FOLLOWS).load(res)),
|
||||||
|
v => {
|
||||||
|
if (typeof v !== 'object' || v === null) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size(v) === 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (typeof raw !== 'object' || raw === null) {
|
||||||
|
Logger.error(
|
||||||
|
`Expected user.follows to be an object but instead got: ${JSON.stringify(
|
||||||
|
raw
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
throw new TypeError('Could not get follows, not an object')
|
||||||
|
}
|
||||||
|
|
||||||
|
const clean = {
|
||||||
|
...raw
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, followOrNull] of Object.entries(clean)) {
|
||||||
|
if (!Common.Schema.isFollow(followOrNull)) {
|
||||||
|
delete clean[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clean
|
||||||
|
}
|
||||||
101
services/gunDB/contact-api/getters/index.js
Normal file
101
services/gunDB/contact-api/getters/index.js
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
/**
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
const Common = require('shock-common')
|
||||||
|
|
||||||
|
const Key = require('../key')
|
||||||
|
const Utils = require('../utils')
|
||||||
|
|
||||||
|
const Wall = require('./wall')
|
||||||
|
const Feed = require('./feed')
|
||||||
|
const User = require('./user')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} pub
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
exports.currentOrderAddress = async pub => {
|
||||||
|
const currAddr = await Utils.tryAndWait(gun =>
|
||||||
|
gun
|
||||||
|
.user(pub)
|
||||||
|
.get(Key.CURRENT_ORDER_ADDRESS)
|
||||||
|
.then()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (typeof currAddr !== 'string') {
|
||||||
|
throw new TypeError('Expected user.currentOrderAddress to be an string')
|
||||||
|
}
|
||||||
|
|
||||||
|
return currAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} pub
|
||||||
|
* @returns {Promise<string|null>}
|
||||||
|
*/
|
||||||
|
exports.userToIncomingID = async pub => {
|
||||||
|
const incomingID = await require('../../Mediator')
|
||||||
|
.getUser()
|
||||||
|
.get(Key.USER_TO_INCOMING)
|
||||||
|
.get(pub)
|
||||||
|
.then()
|
||||||
|
|
||||||
|
if (typeof incomingID === 'string') return incomingID
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<Common.SchemaTypes.User>}
|
||||||
|
*/
|
||||||
|
const getMyUser = async () => {
|
||||||
|
const oldProfile = await Utils.tryAndWait(
|
||||||
|
(_, user) => new Promise(res => user.get(Key.PROFILE).load(res)),
|
||||||
|
v => typeof v !== 'object'
|
||||||
|
)
|
||||||
|
|
||||||
|
const bio = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.BIO).then(),
|
||||||
|
v => typeof v !== 'string'
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastSeenApp = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.LAST_SEEN_APP).then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastSeenNode = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.LAST_SEEN_NODE).then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
const publicKey = await Utils.tryAndWait(
|
||||||
|
(_, user) => Promise.resolve(user.is && user.is.pub),
|
||||||
|
v => typeof v !== 'string'
|
||||||
|
)
|
||||||
|
|
||||||
|
/** @type {Common.SchemaTypes.User} */
|
||||||
|
const u = {
|
||||||
|
avatar: oldProfile.avatar,
|
||||||
|
// @ts-ignore
|
||||||
|
bio,
|
||||||
|
displayName: oldProfile.displayName,
|
||||||
|
// @ts-ignore
|
||||||
|
lastSeenApp,
|
||||||
|
// @ts-ignore
|
||||||
|
lastSeenNode,
|
||||||
|
// @ts-ignore
|
||||||
|
publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getMyUser = getMyUser
|
||||||
|
module.exports.Follows = require('./follows')
|
||||||
|
|
||||||
|
module.exports.getWallPage = Wall.getWallPage
|
||||||
|
module.exports.getWallTotalPages = Wall.getWallTotalPages
|
||||||
|
|
||||||
|
module.exports.getFeedPage = Feed.getFeedPage
|
||||||
|
module.exports.getAnUser = User.getAnUser
|
||||||
111
services/gunDB/contact-api/getters/user.js
Normal file
111
services/gunDB/contact-api/getters/user.js
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
/**
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
const Common = require('shock-common')
|
||||||
|
|
||||||
|
const Key = require('../key')
|
||||||
|
const Utils = require('../utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} publicKey
|
||||||
|
* @returns {Promise<Common.SchemaTypes.User>}
|
||||||
|
*/
|
||||||
|
const getAnUser = async publicKey => {
|
||||||
|
const oldProfile = await Utils.tryAndWait(
|
||||||
|
g => {
|
||||||
|
const user = g.get(`~${publicKey}`)
|
||||||
|
|
||||||
|
return new Promise(res => user.get(Key.PROFILE).load(res))
|
||||||
|
},
|
||||||
|
v => typeof v !== 'object'
|
||||||
|
)
|
||||||
|
|
||||||
|
const bio = await Utils.tryAndWait(
|
||||||
|
g =>
|
||||||
|
g
|
||||||
|
.get(`~${publicKey}`)
|
||||||
|
.get(Key.BIO)
|
||||||
|
.then(),
|
||||||
|
v => typeof v !== 'string'
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastSeenApp = await Utils.tryAndWait(
|
||||||
|
g =>
|
||||||
|
g
|
||||||
|
.get(`~${publicKey}`)
|
||||||
|
.get(Key.LAST_SEEN_APP)
|
||||||
|
.then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastSeenNode = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.LAST_SEEN_NODE).then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
/** @type {Common.SchemaTypes.User} */
|
||||||
|
const u = {
|
||||||
|
avatar: oldProfile.avatar,
|
||||||
|
// @ts-ignore
|
||||||
|
bio,
|
||||||
|
displayName: oldProfile.displayName,
|
||||||
|
// @ts-ignore
|
||||||
|
lastSeenApp,
|
||||||
|
// @ts-ignore
|
||||||
|
lastSeenNode,
|
||||||
|
// @ts-ignore
|
||||||
|
publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getAnUser = getAnUser
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<Common.SchemaTypes.User>}
|
||||||
|
*/
|
||||||
|
const getMyUser = async () => {
|
||||||
|
const oldProfile = await Utils.tryAndWait(
|
||||||
|
(_, user) => new Promise(res => user.get(Key.PROFILE).load(res)),
|
||||||
|
v => typeof v !== 'object'
|
||||||
|
)
|
||||||
|
|
||||||
|
const bio = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.BIO).then(),
|
||||||
|
v => typeof v !== 'string'
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastSeenApp = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.LAST_SEEN_APP).then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
const lastSeenNode = await Utils.tryAndWait(
|
||||||
|
(_, user) => user.get(Key.LAST_SEEN_NODE).then(),
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
const publicKey = await Utils.tryAndWait(
|
||||||
|
(_, user) => Promise.resolve(user.is && user.is.pub),
|
||||||
|
v => typeof v !== 'string'
|
||||||
|
)
|
||||||
|
|
||||||
|
/** @type {Common.SchemaTypes.User} */
|
||||||
|
const u = {
|
||||||
|
avatar: oldProfile.avatar,
|
||||||
|
// @ts-ignore
|
||||||
|
bio,
|
||||||
|
displayName: oldProfile.displayName,
|
||||||
|
// @ts-ignore
|
||||||
|
lastSeenApp,
|
||||||
|
// @ts-ignore
|
||||||
|
lastSeenNode,
|
||||||
|
// @ts-ignore
|
||||||
|
publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getMyUser = getMyUser
|
||||||
131
services/gunDB/contact-api/getters/wall.js
Normal file
131
services/gunDB/contact-api/getters/wall.js
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
/**
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
const Common = require('shock-common')
|
||||||
|
|
||||||
|
const Utils = require('../utils')
|
||||||
|
const Key = require('../key')
|
||||||
|
|
||||||
|
const Wall = require('./user')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string=} publicKey
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
const getWallTotalPages = async publicKey => {
|
||||||
|
const totalPages = await Utils.tryAndWait(
|
||||||
|
(gun, u) => {
|
||||||
|
const user = publicKey ? gun.get(`~${publicKey}`) : u
|
||||||
|
|
||||||
|
return user
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.NUM_OF_PAGES)
|
||||||
|
.then()
|
||||||
|
},
|
||||||
|
v => typeof v !== 'number'
|
||||||
|
)
|
||||||
|
|
||||||
|
return typeof totalPages === 'number' ? totalPages : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} page
|
||||||
|
* @param {string=} publicKey
|
||||||
|
* @throws {TypeError}
|
||||||
|
* @throws {RangeError}
|
||||||
|
* @returns {Promise<Common.SchemaTypes.WallPage>}
|
||||||
|
*/
|
||||||
|
const getWallPage = async (page, publicKey) => {
|
||||||
|
const totalPages = await getWallTotalPages(publicKey)
|
||||||
|
|
||||||
|
if (page === 0 || totalPages === 0) {
|
||||||
|
return {
|
||||||
|
count: 0,
|
||||||
|
posts: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const actualPageIdx = page < 0 ? totalPages + page : page - 1
|
||||||
|
|
||||||
|
if (actualPageIdx > totalPages - 1) {
|
||||||
|
throw new RangeError(`Requested a page out of bounds`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Common.SchemaTypes.WallPage}
|
||||||
|
*/
|
||||||
|
const thePage = await Utils.tryAndWait(
|
||||||
|
(g, u) => {
|
||||||
|
const user = publicKey ? g.get(`~${publicKey}`) : u
|
||||||
|
|
||||||
|
return new Promise(res => {
|
||||||
|
user
|
||||||
|
.get(Key.WALL)
|
||||||
|
.get(Key.PAGES)
|
||||||
|
.get(actualPageIdx.toString())
|
||||||
|
// @ts-ignore
|
||||||
|
.load(res)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
maybePage => {
|
||||||
|
if (typeof maybePage !== 'object' || maybePage === null) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const clean = {
|
||||||
|
...maybePage
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
for (const [key, post] of Object.entries(clean.posts)) {
|
||||||
|
// delete unsuccessful writes
|
||||||
|
if (post === null) {
|
||||||
|
// @ts-ignore
|
||||||
|
delete clean.posts[key]
|
||||||
|
} else {
|
||||||
|
post.id = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .load() sometimes doesn't load all data on first call
|
||||||
|
// @ts-ignore
|
||||||
|
if (Object.keys(clean.posts).length === 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return !Common.Schema.isWallPage(clean)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const clean = {
|
||||||
|
...thePage
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, post] of Object.entries(clean.posts)) {
|
||||||
|
// delete unsuccessful writes
|
||||||
|
if (post === null) {
|
||||||
|
delete clean.posts[key]
|
||||||
|
clean.count--
|
||||||
|
} else {
|
||||||
|
post.author = publicKey
|
||||||
|
? // eslint-disable-next-line no-await-in-loop
|
||||||
|
await Wall.getAnUser(publicKey)
|
||||||
|
: // eslint-disable-next-line no-await-in-loop
|
||||||
|
await Wall.getMyUser()
|
||||||
|
post.id = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Common.Schema.isWallPage(clean)) {
|
||||||
|
throw new Error(
|
||||||
|
`Fetched page not a wall page, instead got: ${JSON.stringify(clean)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return clean
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getWallTotalPages,
|
||||||
|
getWallPage
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,15 @@ const lastSeenNode = user => {
|
||||||
logger.error(`Error inside lastSeenNode job: ${ack.err}`)
|
logger.error(`Error inside lastSeenNode job: ${ack.err}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
user
|
||||||
|
.get(Key.PROFILE)
|
||||||
|
.get(Key.LAST_SEEN_NODE)
|
||||||
|
.put(Date.now(), ack => {
|
||||||
|
if (ack.err) {
|
||||||
|
logger.error(`Error inside lastSeenNode job: ${ack.err}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, LAST_SEEN_NODE_INTERVAL)
|
}, LAST_SEEN_NODE_INTERVAL)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,3 +42,16 @@ exports.CHANNELS_BACKUP = 'channelsBackup'
|
||||||
exports.LAST_SEEN_APP = 'lastSeenApp'
|
exports.LAST_SEEN_APP = 'lastSeenApp'
|
||||||
|
|
||||||
exports.LAST_SEEN_NODE = 'lastSeenNode'
|
exports.LAST_SEEN_NODE = 'lastSeenNode'
|
||||||
|
|
||||||
|
exports.WALL = 'wall'
|
||||||
|
|
||||||
|
exports.NUM_OF_PAGES = 'numOfPages'
|
||||||
|
|
||||||
|
exports.PAGES = 'pages'
|
||||||
|
|
||||||
|
exports.COUNT = 'count'
|
||||||
|
|
||||||
|
exports.CONTENT_ITEMS = 'contentItems'
|
||||||
|
exports.FOLLOWS = 'follows'
|
||||||
|
|
||||||
|
exports.POSTS = 'posts'
|
||||||
|
|
|
||||||
256
src/routes.js
256
src/routes.js
|
|
@ -12,7 +12,7 @@ const httpsAgent = require("https");
|
||||||
const responseTime = require("response-time");
|
const responseTime = require("response-time");
|
||||||
const uuid = require("uuid/v4");
|
const uuid = require("uuid/v4");
|
||||||
const Common = require('shock-common')
|
const Common = require('shock-common')
|
||||||
|
const isARealUsableNumber = require('lodash/isFinite')
|
||||||
|
|
||||||
const getListPage = require("../utils/paginate");
|
const getListPage = require("../utils/paginate");
|
||||||
const auth = require("../services/auth/auth");
|
const auth = require("../services/auth/auth");
|
||||||
|
|
@ -22,6 +22,7 @@ const LightningServices = require("../utils/lightningServices");
|
||||||
const GunDB = require("../services/gunDB/Mediator");
|
const GunDB = require("../services/gunDB/Mediator");
|
||||||
const { unprotectedRoutes, nonEncryptedRoutes } = require("../utils/protectedRoutes");
|
const { unprotectedRoutes, nonEncryptedRoutes } = require("../utils/protectedRoutes");
|
||||||
const GunActions = require("../services/gunDB/contact-api/actions")
|
const GunActions = require("../services/gunDB/contact-api/actions")
|
||||||
|
const GunGetters = require('../services/gunDB/contact-api/getters')
|
||||||
|
|
||||||
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
|
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
|
||||||
const SESSION_ID = uuid();
|
const SESSION_ID = uuid();
|
||||||
|
|
@ -33,6 +34,8 @@ module.exports = async (
|
||||||
mySocketsEvents,
|
mySocketsEvents,
|
||||||
{ serverPort, CA, CA_KEY, usetls }
|
{ serverPort, CA, CA_KEY, usetls }
|
||||||
) => {
|
) => {
|
||||||
|
const {timeout5} = require('../services/gunDB/contact-api/utils')
|
||||||
|
|
||||||
const Http = Axios.create({
|
const Http = Axios.create({
|
||||||
httpsAgent: new httpsAgent.Agent({
|
httpsAgent: new httpsAgent.Agent({
|
||||||
ca: await FS.readFile(CA)
|
ca: await FS.readFile(CA)
|
||||||
|
|
@ -227,7 +230,7 @@ module.exports = async (
|
||||||
const deviceId = req.headers["x-shockwallet-device-id"];
|
const deviceId = req.headers["x-shockwallet-device-id"];
|
||||||
logger.debug("Decrypting route...")
|
logger.debug("Decrypting route...")
|
||||||
try {
|
try {
|
||||||
if (nonEncryptedRoutes.includes(req.path)) {
|
if (nonEncryptedRoutes.includes(req.path) || process.env.DISABLE_SHOCK_ENCRYPTION === "true") {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,7 +252,7 @@ module.exports = async (
|
||||||
return res.status(401).json(error);
|
return res.status(401).json(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.method === "GET") {
|
if (req.method === "GET" || req.method === "DELETE" || !req.body.encryptionKey && !req.body.iv) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,6 +437,76 @@ 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
|
//register to listen for channel backups
|
||||||
const onNewChannelBackup = () => {
|
const onNewChannelBackup = () => {
|
||||||
logger.warn("Subscribing to channel backup ...")
|
logger.warn("Subscribing to channel backup ...")
|
||||||
|
|
@ -1715,8 +1788,6 @@ module.exports = async (
|
||||||
|
|
||||||
const GunEvent = Common.Constants.Event
|
const GunEvent = Common.Constants.Event
|
||||||
const Key = require('../services/gunDB/contact-api/key')
|
const Key = require('../services/gunDB/contact-api/key')
|
||||||
const { timeout5 } = require('../services/gunDB/contact-api/utils')
|
|
||||||
|
|
||||||
app.get("/api/gun/lndchanbackups", async (req,res) => {
|
app.get("/api/gun/lndchanbackups", async (req,res) => {
|
||||||
try{
|
try{
|
||||||
const user = require('../services/gunDB/Mediator').getUser()
|
const user = require('../services/gunDB/Mediator').getUser()
|
||||||
|
|
@ -1731,6 +1802,18 @@ module.exports = async (
|
||||||
res.json({ok:"err"})
|
res.json({ok:"err"})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
app.get("/api/gun/feedpoc", async (req,res) =>{
|
||||||
|
try{
|
||||||
|
logger.warn("FEED POC")
|
||||||
|
const user = require('../services/gunDB/Mediator').getUser()
|
||||||
|
const feedObj = await timeout5(user.get("FEED_POC").then())
|
||||||
|
logger.warn(feedObj)
|
||||||
|
|
||||||
|
res.json({data:feedObj})
|
||||||
|
} catch (err) {
|
||||||
|
//res.json({ok:"err"})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const Events = require('../services/gunDB/contact-api/events')
|
const Events = require('../services/gunDB/contact-api/events')
|
||||||
|
|
||||||
|
|
@ -1854,6 +1937,169 @@ module.exports = async (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
app.get(`/api/gun/wall/:publicKey?`, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { page } = req.query;
|
||||||
|
const {publicKey} = req.params
|
||||||
|
|
||||||
|
const pageNum = Number(page)
|
||||||
|
|
||||||
|
if (!isARealUsableNumber(pageNum)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
field: 'page',
|
||||||
|
errorMessage: 'Not a number'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalPages = await GunGetters.getWallTotalPages(publicKey)
|
||||||
|
const fetchedPage = await GunGetters.getWallPage(pageNum, publicKey)
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
...fetchedPage,
|
||||||
|
totalPages,
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({
|
||||||
|
errorMessage: err.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.post(`/api/gun/wall/`, async (req,res) => {
|
||||||
|
try{
|
||||||
|
const {tags,title,contentItems} = req.body
|
||||||
|
return res.status(200).json(await GunActions.createPost(
|
||||||
|
tags,
|
||||||
|
title,
|
||||||
|
contentItems
|
||||||
|
))
|
||||||
|
} catch(e) {
|
||||||
|
return res.status(500).json({
|
||||||
|
errorMessage: (typeof e === 'string' ? e : e.message)
|
||||||
|
|| 'Unknown error.'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.delete(`/api/gun/wall/:postID`, (_, res) => res.status(200).json({
|
||||||
|
ok: 'true'
|
||||||
|
}))
|
||||||
|
/////////////////////////////////
|
||||||
|
/**
|
||||||
|
* @template P
|
||||||
|
* @typedef {import('express-serve-static-core').RequestHandler<P>} RequestHandler
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const ap = /** @type {Application} */ (app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} FollowsRouteParams
|
||||||
|
* @prop {(string|undefined)=} publicKey
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {RequestHandler<FollowsRouteParams>}
|
||||||
|
*/
|
||||||
|
const apiGunFollowsGet = async (_, res) => {
|
||||||
|
try {
|
||||||
|
const currFollows = await GunGetters.Follows.currentFollows()
|
||||||
|
|
||||||
|
return res.status(200).json(currFollows)
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({
|
||||||
|
errorMessage: err.message || 'Unknown ERR at GET /api/follows'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {RequestHandler<FollowsRouteParams>}
|
||||||
|
*/
|
||||||
|
const apiGunFollowsPut = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { publicKey } = req.params;
|
||||||
|
if (!publicKey) {
|
||||||
|
throw new Error(`Missing publicKey route param.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
await GunActions.follow(req.params.publicKey, false)
|
||||||
|
|
||||||
|
// 201 would be extraneous here. Implement it inside app.put
|
||||||
|
return res.status(200).json({
|
||||||
|
ok: true
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({
|
||||||
|
errorMessage: err.message || 'Unknown error inside /api/gun/follows/'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {RequestHandler<FollowsRouteParams>}
|
||||||
|
*/
|
||||||
|
const apiGunFollowsDelete = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { publicKey } = req.params;
|
||||||
|
if (!publicKey) {
|
||||||
|
throw new Error(`Missing publicKey route param.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
await GunActions.unfollow(req.params.publicKey)
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
ok: true
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({
|
||||||
|
errorMessage: err.message || 'Unknown error inside /api/gun/follows/'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ap.get('/api/gun/follows/', apiGunFollowsGet)
|
||||||
|
ap.get('/api/gun/follows/:publicKey', apiGunFollowsGet)
|
||||||
|
ap.put(`/api/gun/follows/:publicKey`,apiGunFollowsPut)
|
||||||
|
ap.delete(`/api/gun/follows/:publicKey`, apiGunFollowsDelete)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {RequestHandler<{}>}
|
||||||
|
*/
|
||||||
|
const apiGunFeedGet = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { page: pageStr } = req.query;
|
||||||
|
const page = Number(pageStr)
|
||||||
|
|
||||||
|
if (!isARealUsableNumber(page)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
field: 'page',
|
||||||
|
errorMessage: 'page must be a number'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page < 1) {
|
||||||
|
return res.status(400).json({
|
||||||
|
field: page,
|
||||||
|
errorMessage: 'page must be a positive number'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
posts: await GunGetters.getFeedPage(page)
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({
|
||||||
|
errorMessage: err.message || 'Unknown error inside /api/gun/follows/'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ap.get(`/api/gun/feed`, apiGunFeedGet)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return app so that it can be used by express.
|
* Return app so that it can be used by express.
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const server = program => {
|
||||||
const Http = require('http')
|
const Http = require('http')
|
||||||
const Express = require('express')
|
const Express = require('express')
|
||||||
const Crypto = require('crypto')
|
const Crypto = require('crypto')
|
||||||
|
const Dotenv = require('dotenv')
|
||||||
const LightningServices = require('../utils/lightningServices')
|
const LightningServices = require('../utils/lightningServices')
|
||||||
const Encryption = require('../utils/encryptionStore')
|
const Encryption = require('../utils/encryptionStore')
|
||||||
const app = Express()
|
const app = Express()
|
||||||
|
|
@ -25,6 +26,7 @@ const server = program => {
|
||||||
// load app default configuration data
|
// load app default configuration data
|
||||||
const defaults = require('../config/defaults')(program.mainnet)
|
const defaults = require('../config/defaults')(program.mainnet)
|
||||||
// define useful global variables ======================================
|
// define useful global variables ======================================
|
||||||
|
Dotenv.config()
|
||||||
module.useTLS = program.usetls
|
module.useTLS = program.usetls
|
||||||
module.serverPort = program.serverport || defaults.serverPort
|
module.serverPort = program.serverport || defaults.serverPort
|
||||||
module.httpsPort = module.serverPort
|
module.httpsPort = module.serverPort
|
||||||
|
|
@ -41,6 +43,12 @@ const server = program => {
|
||||||
|
|
||||||
logger.info('Mainnet Mode:', !!program.mainnet)
|
logger.info('Mainnet Mode:', !!program.mainnet)
|
||||||
|
|
||||||
|
if (process.env.DISABLE_SHOCK_ENCRYPTION === 'true') {
|
||||||
|
logger.error('Encryption Mode: false')
|
||||||
|
} else {
|
||||||
|
logger.info('Encryption Mode: true')
|
||||||
|
}
|
||||||
|
|
||||||
const stringifyData = data => {
|
const stringifyData = data => {
|
||||||
if (typeof data === 'object') {
|
if (typeof data === 'object') {
|
||||||
const stringifiedData = JSON.stringify(data)
|
const stringifiedData = JSON.stringify(data)
|
||||||
|
|
@ -60,6 +68,46 @@ const server = program => {
|
||||||
.digest('hex')
|
.digest('hex')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cacheCheck = ({ req, res, args, send }) => {
|
||||||
|
if (
|
||||||
|
(process.env.SHOCK_CACHE === 'true' || !process.env.SHOCK_CACHE) &&
|
||||||
|
req.method === 'GET'
|
||||||
|
) {
|
||||||
|
const dataHash = hashData(args[0]).slice(-8)
|
||||||
|
res.set('shock-cache-hash', dataHash)
|
||||||
|
|
||||||
|
logger.debug('shock-cache-hash:', req.headers['shock-cache-hash'])
|
||||||
|
logger.debug('Data Hash:', dataHash)
|
||||||
|
if (
|
||||||
|
!req.headers['shock-cache-hash'] &&
|
||||||
|
(process.env.CACHE_HEADERS_MANDATORY === 'true' ||
|
||||||
|
!process.env.CACHE_HEADERS_MANDATORY)
|
||||||
|
) {
|
||||||
|
logger.warn(
|
||||||
|
"Request is missing 'shock-cache-hash' header, please make sure to include that in each GET request in order to benefit from reduced data usage"
|
||||||
|
)
|
||||||
|
return { cached: false, hash: dataHash }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.headers['shock-cache-hash'] === dataHash) {
|
||||||
|
logger.debug('Same Hash Detected!')
|
||||||
|
args[0] = null
|
||||||
|
res.status(304)
|
||||||
|
send.apply(res, args)
|
||||||
|
return { cached: true, hash: dataHash }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { cached: false, hash: dataHash }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { cached: false, hash: null }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Express.Request} req
|
||||||
|
* @param {Express.Response} res
|
||||||
|
* @param {(() => void)} next
|
||||||
|
*/
|
||||||
const modifyResponseBody = (req, res, next) => {
|
const modifyResponseBody = (req, res, next) => {
|
||||||
const deviceId = req.headers['x-shockwallet-device-id']
|
const deviceId = req.headers['x-shockwallet-device-id']
|
||||||
const oldSend = res.send
|
const oldSend = res.send
|
||||||
|
|
@ -72,16 +120,9 @@ const server = program => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataHash = hashData(args[0]).slice(-8)
|
const { cached, hash } = cacheCheck({ req, res, args, send: oldSend })
|
||||||
res.set('shock-cache-hash', dataHash)
|
|
||||||
|
|
||||||
logger.debug('shock-cache-hash:', req.headers['shock-cache-hash'])
|
if (cached) {
|
||||||
logger.debug('Data Hash:', dataHash)
|
|
||||||
if (req.headers['shock-cache-hash'] === dataHash) {
|
|
||||||
logger.debug('Same Hash Detected!')
|
|
||||||
args[0] = null
|
|
||||||
res.status(304)
|
|
||||||
oldSend.apply(res, args)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,10 +130,10 @@ const server = program => {
|
||||||
const authorized = Encryption.isAuthorizedDevice({ deviceId })
|
const authorized = Encryption.isAuthorizedDevice({ deviceId })
|
||||||
const encryptedMessage = authorized
|
const encryptedMessage = authorized
|
||||||
? Encryption.encryptMessage({
|
? Encryption.encryptMessage({
|
||||||
message: args[0],
|
message: args[0] ? args[0] : {},
|
||||||
deviceId,
|
deviceId,
|
||||||
metadata: {
|
metadata: {
|
||||||
hash: dataHash
|
hash
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
: args[0]
|
: args[0]
|
||||||
|
|
@ -249,7 +290,9 @@ const server = program => {
|
||||||
// app.use(bodyParser.json({limit: '100000mb'}));
|
// app.use(bodyParser.json({limit: '100000mb'}));
|
||||||
app.use(bodyParser.json({ limit: '50mb' }))
|
app.use(bodyParser.json({ limit: '50mb' }))
|
||||||
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }))
|
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }))
|
||||||
app.use(modifyResponseBody)
|
if (process.env.DISABLE_SHOCK_ENCRYPTION !== 'true') {
|
||||||
|
app.use(modifyResponseBody)
|
||||||
|
}
|
||||||
|
|
||||||
serverInstance.listen(module.serverPort, module.serverhost)
|
serverInstance.listen(module.serverPort, module.serverhost)
|
||||||
|
|
||||||
|
|
|
||||||
49
yarn.lock
49
yarn.lock
|
|
@ -633,6 +633,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||||
|
|
||||||
|
"@types/ramda@types/npm-ramda#dist":
|
||||||
|
version "0.25.0"
|
||||||
|
resolved "https://codeload.github.com/types/npm-ramda/tar.gz/9529aa3c8ff70ff84afcbc0be83443c00f30ea90"
|
||||||
|
|
||||||
"@types/range-parser@*":
|
"@types/range-parser@*":
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||||
|
|
@ -3168,6 +3172,11 @@ ignore@^4.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||||
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
||||||
|
|
||||||
|
immer@^6.0.6:
|
||||||
|
version "6.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/immer/-/immer-6.0.9.tgz#b9dd69b8e69b3a12391e87db1e3ff535d1b26485"
|
||||||
|
integrity sha512-SyCYnAuiRf67Lvk0VkwFvwtDoEiCMjeamnHvRfnVDyc7re1/rQrNxuL+jJ7lA3WvdC4uznrvbmm+clJ9+XXatg==
|
||||||
|
|
||||||
import-fresh@^3.0.0:
|
import-fresh@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118"
|
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118"
|
||||||
|
|
@ -5383,6 +5392,11 @@ ramda@^0.26.1:
|
||||||
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
|
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
|
||||||
integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==
|
integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==
|
||||||
|
|
||||||
|
ramda@^0.27.0:
|
||||||
|
version "0.27.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.0.tgz#915dc29865c0800bf3f69b8fd6c279898b59de43"
|
||||||
|
integrity sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==
|
||||||
|
|
||||||
random-bytes@~1.0.0:
|
random-bytes@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
|
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
|
||||||
|
|
@ -5500,6 +5514,19 @@ rechoir@^0.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
resolve "^1.1.6"
|
resolve "^1.1.6"
|
||||||
|
|
||||||
|
redux-thunk@^2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
|
||||||
|
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
|
||||||
|
|
||||||
|
redux@^4.0.5:
|
||||||
|
version "4.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
|
||||||
|
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.4.0"
|
||||||
|
symbol-observable "^1.2.0"
|
||||||
|
|
||||||
regenerator-runtime@^0.11.0:
|
regenerator-runtime@^0.11.0:
|
||||||
version "0.11.1"
|
version "0.11.1"
|
||||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
||||||
|
|
@ -5876,13 +5903,17 @@ shellwords@^0.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
||||||
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
|
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
|
||||||
|
|
||||||
shock-common@^0.0.1:
|
shock-common@4.0.1:
|
||||||
version "0.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-0.0.1.tgz#72092c565ab65198da13656b5027fbd44881bf72"
|
resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-4.0.1.tgz#035e7081b6e67f6721e68dcc6b4d1e4c8f2cd96d"
|
||||||
integrity sha512-LV2WiJDr1E6TEWel095oLN6gxpGTmsg6CUeGB6DdLHbYEz0qSpcDG4MYp2mZGpj/DejNKwYg1EiX2qf7ArpIkQ==
|
integrity sha512-3xAkG8lyfyZHK8trgOy2aN75uG1ZBm0MPoIEzP4hgXhyT/b80WmQzX3DqVSSmjfhq1Di0sjmNCY7O5Nf6cEmFg==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
immer "^6.0.6"
|
||||||
lodash "^4.17.15"
|
lodash "^4.17.15"
|
||||||
normalizr "^3.6.0"
|
normalizr "^3.6.0"
|
||||||
|
redux "^4.0.5"
|
||||||
|
redux-thunk "^2.3.0"
|
||||||
|
uuid "3.x.x"
|
||||||
|
|
||||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
|
|
@ -6302,6 +6333,11 @@ supports-color@^7.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
symbol-observable@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||||
|
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
|
||||||
|
|
||||||
symbol-tree@^3.2.2:
|
symbol-tree@^3.2.2:
|
||||||
version "3.2.4"
|
version "3.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||||
|
|
@ -6672,6 +6708,11 @@ utils-merge@1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
||||||
|
|
||||||
|
uuid@3.x.x:
|
||||||
|
version "3.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
|
||||||
uuid@^3.3.2:
|
uuid@^3.3.2:
|
||||||
version "3.3.3"
|
version "3.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue