diff --git a/rootfs/standard/usr/share/mynode_apps/canary/app_data/docker-compose.yml b/rootfs/standard/usr/share/mynode_apps/canary/app_data/docker-compose.yml index ecc3644c..dcede9f5 100644 --- a/rootfs/standard/usr/share/mynode_apps/canary/app_data/docker-compose.yml +++ b/rootfs/standard/usr/share/mynode_apps/canary/app_data/docker-compose.yml @@ -8,6 +8,8 @@ services: stop_grace_period: 30s volumes: - /mnt/hdd/mynode/canary:/app/data + env_file: + - /mnt/hdd/mynode/canary/canary.env environment: CANARY_DATA_DIR: /app/data CANARY_ELECTRUM_URL: tcp://127.0.0.1:50001 @@ -24,4 +26,4 @@ services: - backend environment: API_URL: http://127.0.0.1:3004 - PORT: "3005" \ No newline at end of file + PORT: "3005" diff --git a/rootfs/standard/usr/share/mynode_apps/canary/canary.json b/rootfs/standard/usr/share/mynode_apps/canary/canary.json index e8cde289..4dff85bb 100644 --- a/rootfs/standard/usr/share/mynode_apps/canary/canary.json +++ b/rootfs/standard/usr/share/mynode_apps/canary/canary.json @@ -16,7 +16,7 @@ "Get instant notifications when your bitcoins move via ntfy push notifications.", "Features include: transaction monitoring, RBF/CPFP detection, balance alerts, and deep wallet scanning." ], - "latest_version": "v1.4.0", + "latest_version": "v1.5.0", "supported_archs": ["amd64", "arm64"], "download_skip": true, "requires_docker_image_installation": true, @@ -29,6 +29,8 @@ "app_tile_name": "Canary", "app_tile_running_status_text": "Monitoring", "app_tile_default_status_text": "Wallet Monitor", + "app_tile_button_text": "Open", + "app_tile_button_href": "/app/canary/info", "app_tile_button_open_app_directly": true, "can_uninstall": true, "can_reinstall": true, diff --git a/rootfs/standard/usr/share/mynode_apps/canary/scripts/install_canary.sh b/rootfs/standard/usr/share/mynode_apps/canary/scripts/install_canary.sh index 10a0d986..35c6f01b 100755 --- a/rootfs/standard/usr/share/mynode_apps/canary/scripts/install_canary.sh +++ b/rootfs/standard/usr/share/mynode_apps/canary/scripts/install_canary.sh @@ -9,11 +9,50 @@ set -e echo "==================== INSTALLING APP ====================" +APP_DIR="/opt/mynode/canary" +VERSION="${VERSION:-v1.5.0}" +VERSION_FILE="/mnt/hdd/mynode/settings/canary_version" + +write_compose_file() { + cat > "$APP_DIR/docker-compose.yml" </dev/null || true remove_docker_images_by_name "canary-backend" @@ -25,6 +64,10 @@ docker pull schjonhaug/canary-frontend:$VERSION docker tag schjonhaug/canary-backend:$VERSION canary-backend:latest docker tag schjonhaug/canary-frontend:$VERSION canary-frontend:latest +echo "$VERSION" > "$VERSION_FILE" +chown bitcoin:bitcoin "$VERSION_FILE" +touch /tmp/need_application_refresh + chown -R bitcoin:bitcoin /mnt/hdd/mynode/canary echo "================== DONE INSTALLING APP =================" diff --git a/rootfs/standard/usr/share/mynode_apps/canary/scripts/pre_canary.sh b/rootfs/standard/usr/share/mynode_apps/canary/scripts/pre_canary.sh index 69b10ac0..fc233dd0 100755 --- a/rootfs/standard/usr/share/mynode_apps/canary/scripts/pre_canary.sh +++ b/rootfs/standard/usr/share/mynode_apps/canary/scripts/pre_canary.sh @@ -2,9 +2,71 @@ set -e -# Keep the compose file in sync with the packaged app data. -cp -f app_data/docker-compose.yml docker-compose.yml +APP_DIR="/opt/mynode/canary" +DATA_DIR="/mnt/hdd/mynode/canary" +VERSION_FILE="/mnt/hdd/mynode/settings/canary_version" +VERSION="${VERSION:-$(cat "$VERSION_FILE" 2>/dev/null || echo v1.5.0)}" +ADMIN_PASSWORD_FILE="$DATA_DIR/admin_password" +JWT_SECRET_FILE="$DATA_DIR/jwt_secret" +ENV_FILE="$DATA_DIR/canary.env" + +write_compose_file() { + mkdir -p "$APP_DIR" + cat > "$APP_DIR/docker-compose.yml" < "$ADMIN_PASSWORD_FILE" +fi + +if [ ! -s "$JWT_SECRET_FILE" ]; then + generate_secret 64 > "$JWT_SECRET_FILE" +fi + +cat > "$ENV_FILE" </dev/null || true +APP_DIR="/opt/mynode/canary" +VERSION_FILE="/mnt/hdd/mynode/settings/canary_version" + +remove_canary_images() { + docker images --format '{{.Repository}}:{{.Tag}}' \ + | grep -E '^(canary-backend|canary-frontend|schjonhaug/canary-backend|schjonhaug/canary-frontend):' \ + | xargs -r docker rmi 2>/dev/null || true +} + +cp -f "$APP_DIR/app_data/docker-compose.yml" "$APP_DIR/docker-compose.yml" 2>/dev/null || true +cd "$APP_DIR" 2>/dev/null || true /usr/local/bin/docker-compose down --remove-orphans 2>/dev/null || true -remove_docker_images_by_name "canary-backend" -remove_docker_images_by_name "canary-frontend" +remove_canary_images +rm -f "$VERSION_FILE" rm -rf /mnt/hdd/mynode/canary +touch /tmp/need_application_refresh echo "================== DONE UNINSTALLING APP =================" diff --git a/rootfs/standard/usr/share/mynode_apps/canary/www/python/canary.py b/rootfs/standard/usr/share/mynode_apps/canary/www/python/canary.py index 1ef25df5..0954cae2 100644 --- a/rootfs/standard/usr/share/mynode_apps/canary/www/python/canary.py +++ b/rootfs/standard/usr/share/mynode_apps/canary/www/python/canary.py @@ -2,16 +2,38 @@ from user_management import check_logged_in from application_info import get_application, get_application_status, get_application_status_color from device_info import read_ui_settings +import os mynode_canary = Blueprint("mynode_canary", __name__) +CANARY_PASSWORD_FILE = "/mnt/hdd/mynode/canary/admin_password" +CANARY_VERSION_FILE = "/mnt/hdd/mynode/settings/canary_version" + + +def get_canary_password(): + if not os.path.isfile(CANARY_PASSWORD_FILE): + return "" + with open(CANARY_PASSWORD_FILE, "r") as password_file: + return password_file.read().strip() + + +def get_canary_current_version(): + if not os.path.isfile(CANARY_VERSION_FILE): + return None + with open(CANARY_VERSION_FILE, "r") as version_file: + return version_file.read().strip()[0:16] + @mynode_canary.route("/info") def canary_page(): check_logged_in() app = get_application("canary") + current_version = get_canary_current_version() + if current_version: + app["current_version"] = current_version + app_status = get_application_status("canary") app_status_color = get_application_status_color("canary") @@ -21,5 +43,7 @@ def canary_page(): "app_status": app_status, "app_status_color": app_status_color, "app": app, + "canary_username": "admin@local", + "canary_password": get_canary_password(), } - return render_template("/app/generic_app.html", **template_data) + return render_template("/app/canary/canary.html", **template_data) diff --git a/rootfs/standard/usr/share/mynode_apps/canary/www/templates/canary.html b/rootfs/standard/usr/share/mynode_apps/canary/www/templates/canary.html new file mode 100644 index 00000000..1725053f --- /dev/null +++ b/rootfs/standard/usr/share/mynode_apps/canary/www/templates/canary.html @@ -0,0 +1,210 @@ + + + {{app.name}} + {% include 'includes/head.html' %} + + + + + + + + + {% include 'includes/logo_header.html' %} +
+ +
+ +
{{app.name}}
+
+ +
+
 
