Compare commits

..

16 Commits

Author SHA1 Message Date
cpu
2da6061795 flow diagrams 2025-03-31 22:32:26 +02:00
cpu
c89eaacd42 auth 2025-03-26 23:57:03 +01:00
cpu
682dc6942a added subscription route 2025-03-26 20:31:31 +01:00
cpu
064f803784 Merge branch 'one_line_key' 2025-03-26 19:22:19 +01:00
cpu
9b4bf1e255 flask and node.js solution 2025-03-26 19:12:43 +01:00
cpu
fc7f4f4b7a rewritten 2025-03-26 09:36:58 +01:00
cpu
b87e30f6b4 fix 2025-03-26 09:25:28 +01:00
cpu
faa32510df again validations 2025-03-26 08:59:03 +01:00
cpu
ce7ab594e2 improved validations 2025-03-26 08:52:30 +01:00
cpu
f500c00896 logs 2025-03-26 08:34:51 +01:00
cpu
b246923283 clean up 2025-03-26 08:21:33 +01:00
cpu
907ad382dc helper prints 2025-03-26 08:16:56 +01:00
cpu
102d2e2748 fixed key to one line 2025-03-26 06:38:33 +01:00
cpu
f2de1e55d0 CORS 2025-03-26 05:33:53 +01:00
cpu
ba9704d3c2 config 2025-03-26 03:57:54 +01:00
cpu
95a5b893ec first version 2025-03-26 03:09:49 +01:00
2 changed files with 38 additions and 68 deletions

39
.env
View File

@@ -1,39 +0,0 @@
# Flic to PWA WebPush Configuration
# --- VAPID Keys (Required) ---
# Generate using: npx web-push generate-vapid-keys
VAPID_PUBLIC_KEY=BKfRJXjSQmAJ452gLwlK_8scGrW6qMU1mBRp39ONtcQHkSsQgmLAaODIyGbgHyRpnDEv3HfXV1oGh3SC0fHxY0E
VAPID_PRIVATE_KEY=ErEgsDKYQi5j2KPERC_gCtrEALAD0k-dWSwrrcD0-JU
VAPID_SUBJECT=mailto:admin@virtonline.eu
# --- Server Configuration ---
# Internal port for the Node.js app
PORT=3000
SUBSCRIPTIONS_FILE=subscriptions.json
DEFAULT_BUTTON_NAME=game-button
# --- Authentication (Optional) ---
# If both USERNAME and PASSWORD are set, Basic Auth will be enabled for:
# - POST /subscribe
# - GET /webhook
# Leave blank to disable authentication.
BASIC_AUTH_USERNAME=player
BASIC_AUTH_PASSWORD=SevenOfNine
# --- Web Push Retry Configuration (Optional) ---
# Number of retries on failure (e.g., DNS issues)
NOTIFICATION_MAX_RETRIES=3
# First retry delay in milliseconds (minimal delay for immediate retry)
NOTIFICATION_FIRST_RETRY_DELAY_MS=10
# Base delay in milliseconds for subsequent retries (used for exponential backoff)
NOTIFICATION_SUBSEQUENT_RETRY_DELAY_MS=1000
# --- Network Configuration (Optional) ---
# Timeout for DNS lookups (ms)
DNS_TIMEOUT_MS=5000
# Timeout for outgoing HTTP requests (ms)
HTTP_TIMEOUT_MS=10000
# --- Logging ---
# Controls log verbosity: error, warn, info, debug
LOG_LEVEL=info

View File

