Minor changes
parent
30a8f66db2
commit
020996ea04
|
@ -789,7 +789,7 @@ Note that the self-hosted server literally sends the message `New message` for e
|
|||
may be `Some other message`. This is so that if iOS cannot talk to the self-hosted server (in time, or at all),
|
||||
it'll show `New message` as a popup.
|
||||
|
||||
## Web Push notifications
|
||||
## Web Push
|
||||
[Web Push](https://developer.mozilla.org/en-US/docs/Web/API/Push_API) ([RFC8030](https://datatracker.ietf.org/doc/html/rfc8030))
|
||||
allows ntfy to receive push notifications, even when the ntfy web app (or even the browser, depending on the platform) is closed.
|
||||
When enabled, the user can enable **background notifications** for their topics in the wep app under Settings. Once enabled by the
|
||||
|
@ -817,6 +817,7 @@ To configure VAPID keys, first generate them:
|
|||
```sh
|
||||
$ ntfy webpush keys
|
||||
Web Push keys generated.
|
||||
...
|
||||
```
|
||||
|
||||
Then copy the generated values into your `server.yml` or use the corresponding environment variables or command line arguments:
|
||||
|
@ -828,8 +829,9 @@ web-push-subscriptions-file: /var/cache/ntfy/webpush.db
|
|||
web-push-email-address: sysadmin@example.com
|
||||
```
|
||||
|
||||
The `web-push-subscriptions-file` is used to store the push subscriptions. Subscriptions do not ever expire automatically, unless the push
|
||||
gateway returns an error (e.g. 410 Gone when a user has unsubscribed).
|
||||
The `web-push-subscriptions-file` is used to store the push subscriptions. Unused subscriptions will send out a warning after 7 days,
|
||||
and will automatically expire after 9 days (not configurable). If the gateway returns an error (e.g. 410 Gone when a user has unsubscribed),
|
||||
subscriptions are also removed automatically.
|
||||
|
||||
The web app refreshes subscriptions on start and regularly on an interval, but this file should be persisted across restarts. If the subscription
|
||||
file is deleted or lost, any web apps that aren't open will not receive new web push notifications until you open then.
|
||||
|
@ -1333,8 +1335,8 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
|
|||
| `stripe-secret-key` | `NTFY_STRIPE_SECRET_KEY` | *string* | - | Payments: Key used for the Stripe API communication, this enables payments |
|
||||
| `stripe-webhook-key` | `NTFY_STRIPE_WEBHOOK_KEY` | *string* | - | Payments: Key required to validate the authenticity of incoming webhooks from Stripe |
|
||||
| `billing-contact` | `NTFY_BILLING_CONTACT` | *email address* or *website* | - | Payments: Email or website displayed in Upgrade dialog as a billing contact |
|
||||
| `web-push-public-key` | `NTFY_WEB_PUSH_PUBLIC_KEY` | *string* | - | Web Push: Public Key. Run `ntfy webpush generate-keys` to generate |
|
||||
| `web-push-private-key` | `NTFY_WEB_PUSH_PRIVATE_KEY` | *string* | - | Web Push: Private Key. Run `ntfy webpush generate-keys` to generate |
|
||||
| `web-push-public-key` | `NTFY_WEB_PUSH_PUBLIC_KEY` | *string* | - | Web Push: Public Key. Run `ntfy webpush keys` to generate |
|
||||
| `web-push-private-key` | `NTFY_WEB_PUSH_PRIVATE_KEY` | *string* | - | Web Push: Private Key. Run `ntfy webpush keys` to generate |
|
||||
| `web-push-subscriptions-file` | `NTFY_WEB_PUSH_SUBSCRIPTIONS_FILE` | *string* | - | Web Push: Subscriptions file |
|
||||
| `web-push-email-address` | `NTFY_WEB_PUSH_EMAIL_ADDRESS` | *string* | - | Web Push: Sender email address |
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
# Using the web app as an installed web app
|
||||
|
||||
While ntfy doesn't have a native desktop app, it is built as a [progressive web app](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps) (PWA)
|
||||
and thus can be installed on both desktop and mobile. This gives it its own launcher (e.g. shortcut on Windows, app on
|
||||
macOS, launcher shortcut on Linux) own window, push notifications, and an app badge with the unread notification count.
|
||||
and thus can be installed on both desktop and mobile devices. This gives it its own launcher (e.g. shortcut on Windows, app on
|
||||
macOS, launcher shortcut on Linux), own window, push notifications, and an app badge with the unread notification count.
|
||||
|
||||
To install and register the web app in your operating system, click the "install app" icon in your browser (usually next to the
|
||||
address bar). To receive background notifications, **either the browser or the installed web app must be open**.
|
||||
|
|
|
@ -146,8 +146,8 @@
|
|||
|
||||
# Web Push support (background notifications for browsers)
|
||||
#
|
||||
# If enabled, allows ntfy to receive push notifications, even when the ntfy web app is closed. When enabled, the user
|
||||
# can enable background notifications. Once enabled by the user, ntfy will forward published messages to the push
|
||||
# If enabled, allows ntfy to receive push notifications, even when the ntfy web app is closed. When enabled, users
|
||||
# can enable background notifications in the web app. Once enabled, ntfy will forward published messages to the push
|
||||
# endpoint, which will then forward it to the browser.
|
||||
#
|
||||
# You must configure all settings below to enable Web Push.
|
||||
|
|
|
@ -431,6 +431,41 @@ func TestAccount_Delete_Not_Allowed(t *testing.T) {
|
|||
require.Equal(t, 40026, toHTTPError(t, rr.Body.String()).Code)
|
||||
}
|
||||
|
||||
func TestAccount_Delete_Success_WithWebPush(t *testing.T) {
|
||||
conf := configureAuth(t, newTestConfigWithWebPush(t))
|
||||
conf.EnableSignup = true
|
||||
s := newTestServer(t, conf)
|
||||
|
||||
// Add account
|
||||
rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
|
||||
require.Equal(t, 200, rr.Code)
|
||||
|
||||
// Add web push subscription
|
||||
rr = request(t, s, "POST", "/v1/webpush", payloadForTopics(t, []string{"mytopic"}, testWebPushEndpoint), map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "mypass"),
|
||||
})
|
||||
require.Equal(t, 200, rr.Code)
|
||||
|
||||
u, err := s.userManager.User("phil")
|
||||
require.Nil(t, err)
|
||||
|
||||
subs, err := s.webPush.SubscriptionsForTopic("mytopic")
|
||||
require.Nil(t, err)
|
||||
require.Len(t, subs, 1)
|
||||
require.Equal(t, u.ID, subs[0].UserID)
|
||||
|
||||
// Delete account
|
||||
rr = request(t, s, "DELETE", "/v1/account", `{"password":"mypass"}`, map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "mypass"),
|
||||
})
|
||||
require.Equal(t, 200, rr.Code)
|
||||
|
||||
// Make sure web push subscription was deleted
|
||||
subs, err = s.webPush.SubscriptionsForTopic("mytopic")
|
||||
require.Nil(t, err)
|
||||
require.Len(t, subs, 0)
|
||||
}
|
||||
|
||||
func TestAccount_Reservation_AddWithoutTierFails(t *testing.T) {
|
||||
conf := newTestConfigWithAuthFile(t)
|
||||
conf.EnableSignup = true
|
||||
|
|
|
@ -120,7 +120,6 @@ func (s *Server) pruneAndNotifyWebPushSubscriptionsInternal() error {
|
|||
}
|
||||
payload, err := json.Marshal(newWebPushSubscriptionExpiringPayload())
|
||||
if err != nil {
|
||||
log.Tag(tagWebPush).Err(err).Warn("Unable to marshal expiring payload")
|
||||
return err
|
||||
}
|
||||
warningSent := make([]*webPushSubscription, 0)
|
||||
|
@ -140,7 +139,14 @@ func (s *Server) pruneAndNotifyWebPushSubscriptionsInternal() error {
|
|||
|
||||
func (s *Server) sendWebPushNotification(sub *webPushSubscription, message []byte, contexters ...log.Contexter) error {
|
||||
log.Tag(tagWebPush).With(sub).With(contexters...).Debug("Sending web push message")
|
||||
resp, err := webpush.SendNotification(message, sub.ToSubscription(), &webpush.Options{
|
||||
payload := &webpush.Subscription{
|
||||
Endpoint: sub.Endpoint,
|
||||
Keys: webpush.Keys{
|
||||
Auth: sub.Auth,
|
||||
P256dh: sub.P256dh,
|
||||
},
|
||||
}
|
||||
resp, err := webpush.SendNotification(message, payload, &webpush.Options{
|
||||
Subscriber: s.config.WebPushEmailAddress,
|
||||
VAPIDPublicKey: s.config.WebPushPublicKey,
|
||||
VAPIDPrivateKey: s.config.WebPushPrivateKey,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"github.com/SherClockHolmes/webpush-go"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
@ -512,16 +511,6 @@ type webPushSubscription struct {
|
|||
UserID string
|
||||
}
|
||||
|
||||
func (w *webPushSubscription) ToSubscription() *webpush.Subscription {
|
||||
return &webpush.Subscription{
|
||||
Endpoint: w.Endpoint,
|
||||
Keys: webpush.Keys{
|
||||
Auth: w.Auth,
|
||||
P256dh: w.P256dh,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *webPushSubscription) Context() log.Context {
|
||||
return map[string]any{
|
||||
"web_push_subscription_id": w.ID,
|
||||
|
|
|
@ -63,8 +63,12 @@ const (
|
|||
WHERE st.topic = ?
|
||||
ORDER BY endpoint
|
||||
`
|
||||
selectWebPushSubscriptionsExpiringSoonQuery = `SELECT id, endpoint, key_auth, key_p256dh, user_id FROM subscription WHERE warned_at = 0 AND updated_at <= ?`
|
||||
insertWebPushSubscriptionQuery = `
|
||||
selectWebPushSubscriptionsExpiringSoonQuery = `
|
||||
SELECT id, endpoint, key_auth, key_p256dh, user_id
|
||||
FROM subscription
|
||||
WHERE warned_at = 0 AND updated_at <= ?
|
||||
`
|
||||
insertWebPushSubscriptionQuery = `
|
||||
INSERT INTO subscription (id, endpoint, key_auth, key_p256dh, user_id, subscriber_ip, updated_at, warned_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (endpoint)
|
||||
|
|
Loading…
Reference in New Issue