Merge branch 'master' into bug/bad-mac-logs

This commit is contained in:
emad-salah 2021-07-11 23:29:38 +01:00
commit 126003f0ef
9 changed files with 113 additions and 40 deletions

View file

@ -1,29 +1,19 @@
FROM node:12.18.0-alpine3.9
FROM node:lts-alpine
EXPOSE 9835
VOLUME [ "/lnd", "/data" ]
WORKDIR /usr/src/app
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
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
RUN yarn
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"]
ENTRYPOINT [ "node", "main.js" ]

View file

@ -11,6 +11,13 @@ This is an alpha release of the Shockwallet backend service, providing a wrapper
Run this service on your Lightning node and connect with a mobile device or desktop browser.
---
- [Easy Installation](#easy-installation)
- [Manual Installation](#manual-installation)
- [Docker Usage](#docker-usage)
- [Node Security](#node-security)
<!--- - [Docker for Raspberry Pi](#docker-for-raspberry-pi) -->
---
### Easy Installation
For easy setup on your Laptop/Desktop, [a node wizard is available here.](https://github.com/shocknet/wizard)
@ -42,12 +49,39 @@ cd api
yarn install
```
3) Run with `yarn start`
4) Connect with Shockwallet *(Provide your nodes IP manually or scan QR from ShockWizard)*
*Optionally, add the `-t` flag to route through a tunnel.rip webserver for zero-configuration networking. All communication between the api and wallet is end-to-end encrypted and your privacy is protected.*
3) Run with `yarn start -t` *(`-t` is recommended but [not required](#node-security))*
4) Connect with Shockwallet
### Docker Usage
To run ShockAPI in a fully isolated environment you can use the Docker image
provided on the Docker Hub and easily interact with API's CLI interface and flags.
Example of listing available configuration flags:
```
docker run --rm shockwallet/api:latest --help
```
Example of running an local instance:
```
docker run shockwallet/api:latest -h 0.0.0.0 -c
```
<!---
### Docker for Raspberry Pi
* [Instructions](https://gist.github.com/boufni95/3f4e1f19cf9525c3b7741b7a29f122bc)
-->
### Node Security
Shockwallet authenticates to the API with the keys of the `GUN` user. Where the API itself typically has full macaroon access to LND, we've implemented an extra security measure at user enrollment to whitelist these keys and prevent rogue authentication.
If installing the ShockAPI onto a pre-existing LND node instance, the decryption passphrase must be proven at user enrollment. This requires LND to be in a locked state when creating the user, and the `GUN` password to be synchronized with the LND decryption phrase.
The API will verify the defined `GUN` password unlocks LND before completing enrollment, and can thus be used in the future to directly unlock LND from Shockwallet. This will restrict authentication to only this `GUN` key. Changing or adding alternative users will require repeating this **"lock and enroll"** process.
There are advanced or testing scenarios where you may wish to bypass this sync and whitelist mechanism, to do so pass the env `TRUSTED_KEYS=false`
_New LND nodes will automatically use the `GUN` user password as their decryption phrase upon creation._
Communication between the wallet and API is encrypted regardless of whether or not SSL is used, though an SSL equipped reverse proxy is recommended for better usability with the wallet PWA. Running with `-t` enables the built-in SSL tunnel provider for ease of use and zero-configuration networking.

View file

@ -1,6 +1,6 @@
{
"name": "shockapi",
"version": "2021.6.28",
"version": "2021.07.10",
"description": "",
"main": "src/server.js",
"scripts": {

View file

@ -286,7 +286,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
TipForwarder.notifySocketIfAny(
postID,
order.from,
'TIPPED YOU',
paidInvoice.memo || 'TIPPED YOU',
amt + ' sats'
)
const ackData = { tippedPost: postID }

View file

@ -1,8 +1,21 @@
//@ts-nocheck TODO- fix types
const { gunUUID } = require("../utils")
class TipsCB {
listeners = {}
addSocket(postID,socket){
postsEnabled = {}
enablePostNotifications(postID){
const accessId = gunUUID()
this.postsEnabled[accessId] = postID
return accessId
}
addSocket(accessId,socket){
if(!this.postsEnabled[accessId]){
return "invalid access id"
}
const postID = this.postsEnabled[accessId]
console.log("subbing new socket for post: "+postID)
if(!this.listeners[postID]){

View file

@ -48,22 +48,33 @@
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.msgpack.min.js" crossorigin="anonymous"></script>
</head>
<body>
<div class="main">
<div class="content hide">
<p id="content-name">fdsigfudfsbigbfduigbdfb</p>
<p id="content-name">some random name i dont know</p>
<p id="content-message">JUST TIPPED YOU!</p>
<p id="content-amount">100sats</p>
</div>
</div>
<script>
console.log(location.origin)
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const postID = urlParams.get("postID")
var socket = io(`${location.origin}/streams`);
socket.emit("postID",postID)
const accessId = urlParams.get("accessId")
const relayId = urlParams.get("x-shock-hybrid-relay-id-x")
const socketSetting = {
reconnection: true,
rejectUnauthorized: false,
withCredentials: true,
transports: ["websocket"]
}
var socket = io(`${location.origin}/streams`,socketSetting);
socket.emit('hybridRelayId',{id:relayId})
socket.on("connect", () => {
setTimeout(()=>{socket.emit("accessId",accessId)},500)
})
let latestTimeout = null
socket.on("update",(update)=>{
const name = document.querySelector("#content-name")

View file

@ -37,6 +37,7 @@ const GunWriteRPC = require('../services/gunDB/rpc')
const Key = require('../services/gunDB/contact-api/key')
const { startedStream, endStream } = require('../services/streams')
const channelRequest = require('../utils/lightningServices/channelRequests')
const TipsForwarder = require('../services/tipsCallback')
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10
const SESSION_ID = uuid()
@ -2291,11 +2292,20 @@ module.exports = async (
app.post(`/api/gun/wall/`, async (req, res) => {
try {
const { tags, title, contentItems } = req.body
const { tags, title, contentItems, enableTipsOverlay } = req.body
const SEA = require('../services/gunDB/Mediator').mySEA
return res
.status(200)
.json(await GunActions.createPostNew(tags, title, contentItems, SEA))
const postRes = await GunActions.createPostNew(
tags,
title,
contentItems,
SEA
)
if (enableTipsOverlay) {
const [postID] = postRes
const accessId = TipsForwarder.enablePostNotifications(postID)
return res.status(200).json([...postRes, accessId])
}
return res.status(200).json(postRes)
} catch (e) {
console.log(e)
return res.status(500).json({
@ -3348,6 +3358,18 @@ module.exports = async (
ap.get('/api/subscribeStream', (req, res) => {
res.sendFile(path.join(__dirname, '/index.html'))
})
ap.post('/api/enableNotificationsOverlay', (req, res) => {
const { postID } = req.body
if (!postID) {
return res.status(400).json({
errorMessage: 'no post id provided'
})
}
const accessId = TipsForwarder.enablePostNotifications(postID)
res.json({
accessId
})
})
//this is for wasLive/isLive status
ap.post('/api/listenStream', (req, res) => {
try {

View file

@ -186,10 +186,13 @@ module.exports = (
io.of('streams').on('connect', socket => {
console.log('a user connected')
socket.on('postID', postID => {
TipsForwarder.addSocket(postID, socket)
socket.on('accessId', accessId => {
const err = TipsForwarder.addSocket(accessId, socket)
if (err) {
console.log('err invalid socket for tips notifications ' + err)
socket.disconnect(true)
}
})
})
return io
}

View file

@ -10,7 +10,7 @@ const { asyncFilter } = require('./helpers')
*/
const gunUUID = () => {
// @ts-expect-error Not typed
const uuid = Gun.Text.random()
const uuid = Gun.text.random()
return uuid
}