diff --git a/cmd/serve.go b/cmd/serve.go index 62494ffb..a1f7b21c 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -98,6 +98,7 @@ var flagsServe = append( 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-file", Aliases: []string{"web_push_file"}, EnvVars: []string{"NTFY_WEB_PUSH_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.NewStringFlag(&cli.StringFlag{Name: "web-push-startup-queries", Aliases: []string{"web_push_startup-queries"}, EnvVars: []string{"NTFY_WEB_PUSH_STARTUP_QUERIES"}, Usage: "queries run when the web push database is initialized"}), ) var cmdServe = &cli.Command{ @@ -137,6 +138,7 @@ func execServe(c *cli.Context) error { webPushPublicKey := c.String("web-push-public-key") webPushFile := c.String("web-push-file") webPushEmailAddress := c.String("web-push-email-address") + webPushStartupQueries := c.String("web-push-startup-queries") cacheFile := c.String("cache-file") cacheDuration := c.Duration("cache-duration") cacheStartupQueries := c.String("cache-startup-queries") @@ -361,6 +363,7 @@ func execServe(c *cli.Context) error { conf.WebPushPublicKey = webPushPublicKey conf.WebPushFile = webPushFile conf.WebPushEmailAddress = webPushEmailAddress + conf.WebPushStartupQueries = webPushStartupQueries // Set up hot-reloading of config go sigHandlerConfigReload(config) diff --git a/docs/config.md b/docs/config.md index 70c860c1..9af79992 100644 --- a/docs/config.md +++ b/docs/config.md @@ -803,6 +803,7 @@ a database to keep track of the browser's subscriptions, and an admin email addr - `web-push-private-key` is the generated VAPID private key, e.g. AA2BB1234567890abcdefzxcvbnm1234567890 - `web-push-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` +- `web-push-startup-queries` is an optional list of queries to run on startup` Limitations: @@ -1339,6 +1340,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`). | `web-push-private-key` | `NTFY_WEB_PUSH_PRIVATE_KEY` | *string* | - | Web Push: Private Key. Run `ntfy webpush keys` to generate | | `web-push-file` | `NTFY_WEB_PUSH_FILE` | *string* | - | Web Push: Database file that stores subscriptions | | `web-push-email-address` | `NTFY_WEB_PUSH_EMAIL_ADDRESS` | *string* | - | Web Push: Sender email address | +| `web-push-startup-queries` | `NTFY_WEB_PUSH_STARTUP_QUERIES` | *string* | - | Web Push: SQL queries to run against subscription database at startup | The format for a *duration* is: `(smh)`, e.g. 30s, 20m or 1h. The format for a *size* is: `(GMK)`, e.g. 1G, 200M or 4000k. @@ -1435,5 +1437,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-file value, --web_push_file value file used to store web push subscriptions [$NTFY_WEB_PUSH_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-startup-queries value, --web_push_startup-queries value queries run when the web push database is initialized [$NTFY_WEB_PUSH_STARTUP_QUERIES] --help, -h show help ``` diff --git a/server/config.go b/server/config.go index 078a546c..9815aa88 100644 --- a/server/config.go +++ b/server/config.go @@ -157,6 +157,7 @@ type Config struct { WebPushPublicKey string WebPushFile string WebPushEmailAddress string + WebPushStartupQueries string WebPushExpiryDuration time.Duration WebPushExpiryWarningDuration time.Duration } diff --git a/server/server.go b/server/server.go index aff7771d..82057082 100644 --- a/server/server.go +++ b/server/server.go @@ -158,7 +158,7 @@ func New(conf *Config) (*Server, error) { } var webPush *webPushStore if conf.WebPushPublicKey != "" { - webPush, err = newWebPushStore(conf.WebPushFile) + webPush, err = newWebPushStore(conf.WebPushFile, conf.WebPushStartupQueries) if err != nil { return nil, err } diff --git a/server/server.yml b/server/server.yml index 3119b5e4..6b2fc989 100644 --- a/server/server.yml +++ b/server/server.yml @@ -150,18 +150,20 @@ # 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. +# You must configure web-push-public/private key, web-push-file, and web-push-email-address below to enable Web Push. # Run "ntfy webpush keys" to generate the keys. # # - 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-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` +# - web-push-startup-queries is an optional list of queries to run on startup` # # web-push-public-key: # web-push-private-key: # web-push-file: # web-push-email-address: +# web-push-startup-queries: # If enabled, ntfy can perform voice calls via Twilio via the "X-Call" header. # diff --git a/server/server_account_test.go b/server/server_account_test.go index bf9b84db..119efb16 100644 --- a/server/server_account_test.go +++ b/server/server_account_test.go @@ -431,41 +431,6 @@ 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 diff --git a/server/webpush_store.go b/server/webpush_store.go index ad3e8588..b2ab0d11 100644 --- a/server/webpush_store.go +++ b/server/webpush_store.go @@ -94,7 +94,7 @@ type webPushStore struct { db *sql.DB } -func newWebPushStore(filename string) (*webPushStore, error) { +func newWebPushStore(filename, startupQueries string) (*webPushStore, error) { db, err := sql.Open("sqlite3", filename) if err != nil { return nil, err @@ -102,7 +102,7 @@ func newWebPushStore(filename string) (*webPushStore, error) { if err := setupWebPushDB(db); err != nil { return nil, err } - if err := runWebPushStartupQueries(db); err != nil { + if err := runWebPushStartupQueries(db, startupQueries); err != nil { return nil, err } return &webPushStore{ @@ -129,9 +129,14 @@ func setupNewWebPushDB(db *sql.DB) error { return nil } -func runWebPushStartupQueries(db *sql.DB) error { - _, err := db.Exec(builtinStartupQueries) - return err +func runWebPushStartupQueries(db *sql.DB, startupQueries string) error { + if _, err := db.Exec(startupQueries); err != nil { + return err + } + if _, err := db.Exec(builtinStartupQueries); err != nil { + return err + } + return nil } // UpsertSubscription adds or updates Web Push subscriptions for the given topics and user ID. It always first deletes all diff --git a/server/webpush_store_test.go b/server/webpush_store_test.go index e96603fd..ab5bc424 100644 --- a/server/webpush_store_test.go +++ b/server/webpush_store_test.go @@ -193,7 +193,7 @@ func TestWebPushStore_RemoveExpiredSubscriptions(t *testing.T) { } func newTestWebPushStore(t *testing.T) *webPushStore { - webPush, err := newWebPushStore(filepath.Join(t.TempDir(), "webpush.db")) + webPush, err := newWebPushStore(filepath.Join(t.TempDir(), "webpush.db"), "") require.Nil(t, err) return webPush }