+
+ +
+ + {% if not app.hide_status_icon %} +
+ {% endif %} +

{{app_status}}

+ +
+ + {% if not app.is_installed %} + + {% else %} + + {% if app.is_enabled and app.app_page_show_open_button %} + {% if app.http_port != "" or app.https_port != "" %} + + +
+ {% endif %} + {% endif %} + + {% if app.is_enabled %} + + + {% if app.is_enabled and app.data_manageable %} + + {% endif %} + + {% for btn in app.app_page_additional_buttons %} + + {% endfor %} + +
+ {% endif %} + + {% if app.can_enable_disable %} + {% if not app.is_enabled %} + + {% else %} + + {% endif %} + {% endif %} + {% endif %} + +
+ +
+
+
Info
+
+
+ + + + + + {% if app.author.name is defined %} + + + + + {% endif %} + {% if app.website.name is defined and app.website.link is defined %} + + + + + {% endif %} +
Installed Version + {% if app.is_installed %} + {{app.current_version}} + {% else %} + Not Installed + {% endif %} +
Author + {% if app.author.link is defined and app.author.link != "" %} + {{app.author.name}} + {% else %} + {{app.author.name}} + {% endif %} +
Website + {{app.website.name}} +
+
+ +
+
Credentials
+
+
+ + + + + + + + + +
Username{{canary_username}}
Password + {% if canary_password %} + + + show password + {% else %} + Not generated yet + {% endif %} +
+
+ + {% if app.app_page_content is defined and app.app_page_content|length > 0 %} + {% for section in app.app_page_content %} +
+
{{section.heading}}
+
+
+ {% for parapraph in section.content %} +

{{parapraph}}

+ {% endfor %} +
+ {% endfor %} + {% endif %} + +
+ +
+
+ +
+ + + + {% include 'includes/footer.html' %} + +