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 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 ./package.json /usr/src/app/package.json
ADD ./yarn.lock /usr/src/app/yarn.lock ADD ./yarn.lock /usr/src/app/yarn.lock
#RUN useradd app && \
# mkdir -p /home/app/.lnd RUN yarn
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
RUN yarn install
ADD . /usr/src/app ADD . /usr/src/app
RUN ls /usr/src/app
RUN chmod +x ./docker-start.sh ENTRYPOINT [ "node", "main.js" ]
#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"]

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. 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 ### Easy Installation
For easy setup on your Laptop/Desktop, [a node wizard is available here.](https://github.com/shocknet/wizard) 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 yarn install
``` ```
3) Run with `yarn start` 3) Run with `yarn start -t` *(`-t` is recommended but [not required](#node-security))*
4) Connect with Shockwallet *(Provide your nodes IP manually or scan QR from ShockWizard)* 4) Connect with Shockwallet
*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.*
### 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 ### Docker for Raspberry Pi
* [Instructions](https://gist.github.com/boufni95/3f4e1f19cf9525c3b7741b7a29f122bc) * [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", "name": "shockapi",
"version": "2021.6.28", "version": "2021.07.10",
"description": "", "description": "",
"main": "src/server.js", "main": "src/server.js",
"scripts": { "scripts": {

View file

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

View file

@ -1,8 +1,21 @@
//@ts-nocheck TODO- fix types //@ts-nocheck TODO- fix types
const { gunUUID } = require("../utils")
class TipsCB { class TipsCB {
listeners = {} 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) console.log("subbing new socket for post: "+postID)
if(!this.listeners[postID]){ if(!this.listeners[postID]){

View file

@ -48,22 +48,33 @@
} }
</style> </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/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> </head>
<body> <body>
<div class="main"> <div class="main">
<div class="content hide"> <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-message">JUST TIPPED YOU!</p>
<p id="content-amount">100sats</p> <p id="content-amount">100sats</p>
</div> </div>
</div> </div>
<script> <script>
console.log(location.origin)
const queryString = window.location.search; const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString); const urlParams = new URLSearchParams(queryString);
const postID = urlParams.get("postID") const accessId = urlParams.get("accessId")
var socket = io(`${location.origin}/streams`); const relayId = urlParams.get("x-shock-hybrid-relay-id-x")
socket.emit("postID",postID)
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 let latestTimeout = null
socket.on("update",(update)=>{ socket.on("update",(update)=>{
const name = document.querySelector("#content-name") 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 Key = require('../services/gunDB/contact-api/key')
const { startedStream, endStream } = require('../services/streams') const { startedStream, endStream } = require('../services/streams')
const channelRequest = require('../utils/lightningServices/channelRequests') const channelRequest = require('../utils/lightningServices/channelRequests')
const TipsForwarder = require('../services/tipsCallback')
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10 const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10
const SESSION_ID = uuid() const SESSION_ID = uuid()
@ -2291,11 +2292,20 @@ module.exports = async (
app.post(`/api/gun/wall/`, async (req, res) => { app.post(`/api/gun/wall/`, async (req, res) => {
try { try {
const { tags, title, contentItems } = req.body const { tags, title, contentItems, enableTipsOverlay } = req.body
const SEA = require('../services/gunDB/Mediator').mySEA const SEA = require('../services/gunDB/Mediator').mySEA
return res const postRes = await GunActions.createPostNew(
.status(200) tags,
.json(await GunActions.createPostNew(tags, title, contentItems, SEA)) 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) { } catch (e) {
console.log(e) console.log(e)
return res.status(500).json({ return res.status(500).json({
@ -3348,6 +3358,18 @@ module.exports = async (
ap.get('/api/subscribeStream', (req, res) => { ap.get('/api/subscribeStream', (req, res) => {
res.sendFile(path.join(__dirname, '/index.html')) 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 //this is for wasLive/isLive status
ap.post('/api/listenStream', (req, res) => { ap.post('/api/listenStream', (req, res) => {
try { try {

View file

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

View file

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