Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PWA manifest, service worker, and web push #751

Merged
merged 82 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
ff5c854
Add PWA, service worker and Web Push
nimbleghost May 24, 2023
a9fef38
Add web push tests
nimbleghost May 29, 2023
f94bb1a
Improve web push docs
nimbleghost May 29, 2023
7b23158
Cosmetic changes
binwiederhier May 30, 2023
7f3e4b5
Move stuff to server_web_push.go
binwiederhier May 30, 2023
9e0687e
Random tiny changes
binwiederhier May 30, 2023
e8139ad
Move web-push-config endpoint to config.js
binwiederhier May 30, 2023
20c7650
server.yml update
binwiederhier May 30, 2023
44913c1
Replace if err-nil-Fatal check with require.Nil
nimbleghost May 31, 2023
4648f83
Format emojis in the service worker directly
nimbleghost May 31, 2023
0c25425
Use readJSONWithLimit for web push sub/unsub
nimbleghost May 31, 2023
7aa3d8f
Hide web push toggles if disabled on server
nimbleghost May 31, 2023
4944e3a
Remove webPushEndpoint from indexeddb
nimbleghost May 31, 2023
47ad024
Simplify web push UX and updates
nimbleghost Jun 2, 2023
0f0074c
Implement push subscription expiry
nimbleghost Jun 2, 2023
46f34ca
Add push service allowlist and topic limit
nimbleghost Jun 2, 2023
03aa67e
Remove `webPushDefaultEnabled`
nimbleghost Jun 7, 2023
18edff9
Add TODO comment about Safari 17 PWA
nimbleghost Jun 7, 2023
f3db0e0
Add release notes
nimbleghost Jun 7, 2023
a8db08c
Use attachment URL for image & add timestamp
nimbleghost Jun 7, 2023
46798ac
Make web push toggle global
nimbleghost Jun 8, 2023
2f5acee
Call pushManager.subscribe only if enabled
nimbleghost Jun 8, 2023
75a4b5b
Small refactor
binwiederhier Jun 8, 2023
4ce6fdc
Implement http actions in service worker
nimbleghost Jun 8, 2023
d3ac976
Remove web-push-(enabled|duration*), change endpoint, other cosmetic …
binwiederhier Jun 8, 2023
9d38aeb
Docs in server.yml, schemaVersion table, refactoring
binwiederhier Jun 9, 2023
966ffe1
More refactor
binwiederhier Jun 9, 2023
9e4eafe
Format
nimbleghost Jun 9, 2023
4704b2a
Set default TTL for web push to the cache duration
nimbleghost Jun 9, 2023
2e8292a
No real changes, just renames
binwiederhier Jun 9, 2023
1abcc88
Add subscription_topic table, change updated_at type to INT, split ex…
binwiederhier Jun 10, 2023
9d5556c
Rename things, add comments
binwiederhier Jun 11, 2023
eb22054
Change wording in prefs based on setting
binwiederhier Jun 11, 2023
58992fc
Make DELETE endpoint, add different UI description
binwiederhier Jun 11, 2023
4e44b03
Merge branch 'main' of github.com:binwiederhier/ntfy into pwa
binwiederhier Jun 12, 2023
a8def0a
Make allowed endpoints a list of patterns
binwiederhier Jun 13, 2023
2d0c043
Derp
binwiederhier Jun 13, 2023
9e19183
Merge branch 'main' into pwa
binwiederhier Jun 13, 2023
8ccfa5c
Fix session replica behaviour (merge with session)
nimbleghost Jun 13, 2023
390d42c
Format & fix lint
nimbleghost Jun 13, 2023
cf050cc
Merge branch 'pwa' of github.com:nimbleghost/ntfy into pwa
binwiederhier Jun 14, 2023
6b38499
Revert alert text and button, and warning
binwiederhier Jun 14, 2023
790fd43
Tiny changes
binwiederhier Jun 14, 2023
7083ed9
Move websocketSubscriptions to useConnectionListeners
binwiederhier Jun 14, 2023
67b9d2e
Add missing await
nimbleghost Jun 14, 2023
e2120bc
Improve WebPushEnabled conditional display
nimbleghost Jun 14, 2023
67948d0
Remove stray console.log
nimbleghost Jun 14, 2023
aeb6073
Wording
binwiederhier Jun 14, 2023
ad36f5d
Merge branch 'main' into pwa
binwiederhier Jun 14, 2023
9403873
Re-increate Dexie version number
binwiederhier Jun 14, 2023
4dc89f6
Tiny fixes
binwiederhier Jun 14, 2023
eebe4f8
Refactor and document sw.js file
nimbleghost Jun 14, 2023
2dcad15
Add missing await
nimbleghost Jun 14, 2023
83eb4c3
Add i18n to service worker
nimbleghost Jun 14, 2023
fa418ee
Update develop.md sw docs
nimbleghost Jun 14, 2023
b197ea3
Use the same notification pipeline everywhere
nimbleghost Jun 14, 2023
6e95d62
Cosmetic changess
binwiederhier Jun 16, 2023
c43a116
Docs, mostly
binwiederhier Jun 16, 2023
341e84f
Limit number of webpush subscriptions per subscriber IP
binwiederhier Jun 17, 2023
ff7e894
Add more tests, change endpoint
binwiederhier Jun 17, 2023
2d45e39
Add disabled web push test
nimbleghost Jun 17, 2023
3cd61d8
Add web push delete test
nimbleghost Jun 17, 2023
b7bb445
Check for image mimetype first
nimbleghost Jun 17, 2023
fafe478
Sync localStorage to indexedDB on startup
nimbleghost Jun 17, 2023
9ba733d
Add a reload button to error boundary
nimbleghost Jun 17, 2023
30a8f66
Reorder start/stopWorkers
nimbleghost Jun 17, 2023
020996e
Minor changes
binwiederhier Jun 18, 2023
88c6b4a
Rename web-push-subscriptions-file to web-push-file
binwiederhier Jun 18, 2023
dc7dd83
web-push-startup-queries
binwiederhier Jun 18, 2023
89f5cc5
Doc fixes
nimbleghost Jun 18, 2023
5ce7866
Doc fixes (2)
nimbleghost Jun 18, 2023
27a4e58
Merge branch 'main' into pwa
binwiederhier Jun 19, 2023
6615aea
Fix grant button in language files
binwiederhier Jun 19, 2023
d7aacb8
Fix PWA for non-root web roots
nimbleghost Jun 19, 2023
000a3e0
Improve dynamic webmanifest setup
nimbleghost Jun 19, 2023
8211b4c
Fix: add v1 to navigation fallback denylist
nimbleghost Jun 19, 2023
5f6d753
Remove navigation fallback for all except app root
nimbleghost Jun 19, 2023
f61c67e
Translated using Weblate (Turkish)
oersen Jun 19, 2023
d266579
Merge branch 'main' of https://hosted.weblate.org/git/ntfy/web into pwa
binwiederhier Jun 21, 2023
c400c55
Merge branch 'main' of https://hosted.weblate.org/git/ntfy/web
binwiederhier Jun 21, 2023
141565d
Merge branch 'main' into pwa
binwiederhier Jun 21, 2023
271056a
The last commit
binwiederhier Jun 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ secrets/
node_modules/
.DS_Store
__pycache__
web/dev-dist/
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,4 @@ Third party libraries and resources:
* [Regex for auto-linking](https://github.com/bryanwoods/autolink-js) (MIT) is used to highlight links (the library is not used)
* [Statically linking go-sqlite3](https://www.arp242.net/static-go.html)
* [Linked tabs in mkdocs](https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/#linked-tabs)
* [webpush-go](https://github.com/SherClockHolmes/webpush-go) (MIT) is used to send web push notifications
14 changes: 14 additions & 0 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +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.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-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"}),
)

var cmdServe = &cli.Command{
Expand Down Expand Up @@ -129,6 +133,10 @@ func execServe(c *cli.Context) error {
keyFile := c.String("key-file")
certFile := c.String("cert-file")
firebaseKeyFile := c.String("firebase-key-file")
webPushPrivateKey := c.String("web-push-private-key")
webPushPublicKey := c.String("web-push-public-key")
webPushFile := c.String("web-push-file")
webPushEmailAddress := c.String("web-push-email-address")
cacheFile := c.String("cache-file")
cacheDuration := c.Duration("cache-duration")
cacheStartupQueries := c.String("cache-startup-queries")
Expand Down Expand Up @@ -183,6 +191,8 @@ 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 webPushPublicKey != "" && (webPushPrivateKey == "" || webPushFile == "" || webPushEmailAddress == "" || baseURL == "") {
return errors.New("if web push is enabled, web-push-private-key, web-push-public-key, web-push-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 managerInterval < 5*time.Second {
Expand Down Expand Up @@ -347,6 +357,10 @@ func execServe(c *cli.Context) error {
conf.MetricsListenHTTP = metricsListenHTTP
conf.ProfileListenHTTP = profileListenHTTP
conf.Version = c.App.Version
conf.WebPushPrivateKey = webPushPrivateKey
conf.WebPushPublicKey = webPushPublicKey
conf.WebPushFile = webPushFile
conf.WebPushEmailAddress = webPushEmailAddress

// Set up hot-reloading of config
go sigHandlerConfigReload(config)
Expand Down
48 changes: 48 additions & 0 deletions cmd/webpush.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//go:build !noserver

package cmd

import (
"fmt"

"github.com/SherClockHolmes/webpush-go"
"github.com/urfave/cli/v2"
)

func init() {
commands = append(commands, cmdWebPush)
}

var cmdWebPush = &cli.Command{
Name: "webpush",
Usage: "Generate keys, in the future manage web push subscriptions",
UsageText: "ntfy webpush [keys]",
Category: categoryServer,

Subcommands: []*cli.Command{
{
Action: generateWebPushKeys,
Name: "keys",
Usage: "Generate VAPID keys to enable browser background push notifications",
UsageText: "ntfy webpush keys",
Category: categoryServer,
},
},
}

func generateWebPushKeys(c *cli.Context) error {
privateKey, publicKey, err := webpush.GenerateVAPIDKeys()
if err != nil {
return err
}
_, err = fmt.Fprintf(c.App.ErrWriter, `Web Push keys generated. Add the following lines to your config file:

web-push-public-key: %s
web-push-private-key: %s
web-push-file: /var/cache/ntfy/webpush.db # or similar
web-push-email-address: <email address>

See https://ntfy.sh/docs/config/#web-push for details.
`, publicKey, privateKey)
return err
}
24 changes: 24 additions & 0 deletions cmd/webpush_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cmd

import (
"testing"

"github.com/stretchr/testify/require"
"github.com/urfave/cli/v2"
"heckel.io/ntfy/server"
)

func TestCLI_WebPush_GenerateKeys(t *testing.T) {
app, _, _, stderr := newTestApp()
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",
"webpush",
}
return app.Run(append(webPushArgs, args...))
}
Loading