From 2ea5e8856680dfcf0593302650545ccad1629535 Mon Sep 17 00:00:00 2001 From: cipres Date: Thu, 5 May 2022 23:12:39 +0200 Subject: [PATCH] Add an IpfsObject interface in the ipfs dweb channel Add Dockerfile for Cloudron [appimage] [flatpak] [docker-x11] [deploy] --- .docker/x11vnc_cloudron_start.sh | 37 +++++++++++ BUILDING.rst | 7 +++ CloudronManifest.json | 19 +++++- Dockerfile.cloudron | 103 +++++++++++++++++++++++++++++++ Dockerfile.debian.x11vnc | 5 +- galacteek/dweb/channels/g.py | 2 +- galacteek/dweb/channels/ipfs.py | 94 ++++++++++++++++++++++++++++ galacteek/ui/qmlapp.py | 7 +++ 8 files changed, 269 insertions(+), 5 deletions(-) create mode 100755 .docker/x11vnc_cloudron_start.sh create mode 100644 Dockerfile.cloudron diff --git a/.docker/x11vnc_cloudron_start.sh b/.docker/x11vnc_cloudron_start.sh new file mode 100755 index 00000000..8f42d81f --- /dev/null +++ b/.docker/x11vnc_cloudron_start.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +Xvfb $DISPLAY -ac +iglx -screen 0 $XVFB_WHD & + +PWD=$(date +%s | sha256sum | base64 | head -c 12) + +x11vnc -display $DISPLAY -listen 0.0.0.0 -shared \ + -forever -passwd $PWD > /dev/null 2>&1 & + +echo "Container IP address:" + +ip a show eth0|grep 'inet' + +echo + +echo "Running healthcheck http service" + +hcdir=$(mktemp -d) + +nohup python3 -m http.server -d "${hcdir}" 8000 & + +cat < /dev/null 2>&1 & +sleep 1 + +exec "$@" diff --git a/BUILDING.rst b/BUILDING.rst index 3052c84a..c02c0a92 100644 --- a/BUILDING.rst +++ b/BUILDING.rst @@ -18,6 +18,7 @@ Install the dependencies with: pip install -r requirements-dev.txt pip install -r requirements.txt + Install the PyQt dependencies (the following extras can be used: *ui-pyqt-5.15*, *ui-pyqt-5.13*): @@ -25,6 +26,12 @@ Install the PyQt dependencies (the following extras can be used: pip install -e '.[ui-pyqt-5.15]' +Install bsddb: + +.. code-block:: shell + + pip install -r requirements-rdf-bsddb.txt + To build and install the application, use: .. code-block:: shell diff --git a/CloudronManifest.json b/CloudronManifest.json index b7b9485b..f6310fb4 100644 --- a/CloudronManifest.json +++ b/CloudronManifest.json @@ -5,14 +5,27 @@ "contactEmail": "galacteek@protonmail.com", "description": "Browser for the distributed web", "changelog": "file://CHANGELOG.md", - "version": "0.5.4", - "healthCheckPath": "/ipfs/bafybeiahiixfpzirbz6rjjd4fkgvw7kksaigyd3fwnomrw5r3eo56ls6xm", - "httpPort": 8080, + "version": "0.5.5", + "tagline": "Initial", + "healthCheckPath": "/", + "httpPort": 8000, "manifestVersion": 2, "memoryLimit": 524288000, "website": "https://galacteek.gitlab.io", "icon": "file://share/icons/galacteek-incandescent-128.png", + "addons": { + "localstorage": {} + }, + "tcpPorts": { + "SSH_PORT": { + "title": "SSH Tunnel for VNC", + "description": "SSH Port over which tunnel can be created for VNC", + "defaultValue": 5900, + "containerPort": 5900 + } + }, "tags": [ + "cloudron", "dweb", "ipfs", "qt", diff --git a/Dockerfile.cloudron b/Dockerfile.cloudron new file mode 100644 index 00000000..b1909225 --- /dev/null +++ b/Dockerfile.cloudron @@ -0,0 +1,103 @@ +# Adapted by timconsidine +# +# https://git.cloudron.io/timconsidine/cloudron-galacteek/-/raw/master/Dockerfile + +FROM python:3.7-slim-buster + +EXPOSE 5900-5904 +EXPOSE 4001 +EXPOSE 8080 +EXPOSE 8000 + +ENV NOTBIT_DIST_URL "https://gitlab.com/api/v4/projects/27627112/packages/generic/notbit/0.7/notbit.tar.gz" +ENV X11VNC_PASSWORD "galacteek" +ENV DEBIAN_FRONTEND "noninteractive" +ENV QT_QPA_PLATFORM=xcb +ENV DISPLAY=:99 +ENV XVFB_WHD=1024x768x24 +ENV QTWEBENGINE_DISABLE_SANDBOX=1 +ENV PATH "/app/code/bin:${PATH}" +# ENV QTWEBENGINE_CHROMIUM_FLAGS="--disable-gpu-compositing" + +# start TC added for Cloudron +ENV XDG_RUNTIME_DIR "/app/data/tmp/runtime-galacteek" +# end TC + +RUN echo "${PATH}" >> /etc/bash.bashrc + +RUN apt-get update && apt-get install -q -y --force-yes \ + gcc git net-tools iproute2 \ + libdb5.3-dev libdb-dev libdb5.3 \ + file libmagic1 libmagic-mgc \ + libgl1-mesa-glx libnss3 libxtst6 libxext6 \ + libasound2 libegl1-mesa libpulse-mainloop-glib0 libpulse0 \ + libzbar0 xvfb xorg dbus-x11 wget \ + xfonts-100dpi xfonts-75dpi x11vnc fluxbox \ + libxkbcommon-x11-0 libxkbcommon0 libgl1 xinit x11-xserver-utils \ + libxcb-xkb1 libxcb-icccm4 libxcb-composite0 libxcb-util0 \ + libxcb-image0 libxcb-keysyms1 libxcb-render-util0 \ + libxcb-xinerama0 libqt5multimedia5 libqt5multimediaquick5 + +# start TC added for Cloudron +RUN mkdir -p /app/code +RUN mkdir -p /tmp/.X11-unix +RUN chmod 1777 /tmp/.X11-unix +WORKDIR /app/code +# end TC + +# Get ipfs binary +RUN wget http://dist.ipfs.io/go-ipfs/v0.9.1/go-ipfs_v0.9.1_linux-amd64.tar.gz && \ + tar -xvf go-ipfs_v0.9.1_linux-amd64.tar.gz && \ + cp go-ipfs/ipfs /app/code/bin && cp go-ipfs/ipfs /usr/bin && \ + rm go-ipfs_v0.9.1_linux-amd64.tar.gz + +# Add source code. +COPY README.rst COPYING LICENSE LICENSE.go-ipfs \ + requirements*.txt setup.py galacteek.pro \ + /app/code/galacteek/ + +COPY share /app/code/galacteek/share +COPY galacteek/ /app/code/galacteek/galacteek + +COPY requirements.txt requirements-dev.txt \ + requirements-extra-markdown.txt \ + requirements-rdf-bsddb.txt \ + requirements-ui-pyqt-5.15.txt \ + ./ + +RUN pip install -U pip wheel && pip install -r requirements.txt && \ + pip install -r requirements-dev.txt && \ + pip install -r requirements-extra-markdown.txt && \ + pip install -r requirements-rdf-bsddb.txt && \ + pip install -r requirements-ui-pyqt-5.15.txt + +RUN cd /app/code/galacteek && \ + python setup.py build build_docs install && \ + rm -f requirements*.txt + +RUN apt-get remove -y gcc perl + +RUN ln -s /usr/lib/x86_64-linux-gnu/libxcb-util.so.0 \ + /usr/lib/x86_64-linux-gnu/libxcb-util.so.1 + +RUN wget ${NOTBIT_DIST_URL} && \ + tar -C /usr/bin -xvf notbit.tar.gz && \ + rm notbit.tar.gz + +# start TC added for Cloudron +RUN mkdir -p /app/data +RUN mkdir -p /app/data/.X-11-unix +RUN mkdir -p /app/data/tmp/runtime-galacteek +RUN mkdir -p /app/data/.local +RUN mkdir -p /app/data/.local/share +RUN mkdir -p /app/data/.local/share/galacteek +RUN mkdir -p /app/data/.local/share/galacteek/main +RUN mkdir -p /app/data/.local/share/galacteek/main/mhashmetadb +RUN useradd -m -u 1000 -d /app/data galacteek +RUN chown -R galacteek /app/data +# end TC + +COPY .docker/x11vnc_cloudron_start.sh / +RUN chmod +x /x11vnc_cloudron_start.sh +USER galacteek +CMD ["/x11vnc_cloudron_start.sh", "galacteek", "--config-ipfs-auto", "-d"] diff --git a/Dockerfile.debian.x11vnc b/Dockerfile.debian.x11vnc index 8ca87e4b..bdfd8a84 100644 --- a/Dockerfile.debian.x11vnc +++ b/Dockerfile.debian.x11vnc @@ -1,7 +1,7 @@ FROM python:3.7-slim-buster EXPOSE 5900-5904 -EXPOSE 5001 +EXPOSE 4001 EXPOSE 8080 ENV NOTBIT_DIST_URL "https://gitlab.com/api/v4/projects/27627112/packages/generic/notbit/0.7/notbit.tar.gz" @@ -15,6 +15,7 @@ ENV QTWEBENGINE_DISABLE_SANDBOX=1 RUN apt-get update && apt-get install -q -y --force-yes \ gcc git net-tools iproute2 \ + libdb5.3-dev libdb-dev libdb5.3 \ file libmagic1 libmagic-mgc \ libgl1-mesa-glx libnss3 libxtst6 libxext6 \ libasound2 libegl1-mesa libpulse-mainloop-glib0 libpulse0 \ @@ -42,12 +43,14 @@ COPY galacteek/ /usr/local/galacteek/galacteek COPY requirements.txt requirements-dev.txt \ requirements-extra-markdown.txt \ + requirements-rdf-bsddb.txt \ requirements-ui-pyqt-5.15.txt \ ./ RUN pip install -U pip wheel && pip install -r requirements.txt && \ pip install -r requirements-dev.txt && \ pip install -r requirements-extra-markdown.txt && \ + pip install -r requirements-rdf-bsddb.txt && \ pip install -r requirements-ui-pyqt-5.15.txt RUN cd /usr/local/galacteek && \ diff --git a/galacteek/dweb/channels/g.py b/galacteek/dweb/channels/g.py index 6cb61a71..c202c2b8 100644 --- a/galacteek/dweb/channels/g.py +++ b/galacteek/dweb/channels/g.py @@ -11,7 +11,7 @@ class GHandler(GAsyncObject): @pyqtSlot(result=int) def apiVersion(self): - return 5 + return 6 @pyqtSlot(str, str) def logMsg(self, level: str, message: str): diff --git a/galacteek/dweb/channels/ipfs.py b/galacteek/dweb/channels/ipfs.py index 0cfbbcfe..f9d2188d 100644 --- a/galacteek/dweb/channels/ipfs.py +++ b/galacteek/dweb/channels/ipfs.py @@ -3,10 +3,12 @@ from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import pyqtProperty from PyQt5.QtCore import QVariant from PyQt5.QtCore import QByteArray from PyQt5.QtCore import QJsonValue from PyQt5.QtCore import QUrl +from PyQt5.QtCore import QObject from galacteek import log from galacteek import ensure @@ -14,6 +16,7 @@ from galacteek.core.ps import KeyListener from galacteek.ipfs.mimetype import detectMimeType +from galacteek.ipfs.cidhelpers import IPFSPath from galacteek.ipfs.pubsub.messages import PubsubMessage from galacteek.ipfs.pubsub.service import JSONPubsubService from galacteek.ipfs.pubsub.service import Curve25519JSONPubsubService @@ -422,3 +425,94 @@ def p2pHttpJsonGet(self, peerId, protocol, path, body): path, self._dict(body) ) + + +class IpfsObjectInterface(QObject): + def __init__(self, parent=None): + super().__init__(parent) + + self._ipfsPath = IPFSPath(None) + + def _getAddress(self): + return str(self._ipfsPath) + + def _setAddress(self, addr: str): + self._ipfsPath = IPFSPath(addr, autoCidConv=True) + + @pyqtSlot(result=str) + def objPath(self): + if self._ipfsPath.valid: + return self._ipfsPath.objPath + + return '' + + @pyqtSlot(result=str) + def fragment(self): + if self._ipfsPath.valid: + return self._ipfsPath.fragment + + return '' + + @pyqtSlot(result=str) + def basename(self): + if self._ipfsPath.valid and self._ipfsPath.basename: + return self._ipfsPath.basename + + return '' + + @pyqtSlot(result=str) + def ipnsId(self): + if self._ipfsPath.valid and self._ipfsPath.ipnsId: + return self._ipfsPath.ipnsId + + return '' + + @pyqtSlot(result=str) + def ipfsUrl(self): + if self._ipfsPath.valid: + return self._ipfsPath.ipfsUrl + + return '' + + @pyqtSlot(result=str) + def dwebUrl(self): + if self._ipfsPath.valid: + return self._ipfsPath.dwebUrl + + return '' + + @pyqtSlot(result=str) + def ipfsUrlEncoded(self): + if self._ipfsPath.valid: + return self._ipfsPath.ipfsUrlEncoded + + return '' + + @pyqtSlot(result=bool) + def valid(self): + return self._ipfsPath.valid + + @pyqtSlot(result=bool) + def isIpfs(self): + return self._ipfsPath.isIpfs + + @pyqtSlot(result=bool) + def isIpns(self): + return self._ipfsPath.isIpns + + @pyqtSlot(result=str) + def rootCid(self): + if self._ipfsPath.valid: + return self._ipfsPath.rootCid + + return '' + + @pyqtSlot(result=str) + def publicGwUrl(self): + if self._ipfsPath.valid: + return self._ipfsPath.publicGwUrl + + return '' + + address = pyqtProperty( + 'QString', _getAddress, _setAddress) diff --git a/galacteek/ui/qmlapp.py b/galacteek/ui/qmlapp.py index 667b333e..46a31daf 100644 --- a/galacteek/ui/qmlapp.py +++ b/galacteek/ui/qmlapp.py @@ -19,6 +19,7 @@ from galacteek.dweb.channels.sparql import SparQLHandler from galacteek.dweb.channels.ipid import IPIDHandler from galacteek.dweb.channels.ipfs import IPFSHandler +from galacteek.dweb.channels.ipfs import IpfsObjectInterface from galacteek.dweb.channels.ontolochain import OntoloChainHandler from galacteek.dweb.channels.graphs import * from galacteek.dweb.channels.unixfs import UnixFsDirModel @@ -153,6 +154,12 @@ def setupEngine(self): 1, 0, 'RDFGraphOperator' ) + qmlRegisterType( + IpfsObjectInterface, + 'Galacteek', + 1, 0, + 'IpfsObject' + ) if 0: qmlRegisterSingletonType(