@@ -51,31 +51,31 @@ It's designed to be run as a Docker container and integrated with Traefik v3 for
This will output a Public Key and a Private Key. This will output a Public Key and a Private Key.
3. **Configure Environment Variables:** 3. **Configure Environment Variables:**
* Copy the example `.env` file: * Copy the example `.env` file:
```bash ```bash
cp .env.example .env cp .env.example .env
``` ```
* Edit the `.env` file with your specific values: * Edit the `.env` file with your specific values:
* `VAPID_PUBLIC_KEY`: The public key generated in step 2. **Your PWA will also need this key** when it subscribes to push notifications. * `VAPID_PUBLIC_KEY`: The public key generated in step 2. **Your PWA will also need this key** when it subscribes to push notifications.
* `VAPID_PRIVATE_KEY`: The private key generated in step 2. **Keep this secret!** * `VAPID_PRIVATE_KEY`: The private key generated in step 2. **Keep this secret!**
* `VAPID_SUBJECT`: A `mailto:` or `https:` URL identifying you or your application (e.g., `mailto:admin@yourdomain.com`). Used by push services to contact you. * `VAPID_SUBJECT`: A `mailto:` or `https:` URL identifying you or your application (e.g., `mailto:admin@yourdomain.com`). Used by push services to contact you.
* `PORT`: (Default: `3000`) The internal port the Node.js app listens on. Traefik will map to this. * `PORT`: (Default: `3000`) The internal port the Node.js app listens on. Traefik will map to this.
* `SUBSCRIPTIONS_FILE`: (Default: `subscriptions.json`) The path *inside the container* where the button-to-subscription mapping is stored. * `SUBSCRIPTIONS_FILE`: (Default: `subscriptions.json`) The path *inside the container* where the button-to-subscription mapping is stored.
* `DEFAULT_BUTTON_NAME`: (Default: `game-button`) The default button name to use when the `Button-Name` header is not provided in the webhook request. * `DEFAULT_BUTTON_NAME`: (Default: `game-button`) The default button name to use when the `Button-Name` header is not provided in the webhook request.
* `BASIC_AUTH_USERNAME`: (Optional) Username for Basic Authentication. If set along with `BASIC_AUTH_PASSWORD`, authentication will be enabled for `/webhook` and `/subscribe`. * `BASIC_AUTH_USERNAME`: (Optional) Username for Basic Authentication. If set along with `BASIC_AUTH_PASSWORD`, authentication will be enabled for `/webhook` and `/subscribe`.
* `BASIC_AUTH_PASSWORD`: (Optional) Password for Basic Authentication. If set along with `BASIC_AUTH_USERNAME`, authentication will be enabled. * `BASIC_AUTH_PASSWORD`: (Optional) Password for Basic Authentication. If set along with `BASIC_AUTH_USERNAME`, authentication will be enabled.
* `NOTIFICATION_MAX_RETRIES`: (Default: `3`) Number of retry attempts for failed push notifications. Must be a number. * `NOTIFICATION_MAX_RETRIES`: (Default: `3`) Number of retry attempts for failed push notifications. Must be a number.
* `NOTIFICATION_FIRST_RETRY_DELAY_MS`: (Default: `10`) Delay in milliseconds for the first retry attempt. Setting to 0-10ms provides near-immediate first retry for transient DNS issues. Must be a number. * `NOTIFICATION_FIRST_RETRY_DELAY_MS`: (Default: `10`) Delay in milliseconds for the first retry attempt. Setting to 0-10ms provides near-immediate first retry for transient DNS issues. Must be a number.
* `NOTIFICATION_SUBSEQUENT_RETRY_DELAY_MS`: (Default: `1000`) Base delay in milliseconds for subsequent retries. Each additional retry uses this value with exponential backoff and jitter. Must be a number. * `NOTIFICATION_SUBSEQUENT_RETRY_DELAY_MS`: (Default: `1000`) Base delay in milliseconds for subsequent retries. Each additional retry uses this value with exponential backoff and jitter. Must be a number.
* `DNS_TIMEOUT_MS`: (Default: `5000`) DNS resolution timeout in milliseconds. Must be a number. * `DNS_TIMEOUT_MS`: (Default: `5000`) DNS resolution timeout in milliseconds. Must be a number.
* `HTTP_TIMEOUT_MS`: (Default: `10000`) HTTP request timeout in milliseconds. Must be a number. * `HTTP_TIMEOUT_MS`: (Default: `10000`) HTTP request timeout in milliseconds. Must be a number.
* `LOG_LEVEL`: (Default: `info`) Controls verbosity of logs. Valid values are `error`, `warn`, `info`, or `debug`. Use `debug` to see detailed header information and other diagnostic messages. * `LOG_LEVEL`: (Default: `info`) Controls verbosity of logs. Valid values are `error`, `warn`, `info`, or `debug`. Use `debug` to see detailed header information and other diagnostic messages.
4. **Configure Traefik Labels:** 4. **Configure Traefik Labels:**
* Copy the example `labels` file: * Copy the example `labels` file:
```bash ```bash
cp labels.example labels cp labels.example labels
``` ```
## Running the Service ## Running the Service
@@ -114,11 +114,11 @@ In your Flic app or Flic Hub SDK interface:
2. Add an "Internet Request" action. 2. Add an "Internet Request" action.
3. Fill in the following details: 3. Fill in the following details:
* Select the `GET` method. * Select the `GET` method.
* Set URL with query parameter: `https://webpush.virtonline.eu/webhook/SingleClick` * Set URL with query parameter: `https://<your_domain>/webhook/SingleClick` (Replace `<your_domain>` with your actual service domain, e.g., `webpush.virtonline.eu`).
* **If Basic Authentication is enabled:** * **If Basic Authentication is enabled:**
* Set the Headers: * Set the Headers:
* Set the `Key` fields to `Authorization`. * Set the `Key` fields to `Authorization`.
* Set the `Value` fields to `Basic <base64 encoded username:password>` (e.g., `Basic dXNlcm5hbWU6cGFzc3dvcmQ=`). Use `$(echo -n 'user:password' | base64)` to generate the base64 encoded string. * Set the `Value` fields to `Basic <base64 encoded username:password>`.
* Click `ADD`. * Click `ADD`.
* Tap on `SAVE ACTION`. * Tap on `SAVE ACTION`.
4. Repeat for Double Click (i.e., `/DoubleClick`) and Hold (i.e., `/Hold`) events. 4. Repeat for Double Click (i.e., `/DoubleClick`) and Hold (i.e., `/Hold`) events.
@@ -160,7 +160,7 @@ Search the Play Store - there might be others with similar names.
* `subscription` (object, required): The [PushSubscription object](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription) obtained from the browser's Push API. * `subscription` (object, required): The [PushSubscription object](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription) obtained from the browser's Push API.
```json ```json
{ {
"button_id": "game-button", "button_id": "game-button", // Optional, defaults to DEFAULT_BUTTON_NAME environment variable
"subscription": { "subscription": {
"endpoint": "https://your_pwa_push_endpoint...", "endpoint": "https://your_pwa_push_endpoint...",
"expirationTime": null, "expirationTime": null,
@@ -182,10 +182,19 @@ Search the Play Store - there might be others with similar names.
* **Authentication:** Optional Basic Authentication via `Authorization` header if `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` are configured. * **Authentication:** Optional Basic Authentication via `Authorization` header if `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` are configured.
* **URL Parameters:** * **URL Parameters:**
* `click_type` (required): The type of button press (e.g., `SingleClick`, `DoubleClick`, or `Hold`). * `click_type` (required): The type of button press (e.g., `SingleClick`, `DoubleClick`, or `Hold`).
* **Optional Headers:** * **Required Headers:**
* `Button-Name`: The identifier of the Flic button (sent by the Flic system). If not provided, the value of `DEFAULT_BUTTON_NAME` environment variable will be used as a fallback. * `Button-Name`: The identifier of the Flic button (sent by the Flic system). If not provided, the value of `DEFAULT_BUTTON_NAME` environment variable will be used as a fallback.
* **Optional Headers:**
* `Timestamp`: Timestamp of the button event (sent by the Flic system). * `Timestamp`: Timestamp of the button event (sent by the Flic system).
* `Button-Battery-Level`: The battery level percentage of the button (sent by the Flic system). * `Button-Battery-Level`: The battery level percentage of the button (sent by the Flic system).
* **Push Notification Payload (`data` field):** The service sends a JSON payload within the push notification. The client-side Service Worker can access this data via `event.data.json()`. The structure is:
```bash
curl -X GET https://webpush.virtonline.eu/webhook/SingleClick \
-H 'Authorization: Basic cGxheWVyOlNldmVuT2ZOaW5l' \
-H "Button-Name: Game-button" \
-H "Timestamp: 2025-03-26T01:10:20Z" \
-H "Button-Battery-Level: 100"
```
* **Responses:** * **Responses:**
* `200 OK`: Webhook received, push notification sent successfully. * `200 OK`: Webhook received, push notification sent successfully.
* `400 Bad Request`: Missing `Button-Name` header or `click_type` URL parameter. * `400 Bad Request`: Missing `Button-Name` header or `click_type` URL parameter.
@@ -223,7 +232,7 @@ If you receive a different response, refer to the Troubleshooting section below.
## Troubleshooting ## Troubleshooting
* **Check Backend Logs:** `docker logs flic-webhook-webpush`. Look for errors related to configuration, file access, JSON parsing, authentication, or sending push notifications. * **Check Backend Logs:** `docker logs flic-webhook-webpush`. Look for errors related to configuration, file access, JSON parsing, authentication, or sending push notifications.
* To see detailed debug information including all headers received from the Flic button, set `LOG_LEVEL=debug` in your .env file. * To see detailed debug information including all headers received from the Flic button, set `LOG_LEVEL=debug` in your .env file.
* **Check Traefik Logs:** `docker logs traefik`. Look for routing errors or certificate issues. * **Check Traefik Logs:** `docker logs traefik`. Look for routing errors or certificate issues.
* **Verify `.env`:** Ensure all required variables are set correctly, especially VAPID keys and Traefik settings. * **Verify `.env`:** Ensure all required variables are set correctly, especially VAPID keys and Traefik settings.
* **Verify `labels`:** Double-check that variables were correctly substituted manually and match your `.env` and Traefik setup. * **Verify `labels`:** Double-check that variables were correctly substituted manually and match your `.env` and Traefik setup.