diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml
new file mode 100644
index 00000000..bbd94e7d
--- /dev/null
+++ b/.github/workflows/docker-image.yml
@@ -0,0 +1,173 @@
+# Inspired by https://github.com/sredevopsorg/multi-arch-docker-github-workflow
+name: Docker Image CI
+
+on:
+ push:
+ tags:
+ - "v[0-9]+.[0-9]+.[0-9]+"
+ workflow_dispatch:
+ inputs:
+ upstream_tag:
+ description: "Upstream tag of nextcloud/notify_push to build"
+ required: false
+
+jobs:
+ build:
+ runs-on: ${{ matrix.runner }}
+
+ permissions:
+ contents: read
+ packages: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - platform: linux/amd64
+ runner: ubuntu-latest
+ - platform: linux/arm64
+ runner: ubuntu-24.04-arm
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ repository: ${{ inputs.upstream_tag && 'nextcloud/notify_push' || github.repository }}
+ ref: ${{ inputs.upstream_tag || github.ref_name }}
+
+ - name: Log in to GitHub Packages
+ uses: docker/login-action@v4
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v4
+
+ - name: Lower case docker image name
+ id: image
+ uses: ASzc/change-string-case-action@v8
+ with:
+ string: ${{ github.repository }}
+
+ - name: Sanitize upstream tag
+ if: inputs.upstream_tag != ''
+ id: tag
+ run: echo "value=${INPUT_TAG#v}" >> $GITHUB_OUTPUT
+ env:
+ INPUT_TAG: ${{ inputs.upstream_tag }}
+
+ - name: Extract metadata
+ id: meta
+ uses: docker/metadata-action@v6
+ with:
+ images: ghcr.io/${{ github.repository }}
+ tags: |
+ type=ref,event=tag
+ type=raw,value=latest
+ type=raw,value=${{ steps.tag.outputs.value }},enable=${{ inputs.upstream_tag != '' }}
+
+ - name: Build and push by digest
+ id: build
+ uses: docker/build-push-action@v7
+ with:
+ context: .
+ platforms: ${{ matrix.platform }}
+ labels: ${{ steps.meta.outputs.labels }}
+ outputs: type=image,name=ghcr.io/${{ steps.image.outputs.lowercase }},push-by-digest=true,name-canonical=true,push=true
+ cache-from: type=gha,scope=${{ matrix.platform }}
+ cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
+
+ - name: Export digest
+ run: |
+ mkdir -p /tmp/digests
+ touch "/tmp/digests/${DIGEST#sha256:}"
+ env:
+ DIGEST: ${{ steps.build.outputs.digest }}
+
+ - name: Upload digest
+ uses: actions/upload-artifact@v7
+ with:
+ name: digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
+ path: /tmp/digests/*
+ if-no-files-found: error
+ retention-days: 1
+
+ merge:
+ runs-on: ubuntu-latest
+ needs: build
+
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Download digests
+ uses: actions/download-artifact@v8
+ with:
+ path: /tmp/digests
+ pattern: digests-*
+ merge-multiple: true
+
+ - name: Log in to GitHub Packages
+ uses: docker/login-action@v4
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v4
+
+ - name: Lower case docker image name
+ id: image
+ uses: ASzc/change-string-case-action@v8
+ with:
+ string: ${{ github.repository }}
+
+ - name: Sanitize upstream tag
+ if: inputs.upstream_tag != ''
+ id: tag
+ run: echo "value=${INPUT_TAG#v}" >> $GITHUB_OUTPUT
+ env:
+ INPUT_TAG: ${{ inputs.upstream_tag }}
+
+ - name: Extract metadata
+ id: meta
+ uses: docker/metadata-action@v6
+ with:
+ images: ghcr.io/${{ github.repository }}
+ tags: |
+ type=ref,event=tag
+ type=raw,value=latest
+ type=raw,value=${{ steps.tag.outputs.value }},enable=${{ inputs.upstream_tag != '' }}
+
+ - name: Get timestamp
+ id: timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+
+ - name: Create and push manifest
+ id: manifest
+ working-directory: /tmp/digests
+ continue-on-error: true
+ run: |
+ docker buildx imagetools create \
+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
+ --annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
+ --annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
+ --annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
+ --annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
+ $(printf 'ghcr.io/${{ steps.image.outputs.lowercase }}@sha256:%s ' *)
+
+ - name: Create and push manifest (without annotations)
+ if: steps.manifest.outcome == 'failure'
+ working-directory: /tmp/digests
+ run: |
+ docker buildx imagetools create \
+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
+ $(printf 'ghcr.io/${{ steps.image.outputs.lowercase }}@sha256:%s ' *)
+
+ - name: Inspect manifest
+ run: |
+ docker buildx imagetools inspect 'ghcr.io/${{ steps.image.outputs.lowercase }}:${{ steps.meta.outputs.version }}'
diff --git a/Cargo.lock b/Cargo.lock
index dc4b756c..7c3c02a4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1629,9 +1629,9 @@ dependencies = [
[[package]]
name = "nextcloud-config-parser"
-version = "0.15.2"
+version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a285761c91b18426c4cadf66ffb77f8881ea5cb417d94bad384bcf85a9965de"
+checksum = "0ea4ec27a2e48f55995d7725a6ed8947630348e01803061a8b704ae3a96987d3"
dependencies = [
"form_urlencoded",
"indexmap",
@@ -3876,7 +3876,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
- "windows-sys 0.61.2",
+ "windows-sys 0.48.0",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 26a56a78..da387087 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,7 +29,7 @@ rand = { version = "0.8.5", features = ["small_rng"] }
ahash = "0.8.12"
flexi_logger = { version = "0.31.8", features = ["colors"] }
tokio-stream = { version = "0.1.17", features = ["net"] }
-nextcloud-config-parser = "0.15.1"
+nextcloud-config-parser = "0.15.2"
url = "2.5.4"
clap = { version = "4.5.43", features = ["derive"] }
sd-notify = { version = "0.5.0", optional = true }
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 0f63140e..3daa82b6 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -11,7 +11,7 @@
- 1.3.1
+ 1.3.3
agpl
Robin Appelman
NotifyPush
@@ -27,7 +27,7 @@ Once the app is installed, the push binary needs to be setup. You can either use
https://github.com/nextcloud/notify_push/issues
-
+
diff --git a/flake.nix b/flake.nix
index fb776f23..b4775e5a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -27,7 +27,7 @@
};
lib = pkgs.lib;
- hostTarget = pkgs.hostPlatform.config;
+ hostTarget = pkgs.stdenv.hostPlatform.config;
targets = [
"x86_64-unknown-linux-musl"
"i686-unknown-linux-musl"
diff --git a/lib/Listener.php b/lib/Listener.php
index a5526ae7..97b13eec 100644
--- a/lib/Listener.php
+++ b/lib/Listener.php
@@ -22,6 +22,7 @@
use OCP\Notification\IDismissableNotifier;
use OCP\Notification\INotification;
use OCP\Notification\INotifier;
+use OCP\Notification\UnknownNotificationException;
use OCP\Share\Events\ShareCreatedEvent;
use OCP\Share\IShare;
@@ -102,7 +103,7 @@ public function getName(): string {
}
public function prepare(INotification $notification, string $languageCode): INotification {
- throw new \InvalidArgumentException();
+ throw new UnknownNotificationException();
}
public function dismissNotification(INotification $notification): void {
diff --git a/psalm.xml b/psalm.xml
index 55758e1b..7a444190 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -8,7 +8,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config https://getpsalm.org/schema/config"
- phpVersion="8.0"
+ phpVersion="8.1"
>
diff --git a/src/config.rs b/src/config.rs
index 1c0f2ec4..965b7dd1 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -20,7 +20,7 @@ use sqlx::any::AnyConnectOptions;
use std::convert::{TryFrom, TryInto};
use std::env::var;
use std::fmt::{Debug, Display, Formatter};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+use std::net::{IpAddr, Ipv6Addr, SocketAddr};
use std::path::{Path, PathBuf};
use std::str::FromStr;
@@ -183,9 +183,7 @@ impl TryFrom for Config {
let bind = match config.socket {
Some(socket) => Bind::Unix(socket, socket_permissions),
None => {
- let ip = config
- .bind
- .unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)));
+ let ip = config.bind.unwrap_or(IpAddr::V6(Ipv6Addr::UNSPECIFIED));
let port = config.port.unwrap_or(7867);
Bind::Tcp((ip, port).into())
}
@@ -194,9 +192,7 @@ impl TryFrom for Config {
let metrics_bind = match (config.metrics_socket, config.metrics_port) {
(Some(socket), _) => Some(Bind::Unix(socket, socket_permissions)),
(None, Some(port)) => {
- let ip = config
- .bind
- .unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)));
+ let ip = config.bind.unwrap_or(IpAddr::V6(Ipv6Addr::UNSPECIFIED));
Some(Bind::Tcp((ip, port).into()))
}
_ => None,
diff --git a/src/connection.rs b/src/connection.rs
index e4cf55ae..2d458e94 100644
--- a/src/connection.rs
+++ b/src/connection.rs
@@ -226,6 +226,7 @@ pub async fn handle_user_socket(
// hack while warp only has opaque error types
match formatted.as_str() {
"WebSocket protocol error: Connection reset without closing handshake"
+ | "Broken pipe (os error 32)"
| "IO error: Connection reset by peer (os error 104)" => {
log::debug!("websocket error: {e:#}")
}
@@ -262,11 +263,13 @@ async fn socket_auth(
let username_msg = read_socket_auth_message(rx).await?;
let username = username_msg
.to_str()
- .map_err(|_| AuthenticationError::InvalidMessage)?;
+ .map_err(|_| AuthenticationError::InvalidMessage)?
+ .trim();
let password_msg = read_socket_auth_message(rx).await?;
let password = password_msg
.to_str()
- .map_err(|_| AuthenticationError::InvalidMessage)?;
+ .map_err(|_| AuthenticationError::InvalidMessage)?
+ .trim();
// cleanup all pre_auth tokens older than 15s
let cutoff = Instant::now() - Duration::from_secs(15);