mirror of
https://github.com/binwiederhier/ntfy.git
synced 2024-12-22 09:42:31 +01:00
Remove web-push-(enabled|duration*), change endpoint, other cosmetic changes
This commit is contained in:
parent
4ce6fdcc5a
commit
d3ac976d05
17 changed files with 55 additions and 101 deletions
13
cmd/serve.go
13
cmd/serve.go
|
@ -94,13 +94,10 @@ var flagsServe = append(
|
|||
altsrc.NewBoolFlag(&cli.BoolFlag{Name: "enable-metrics", Aliases: []string{"enable_metrics"}, EnvVars: []string{"NTFY_ENABLE_METRICS"}, Value: false, Usage: "if set, Prometheus metrics are exposed via the /metrics endpoint"}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "metrics-listen-http", Aliases: []string{"metrics_listen_http"}, EnvVars: []string{"NTFY_METRICS_LISTEN_HTTP"}, Usage: "ip:port used to expose the metrics endpoint (implicitly enables metrics)"}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "profile-listen-http", Aliases: []string{"profile_listen_http"}, EnvVars: []string{"NTFY_PROFILE_LISTEN_HTTP"}, Usage: "ip:port used to expose the profiling endpoints (implicitly enables profiling)"}),
|
||||
altsrc.NewBoolFlag(&cli.BoolFlag{Name: "web-push-enabled", Aliases: []string{"web_push_enabled"}, EnvVars: []string{"NTFY_WEB_PUSH_ENABLED"}, Usage: "enable web push (requires public and private key)"}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "web-push-public-key", Aliases: []string{"web_push_public_key"}, EnvVars: []string{"NTFY_WEB_PUSH_PUBLIC_KEY"}, Usage: "public key used for web push notifications"}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "web-push-private-key", Aliases: []string{"web_push_private_key"}, EnvVars: []string{"NTFY_WEB_PUSH_PRIVATE_KEY"}, Usage: "private key used for web push notifications"}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "web-push-subscriptions-file", Aliases: []string{"web_push_subscriptions_file"}, EnvVars: []string{"NTFY_WEB_PUSH_SUBSCRIPTIONS_FILE"}, Usage: "file used to store web push subscriptions"}),
|
||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "web-push-email-address", Aliases: []string{"web_push_email_address"}, EnvVars: []string{"NTFY_WEB_PUSH_EMAIL_ADDRESS"}, Usage: "e-mail address of sender, required to use browser push services"}),
|
||||
altsrc.NewDurationFlag(&cli.DurationFlag{Name: "web-push-expiry-warning-duration", Aliases: []string{"web_push_expiry_warning_duration"}, EnvVars: []string{"NTFY_WEB_PUSH_EXPIRY_WARNING_DURATION"}, Value: server.DefaultWebPushExpiryWarningDuration, Usage: "duration after last update to send a warning notification"}),
|
||||
altsrc.NewDurationFlag(&cli.DurationFlag{Name: "web-push-expiry-duration", Aliases: []string{"web_push_expiry_duration"}, EnvVars: []string{"NTFY_WEB_PUSH_EXPIRY_DURATION"}, Value: server.DefaultWebPushExpiryDuration, Usage: "duration after last update to expire subscription"}),
|
||||
)
|
||||
|
||||
var cmdServe = &cli.Command{
|
||||
|
@ -136,12 +133,9 @@ func execServe(c *cli.Context) error {
|
|||
keyFile := c.String("key-file")
|
||||
certFile := c.String("cert-file")
|
||||
firebaseKeyFile := c.String("firebase-key-file")
|
||||
webPushEnabled := c.Bool("web-push-enabled")
|
||||
webPushPrivateKey := c.String("web-push-private-key")
|
||||
webPushPublicKey := c.String("web-push-public-key")
|
||||
webPushSubscriptionsFile := c.String("web-push-subscriptions-file")
|
||||
webPushExpiryWarningDuration := c.Duration("web-push-expiry-warning-duration")
|
||||
webPushExpiryDuration := c.Duration("web-push-expiry-duration")
|
||||
webPushEmailAddress := c.String("web-push-email-address")
|
||||
cacheFile := c.String("cache-file")
|
||||
cacheDuration := c.Duration("cache-duration")
|
||||
|
@ -197,12 +191,10 @@ func execServe(c *cli.Context) error {
|
|||
// Check values
|
||||
if firebaseKeyFile != "" && !util.FileExists(firebaseKeyFile) {
|
||||
return errors.New("if set, FCM key file must exist")
|
||||
} else if webPushEnabled && (webPushPrivateKey == "" || webPushPublicKey == "" || webPushSubscriptionsFile == "" || webPushEmailAddress == "" || baseURL == "") {
|
||||
} else if webPushPublicKey != "" && (webPushPrivateKey == "" || webPushSubscriptionsFile == "" || webPushEmailAddress == "" || baseURL == "") {
|
||||
return errors.New("if web push is enabled, web-push-private-key, web-push-public-key, web-push-subscriptions-file, web-push-email-address, and base-url should be set. run 'ntfy web-push generate-keys' to generate keys")
|
||||
} else if keepaliveInterval < 5*time.Second {
|
||||
return errors.New("keepalive interval cannot be lower than five seconds")
|
||||
} else if webPushEnabled && (webPushExpiryWarningDuration < 24*time.Hour || (webPushExpiryDuration-webPushExpiryWarningDuration < 24*time.Hour)) {
|
||||
return errors.New("web push expiry warning duration must be at least 1 day, expire duration must be at least 1 day later")
|
||||
} else if managerInterval < 5*time.Second {
|
||||
return errors.New("manager interval cannot be lower than five seconds")
|
||||
} else if cacheDuration > 0 && cacheDuration < managerInterval {
|
||||
|
@ -365,13 +357,10 @@ func execServe(c *cli.Context) error {
|
|||
conf.MetricsListenHTTP = metricsListenHTTP
|
||||
conf.ProfileListenHTTP = profileListenHTTP
|
||||
conf.Version = c.App.Version
|
||||
conf.WebPushEnabled = webPushEnabled
|
||||
conf.WebPushPrivateKey = webPushPrivateKey
|
||||
conf.WebPushPublicKey = webPushPublicKey
|
||||
conf.WebPushSubscriptionsFile = webPushSubscriptionsFile
|
||||
conf.WebPushEmailAddress = webPushEmailAddress
|
||||
conf.WebPushExpiryDuration = webPushExpiryDuration
|
||||
conf.WebPushExpiryWarningDuration = webPushExpiryWarningDuration
|
||||
|
||||
// Set up hot-reloading of config
|
||||
go sigHandlerConfigReload(config)
|
||||
|
|
|
@ -14,7 +14,7 @@ func init() {
|
|||
}
|
||||
|
||||
var cmdWebPush = &cli.Command{
|
||||
Name: "web-push",
|
||||
Name: "webpush",
|
||||
Usage: "Generate keys, in the future manage web push subscriptions",
|
||||
UsageText: "ntfy web-push [generate-keys]",
|
||||
Category: categoryServer,
|
||||
|
@ -22,7 +22,7 @@ var cmdWebPush = &cli.Command{
|
|||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Action: generateWebPushKeys,
|
||||
Name: "generate-keys",
|
||||
Name: "keys",
|
||||
Usage: "Generate VAPID keys to enable browser background push notifications",
|
||||
UsageText: "ntfy web-push generate-keys",
|
||||
Category: categoryServer,
|
||||
|
@ -36,28 +36,15 @@ func generateWebPushKeys(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(c.App.ErrWriter, `Keys generated.
|
||||
fmt.Fprintf(c.App.ErrWriter, `Web Push keys generated. Add the following lines to your config file:
|
||||
|
||||
VAPID Public Key:
|
||||
%s
|
||||
|
||||
VAPID Private Key:
|
||||
%s
|
||||
|
||||
---
|
||||
|
||||
Add the following lines to your config file:
|
||||
|
||||
web-push-enabled: true
|
||||
web-push-public-key: %s
|
||||
web-push-private-key: %s
|
||||
web-push-subscriptions-file: <filename>
|
||||
web-push-subscriptions-file: /var/cache/ntfy/webpush.db # or similar
|
||||
web-push-email-address: <email address>
|
||||
|
||||
Look at the docs for other methods (e.g. command line flags & environment variables).
|
||||
|
||||
You will also need to set a base-url.
|
||||
`, publicKey, privateKey, publicKey, privateKey)
|
||||
See https://ntfy.sh/docs/config/#web-push for details.
|
||||
`, publicKey, privateKey)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -10,15 +10,15 @@ import (
|
|||
|
||||
func TestCLI_WebPush_GenerateKeys(t *testing.T) {
|
||||
app, _, _, stderr := newTestApp()
|
||||
require.Nil(t, runWebPushCommand(app, server.NewConfig(), "generate-keys"))
|
||||
require.Contains(t, stderr.String(), "Keys generated.")
|
||||
require.Nil(t, runWebPushCommand(app, server.NewConfig(), "keys"))
|
||||
require.Contains(t, stderr.String(), "Web Push keys generated.")
|
||||
}
|
||||
|
||||
func runWebPushCommand(app *cli.App, conf *server.Config, args ...string) error {
|
||||
webPushArgs := []string{
|
||||
"ntfy",
|
||||
"--log-level=ERROR",
|
||||
"web-push",
|
||||
"webpush",
|
||||
}
|
||||
return app.Run(append(webPushArgs, args...))
|
||||
}
|
||||
|
|
|
@ -791,9 +791,18 @@ it'll show `New message` as a popup.
|
|||
|
||||
## Web Push notifications
|
||||
[Web Push](https://developer.mozilla.org/en-US/docs/Web/API/Push_API) ([RFC8030](https://datatracker.ietf.org/doc/html/rfc8030))
|
||||
is supported, but needs a little configuration to enable it. Since there is no central server (other than the browser's push endpoint),
|
||||
you have to configure your own [VAPID](https://datatracker.ietf.org/doc/html/draft-thomson-webpush-vapid) keys. These identify the publisher,
|
||||
and are used to encrypt the messages before sending them to the push endpoint.
|
||||
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
|
||||
user, ntfy will forward published messages to the push endpoint (browser-provided, e.g. fcm.googleapis.com), which will then
|
||||
forward it to the browser.
|
||||
|
||||
To configure Web Push, you need to generate and configure a [VAPID](https://datatracker.ietf.org/doc/html/draft-thomson-webpush-vapid) keypair (via `ntfy webpush keys`),
|
||||
a database to keep track of the browser's subscriptions, and an admin email address (you):
|
||||
|
||||
- `web-push-public-key` is the generated VAPID public key, e.g. AA1234BBCCddvveekaabcdfqwertyuiopasdfghjklzxcvbnm1234567890
|
||||
- `web-push-private-key` is the generated VAPID private key, e.g. AA2BB1234567890abcdefzxcvbnm1234567890
|
||||
- `web-push-subscriptions-file` is a database file to keep track of browser subscription endpoints, e.g. `/var/cache/ntfy/webpush.db`
|
||||
- `web-push-email-address` is the admin email address send to the push provider, e.g. `sysadmin@example.com`
|
||||
|
||||
Limitations:
|
||||
|
||||
|
@ -806,32 +815,17 @@ Limitations:
|
|||
To configure VAPID keys, first generate them:
|
||||
|
||||
```sh
|
||||
$ ntfy web-push generate-keys
|
||||
Keys generated.
|
||||
|
||||
VAPID Public Key:
|
||||
AA1234BBCCddvveekaabcdfqwertyuiopasdfghjklzxcvbnm1234567890
|
||||
|
||||
VAPID Private Key:
|
||||
AA2BB1234567890abcdefzxcvbnm1234567890
|
||||
$ 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:
|
||||
|
||||
```yaml
|
||||
web-push-enabled: true
|
||||
web-push-public-key: AA1234BBCCddvveekaabcdfqwertyuiopasdfghjklzxcvbnm1234567890
|
||||
web-push-private-key: AA2BB1234567890abcdefzxcvbnm1234567890
|
||||
web-push-subscriptions-file: /var/cache/ntfy/subscriptions.db
|
||||
web-push-subscriptions-file: /var/cache/ntfy/webpush.db
|
||||
web-push-email-address: sysadmin@example.com
|
||||
|
||||
# don't forget to set the required base-url for web push notifications
|
||||
base-url: https://ntfy.example.com
|
||||
|
||||
# you can also set custom expiry and warning durations
|
||||
# the minimum is 1 day for warning, and 1 day after warning for expiry
|
||||
web-push-expiry-warning-duration: 168h
|
||||
web-push-expiry-duration: 192h
|
||||
```
|
||||
|
||||
The `web-push-subscriptions-file` is used to store the push subscriptions. Subscriptions do not ever expire automatically, unless the push
|
||||
|
@ -840,7 +834,7 @@ gateway returns an error (e.g. 410 Gone when a user has unsubscribed).
|
|||
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.
|
||||
|
||||
Changing your public/private keypair is NOT recommended. Browsers only allow one server identity (public key) per origin, and
|
||||
Changing your public/private keypair is **not recommended**. Browsers only allow one server identity (public key) per origin, and
|
||||
if you change them the clients will not be able to subscribe via web push until the user manually clears the notification permission.
|
||||
|
||||
## Tiers
|
||||
|
@ -1340,12 +1334,10 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
|
|||
| `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-enabled` | `NTFY_WEB_PUSH_ENABLED` | *boolean* (`true` or `false`) | - | Web Push: Enable/disable (requires private and public key below). |
|
||||
| `web-push-public-key` | `NTFY_WEB_PUSH_PUBLIC_KEY` | *string* | - | Web Push: Public Key. Run `ntfy web-push generate-keys` to generate |
|
||||
| `web-push-private-key` | `NTFY_WEB_PUSH_PRIVATE_KEY` | *string* | - | Web Push: Private Key. Run `ntfy web-push generate-keys` to generate |
|
||||
| `web-push-subscriptions-file` | `NTFY_WEB_PUSH_SUBSCRIPTIONS_FILE` | *string* | - | Web Push: Subscriptions file |
|
||||
| `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-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 |
|
||||
| `web-push-expiry-warning-duration` | `NTFY_WEB_PUSH_EXPIRY_WARNING_DURATION` | *duration* | 1 week | Web Push: Time before expiry warning is sent (min 1 day) |
|
||||
| `web-push-expiry-duration` | `NTFY_WEB_PUSH_EXPIRY_DURATION` | *duration* | 1 week + 1 day | Web Push: Time before subscription is expired (min 1 day after warning) |
|
||||
|
||||
The format for a *duration* is: `<number>(smh)`, e.g. 30s, 20m or 1h.
|
||||
The format for a *size* is: `<number>(GMK)`, e.g. 1G, 200M or 4000k.
|
||||
|
@ -1443,8 +1435,6 @@ OPTIONS:
|
|||
--web-push-private-key value, --web_push_private_key value private key used for web push notifications [$NTFY_WEB_PUSH_PRIVATE_KEY]
|
||||
--web-push-subscriptions-file value, --web_push_subscriptions_file value file used to store web push subscriptions [$NTFY_WEB_PUSH_SUBSCRIPTIONS_FILE]
|
||||
--web-push-email-address value, --web_push_email_address value e-mail address of sender, required to use browser push services [$NTFY_WEB_PUSH_EMAIL_ADDRESS]
|
||||
--web-push-expiry-warning-duration value, --web_push_expiry_warning_duration value duration after last update to send a warning notification (default: 168h0m0s) [$NTFY_WEB_PUSH_EXPIRY_WARNING_DURATION]
|
||||
--web-push-expiry-duration value, --web_push_expiry_duration value duration after last update to expire subscription (default: 192h0m0s) [$NTFY_WEB_PUSH_EXPIRY_DURATION]
|
||||
--help, -h show help
|
||||
|
||||
```
|
||||
|
|
|
@ -153,7 +153,6 @@ type Config struct {
|
|||
EnableMetrics bool
|
||||
AccessControlAllowOrigin string // CORS header field to restrict access from web clients
|
||||
Version string // injected by App
|
||||
WebPushEnabled bool
|
||||
WebPushPrivateKey string
|
||||
WebPushPublicKey string
|
||||
WebPushSubscriptionsFile string
|
||||
|
@ -241,7 +240,6 @@ func NewConfig() *Config {
|
|||
EnableReservations: false,
|
||||
AccessControlAllowOrigin: "*",
|
||||
Version: "",
|
||||
WebPushEnabled: false,
|
||||
WebPushPrivateKey: "",
|
||||
WebPushPublicKey: "",
|
||||
WebPushSubscriptionsFile: "",
|
||||
|
|
|
@ -94,7 +94,7 @@ var (
|
|||
apiAccountSettingsPath = "/v1/account/settings"
|
||||
apiAccountSubscriptionPath = "/v1/account/subscription"
|
||||
apiAccountReservationPath = "/v1/account/reservation"
|
||||
apiAccountWebPushPath = "/v1/account/web-push"
|
||||
apiAccountWebPushPath = "/v1/account/webpush"
|
||||
apiAccountPhonePath = "/v1/account/phone"
|
||||
apiAccountPhoneVerifyPath = "/v1/account/phone/verify"
|
||||
apiAccountBillingPortalPath = "/v1/account/billing/portal"
|
||||
|
@ -157,7 +157,7 @@ func New(conf *Config) (*Server, error) {
|
|||
return nil, err
|
||||
}
|
||||
var webPush *webPushStore
|
||||
if conf.WebPushEnabled {
|
||||
if conf.WebPushPublicKey != "" {
|
||||
webPush, err = newWebPushStore(conf.WebPushSubscriptionsFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -574,7 +574,7 @@ func (s *Server) handleWebConfig(w http.ResponseWriter, _ *http.Request, _ *visi
|
|||
EnableCalls: s.config.TwilioAccount != "",
|
||||
EnableEmails: s.config.SMTPSenderFrom != "",
|
||||
EnableReservations: s.config.EnableReservations,
|
||||
EnableWebPush: s.config.WebPushEnabled,
|
||||
EnableWebPush: s.config.WebPushPublicKey != "",
|
||||
BillingContact: s.config.BillingContact,
|
||||
WebPushPublicKey: s.config.WebPushPublicKey,
|
||||
DisallowedTopics: s.config.DisallowedTopics,
|
||||
|
@ -792,7 +792,7 @@ func (s *Server) handlePublishInternal(r *http.Request, v *visitor) (*message, e
|
|||
if s.config.UpstreamBaseURL != "" && !unifiedpush { // UP messages are not sent to upstream
|
||||
go s.forwardPollRequest(v, m)
|
||||
}
|
||||
if s.config.WebPushEnabled {
|
||||
if s.config.WebPushPublicKey != "" {
|
||||
go s.publishToWebPushEndpoints(v, m)
|
||||
}
|
||||
} else {
|
||||
|
@ -1724,7 +1724,7 @@ func (s *Server) sendDelayedMessage(v *visitor, m *message) error {
|
|||
if s.config.UpstreamBaseURL != "" {
|
||||
go s.forwardPollRequest(v, m)
|
||||
}
|
||||
if s.config.WebPushEnabled {
|
||||
if s.config.WebPushPublicKey != "" {
|
||||
go s.publishToWebPushEndpoints(v, m)
|
||||
}
|
||||
if err := s.messageCache.MarkPublished(m); err != nil {
|
||||
|
|
|
@ -40,15 +40,12 @@
|
|||
|
||||
# Enable web push
|
||||
#
|
||||
# Run "ntfy web-push generate-keys" to generate the keys
|
||||
# Run "ntfy webpush keys" to generate the keys
|
||||
#
|
||||
# web-push-enabled: false
|
||||
# web-push-public-key:
|
||||
# web-push-private-key:
|
||||
# web-push-subscriptions-file:
|
||||
# web-push-email-address:
|
||||
# web-push-expiry-warning-duration: 168h
|
||||
# web-push-expiry-duration: 192h
|
||||
|
||||
# If "cache-file" is set, messages are cached in a local SQLite database instead of only in-memory.
|
||||
# This allows for service restarts without losing messages in support of the since= parameter.
|
||||
|
|
|
@ -15,7 +15,7 @@ func (s *Server) execManager() {
|
|||
s.pruneTokens()
|
||||
s.pruneAttachments()
|
||||
s.pruneMessages()
|
||||
if s.config.WebPushEnabled {
|
||||
if s.config.WebPushPublicKey != "" {
|
||||
s.expireOrNotifyOldSubscriptions()
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ func (s *Server) ensureWebEnabled(next handleFunc) handleFunc {
|
|||
|
||||
func (s *Server) ensureWebPushEnabled(next handleFunc) handleFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request, v *visitor) error {
|
||||
if !s.config.WebPushEnabled {
|
||||
if s.config.WebPushPublicKey == "" {
|
||||
return errHTTPNotFound
|
||||
}
|
||||
return next(w, r, v)
|
||||
|
|
|
@ -2622,8 +2622,7 @@ func newTestConfigWithWebPush(t *testing.T) *Config {
|
|||
conf := newTestConfig(t)
|
||||
privateKey, publicKey, err := webpush.GenerateVAPIDKeys()
|
||||
require.Nil(t, err)
|
||||
conf.WebPushEnabled = true
|
||||
conf.WebPushSubscriptionsFile = filepath.Join(t.TempDir(), "subscriptions.db")
|
||||
conf.WebPushSubscriptionsFile = filepath.Join(t.TempDir(), "webpush.db")
|
||||
conf.WebPushEmailAddress = "testing@example.com"
|
||||
conf.WebPushPrivateKey = privateKey
|
||||
conf.WebPushPublicKey = publicKey
|
||||
|
|
|
@ -76,7 +76,7 @@ func (s *Server) publishToWebPushEndpoints(v *visitor, m *message) {
|
|||
}
|
||||
|
||||
// TODO this should return error
|
||||
// TODO the updated_at field is not actually updated ever
|
||||
// TODO rate limiting
|
||||
|
||||
func (s *Server) expireOrNotifyOldSubscriptions() {
|
||||
subscriptions, err := s.webPush.ExpireAndGetExpiringSubscriptions(s.config.WebPushExpiryWarningDuration, s.config.WebPushExpiryDuration)
|
||||
|
|
|
@ -23,7 +23,7 @@ const (
|
|||
func TestServer_WebPush_TopicAdd(t *testing.T) {
|
||||
s := newTestServer(t, newTestConfigWithWebPush(t))
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), nil)
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), nil)
|
||||
require.Equal(t, 200, response.Code)
|
||||
require.Equal(t, `{"success":true}`+"\n", response.Body.String())
|
||||
|
||||
|
@ -40,7 +40,7 @@ func TestServer_WebPush_TopicAdd(t *testing.T) {
|
|||
func TestServer_WebPush_TopicAdd_InvalidEndpoint(t *testing.T) {
|
||||
s := newTestServer(t, newTestConfigWithWebPush(t))
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, []string{"test-topic"}, "https://ddos-target.example.com/webpush"), nil)
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, []string{"test-topic"}, "https://ddos-target.example.com/webpush"), nil)
|
||||
require.Equal(t, 400, response.Code)
|
||||
require.Equal(t, `{"code":40039,"http":400,"error":"invalid request: web push endpoint unknown"}`+"\n", response.Body.String())
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func TestServer_WebPush_TopicAdd_TooManyTopics(t *testing.T) {
|
|||
topicList[i] = util.RandomString(5)
|
||||
}
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, topicList, defaultEndpoint), nil)
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, topicList, defaultEndpoint), nil)
|
||||
require.Equal(t, 400, response.Code)
|
||||
require.Equal(t, `{"code":40040,"http":400,"error":"invalid request: too many web push topic subscriptions"}`+"\n", response.Body.String())
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func TestServer_WebPush_TopicUnsubscribe(t *testing.T) {
|
|||
addSubscription(t, s, "test-topic", defaultEndpoint)
|
||||
requireSubscriptionCount(t, s, "test-topic", 1)
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, []string{}, defaultEndpoint), nil)
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, []string{}, defaultEndpoint), nil)
|
||||
require.Equal(t, 200, response.Code)
|
||||
require.Equal(t, `{"success":true}`+"\n", response.Body.String())
|
||||
|
||||
|
@ -79,7 +79,7 @@ func TestServer_WebPush_TopicSubscribeProtected_Allowed(t *testing.T) {
|
|||
require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser))
|
||||
require.Nil(t, s.userManager.AllowAccess("ben", "test-topic", user.PermissionReadWrite))
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), map[string]string{
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), map[string]string{
|
||||
"Authorization": util.BasicAuth("ben", "ben"),
|
||||
})
|
||||
require.Equal(t, 200, response.Code)
|
||||
|
@ -96,7 +96,7 @@ func TestServer_WebPush_TopicSubscribeProtected_Denied(t *testing.T) {
|
|||
config.AuthDefault = user.PermissionDenyAll
|
||||
s := newTestServer(t, config)
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), nil)
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), nil)
|
||||
require.Equal(t, 403, response.Code)
|
||||
|
||||
requireSubscriptionCount(t, s, "test-topic", 0)
|
||||
|
@ -109,7 +109,7 @@ func TestServer_WebPush_DeleteAccountUnsubscribe(t *testing.T) {
|
|||
require.Nil(t, s.userManager.AddUser("ben", "ben", user.RoleUser))
|
||||
require.Nil(t, s.userManager.AllowAccess("ben", "test-topic", user.PermissionReadWrite))
|
||||
|
||||
response := request(t, s, "PUT", "/v1/account/web-push", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), map[string]string{
|
||||
response := request(t, s, "PUT", "/v1/account/webpush", payloadForTopics(t, []string{"test-topic"}, defaultEndpoint), map[string]string{
|
||||
"Authorization": util.BasicAuth("ben", "ben"),
|
||||
})
|
||||
|
||||
|
|
|
@ -31,10 +31,9 @@ const (
|
|||
INSERT OR REPLACE INTO subscriptions (topic, user_id, endpoint, key_auth, key_p256dh)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`
|
||||
deleteWebPushSubscriptionByEndpointQuery = `DELETE FROM subscriptions WHERE endpoint = ?`
|
||||
deleteWebPushSubscriptionByUserIDQuery = `DELETE FROM subscriptions WHERE user_id = ?`
|
||||
deleteWebPushSubscriptionByTopicAndEndpointQuery = `DELETE FROM subscriptions WHERE topic = ? AND endpoint = ?`
|
||||
deleteWebPushSubscriptionsByAgeQuery = `DELETE FROM subscriptions WHERE warning_sent = 1 AND updated_at <= datetime('now', ?)`
|
||||
deleteWebPushSubscriptionByEndpointQuery = `DELETE FROM subscriptions WHERE endpoint = ?`
|
||||
deleteWebPushSubscriptionByUserIDQuery = `DELETE FROM subscriptions WHERE user_id = ?`
|
||||
deleteWebPushSubscriptionsByAgeQuery = `DELETE FROM subscriptions WHERE warning_sent = 1 AND updated_at <= datetime('now', ?)`
|
||||
|
||||
selectWebPushSubscriptionsForTopicQuery = `SELECT endpoint, key_auth, key_p256dh, user_id FROM subscriptions WHERE topic = ?`
|
||||
selectWebPushSubscriptionsExpiringSoonQuery = `SELECT DISTINCT endpoint, key_auth, key_p256dh FROM subscriptions WHERE warning_sent = 0 AND updated_at <= datetime('now', ?)`
|
||||
|
@ -169,8 +168,7 @@ func (c *webPushStore) ExpireAndGetExpiringSubscriptions(warningDuration time.Du
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
if err = tx.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
topicUrlAuth,
|
||||
topicUrlJsonPoll,
|
||||
topicUrlJsonPollWithSince,
|
||||
webPushSubscriptionsUrl,
|
||||
accountWebPushUrl,
|
||||
} from "./utils";
|
||||
import userManager from "./UserManager";
|
||||
import { fetchOrThrow } from "./errors";
|
||||
|
@ -117,7 +117,7 @@ class Api {
|
|||
|
||||
async updateWebPushSubscriptions(topics, browserSubscription) {
|
||||
const user = await userManager.get(config.base_url);
|
||||
const url = webPushSubscriptionsUrl(config.base_url);
|
||||
const url = accountWebPushUrl(config.base_url);
|
||||
console.log(`[Api] Sending Web Push Subscriptions`, { url, topics, endpoint: browserSubscription.endpoint });
|
||||
|
||||
const response = await fetch(url, {
|
||||
|
|
|
@ -52,17 +52,14 @@ class Notifier {
|
|||
if (!this.pushPossible()) {
|
||||
throw new Error("Unsupported or denied");
|
||||
}
|
||||
|
||||
const pushManager = await this.pushManager();
|
||||
|
||||
const existingSubscription = await pushManager.getSubscription();
|
||||
|
||||
if (existingSubscription) {
|
||||
return existingSubscription;
|
||||
}
|
||||
|
||||
// create a new subscription only if web push is enabled
|
||||
// it is possible that web push was previously enabled and then disabled again
|
||||
// Create a new subscription only if web push is enabled.
|
||||
// It is possible that web push was previously enabled and then disabled again
|
||||
// in which case there would be an existingSubscription.
|
||||
// but if it was _not_ enabled previously, we reach here, and only create a new
|
||||
// subscription if it is now enabled.
|
||||
|
|
|
@ -113,7 +113,6 @@ class SubscriptionManager {
|
|||
|
||||
async refreshWebPushSubscriptions(presetTopics) {
|
||||
const topics = presetTopics ?? (await this.webPushTopics());
|
||||
|
||||
const browserSubscription = await notifier.getBrowserSubscription();
|
||||
|
||||
if (!browserSubscription) {
|
||||
|
|
|
@ -21,7 +21,6 @@ export const topicUrlJsonPoll = (baseUrl, topic) => `${topicUrlJson(baseUrl, top
|
|||
export const topicUrlJsonPollWithSince = (baseUrl, topic, since) => `${topicUrlJson(baseUrl, topic)}?poll=1&since=${since}`;
|
||||
export const topicUrlAuth = (baseUrl, topic) => `${topicUrl(baseUrl, topic)}/auth`;
|
||||
export const topicShortUrl = (baseUrl, topic) => shortUrl(topicUrl(baseUrl, topic));
|
||||
export const webPushSubscriptionsUrl = (baseUrl) => `${baseUrl}/v1/account/web-push`;
|
||||
export const accountUrl = (baseUrl) => `${baseUrl}/v1/account`;
|
||||
export const accountPasswordUrl = (baseUrl) => `${baseUrl}/v1/account/password`;
|
||||
export const accountTokenUrl = (baseUrl) => `${baseUrl}/v1/account/token`;
|
||||
|
@ -33,6 +32,7 @@ export const accountBillingSubscriptionUrl = (baseUrl) => `${baseUrl}/v1/account
|
|||
export const accountBillingPortalUrl = (baseUrl) => `${baseUrl}/v1/account/billing/portal`;
|
||||
export const accountPhoneUrl = (baseUrl) => `${baseUrl}/v1/account/phone`;
|
||||
export const accountPhoneVerifyUrl = (baseUrl) => `${baseUrl}/v1/account/phone/verify`;
|
||||
export const accountWebPushUrl = (baseUrl) => `${baseUrl}/v1/account/webpush`;
|
||||
|
||||
export const validUrl = (url) => url.match(/^https?:\/\/.+/);
|
||||
|
||||
|
|
Loading…
Reference in a new issue