From 97adb3d3e332f06fdd8b49fa9e548914240e6504 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Sat, 28 Mar 2020 16:27:45 +0000 Subject: [PATCH 01/21] Add webpush-go dependency --- go.mod | 3 ++- go.sum | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 54abb2292f80e..a422f18036e44 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 github.com/PuerkitoBio/goquery v1.5.0 github.com/RoaringBitmap/roaring v0.4.21 // indirect + github.com/SherClockHolmes/webpush-go v1.1.0 github.com/bgentry/speakeasy v0.1.0 // indirect github.com/blevesearch/bleve v0.8.1 github.com/blevesearch/blevex v0.0.0-20180227211930-4b158bb555a3 // indirect @@ -102,7 +103,7 @@ require ( github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 github.com/yuin/goldmark v1.1.25 go.etcd.io/bbolt v1.3.3 // indirect - golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 + golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 golang.org/x/net v0.0.0-20200301022130-244492dfa37a golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 diff --git a/go.sum b/go.sum index 552be8a7d0da5..26c731561f120 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8= github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= +github.com/SherClockHolmes/webpush-go v1.1.0 h1:WjWbwo0Bf1Cbd8Yr0myrpYYlcN7VvQz/TVmUTjxL35g= +github.com/SherClockHolmes/webpush-go v1.1.0/go.mod h1:Jbd13H6kOFZubRMAaEHQS+e0EpP/aSHtLKeo9gsyO5k= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755/go.mod h1:voKvFVpXBJxdIPeqjoJuLK+UVcRlo/JLjeToGxPYu68= @@ -608,6 +610,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -622,6 +625,8 @@ golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= From d8924ada34ed722ef9f1fbefa0a977af48658942 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Sat, 28 Mar 2020 16:28:24 +0000 Subject: [PATCH 02/21] Generate VAPID keys and add to settings automatically --- .../doc/advanced/config-cheat-sheet.en-us.md | 2 ++ modules/setting/setting.go | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 2306dd2281e61..c7575ff76cad3 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -289,6 +289,8 @@ set name for unique queues. Individual queues will default to - `INSTALL_LOCK`: **false**: Disallow access to the install page. - `SECRET_KEY`: **\**: Global secret key. This should be changed. +- `WEB_PUSH_PUBLIC_KEY`: **\**: VAPID key pair used for Web Push notifications +- `WEB_PUSH_PRIVATE_KEY`: **\**: VAPID key pair used for Web Push notifications - `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days. - `COOKIE_USERNAME`: **gitea\_awesome**: Name of the cookie used to store the current username. - `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 74f6da38d1564..0d3863febaaa3 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/user" + webpush "github.com/SherClockHolmes/webpush-go" shellquote "github.com/kballard/go-shellquote" version "github.com/mcuadros/go-version" "github.com/unknwon/cae/zip" @@ -147,6 +148,8 @@ var ( // Security settings InstallLock bool SecretKey string + WebPushPublicKey string + WebPushPrivateKey string LogInRememberDays int CookieUserName string CookieRememberName string @@ -816,6 +819,36 @@ func NewContext() { PasswordHashAlgo = sec.Key("PASSWORD_HASH_ALGO").MustString("pbkdf2") CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true) + WebPushPublicKey = sec.Key("WEB_PUSH_PUBLIC_KEY").String() + WebPushPrivateKey = sec.Key("WEB_PUSH_PRIVATE_KEY").String() + if WebPushPrivateKey == "" || WebPushPublicKey == "" { + log.Info("No VAPID (Web Push) keypair detected. Generating and saving to app.ini") + WebPushPrivateKey, WebPushPublicKey, err = webpush.GenerateVAPIDKeys() + if err != nil { + log.Fatal("error generating VAPID keypair: %v", err) + return + } + + cfg := ini.Empty() + if com.IsFile(CustomConf) { + if err := cfg.Append(CustomConf); err != nil { + log.Error("failed to load custom conf %s: %v", CustomConf, err) + return + } + } + cfg.Section("security").Key("WEB_PUSH_PUBLIC_KEY").SetValue(WebPushPublicKey) + cfg.Section("security").Key("WEB_PUSH_PRIVATE_KEY").SetValue(WebPushPrivateKey) + + if err := os.MkdirAll(filepath.Dir(CustomConf), os.ModePerm); err != nil { + log.Fatal("failed to create '%s': %v", CustomConf, err) + return + } + if err := cfg.SaveTo(CustomConf); err != nil { + log.Fatal("error saving generated VAPID keypair to custom config: %v", err) + return + } + } + InternalToken = loadInternalToken(sec) cfgdata := sec.Key("PASSWORD_COMPLEXITY").Strings(",") From 4d3753693d87c3b3413d45044f36177cecdd4a05 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Sat, 28 Mar 2020 16:47:11 +0000 Subject: [PATCH 03/21] Document requirement of service worker --- docs/content/doc/advanced/config-cheat-sheet.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index c7575ff76cad3..9d25aff559c72 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -131,7 +131,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. - `REACTIONS`: All available reactions. Allow users react with different emoji's. - `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used. - `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page. -- `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets. +- `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets and enable push notifications on supported browsers. ### UI - Admin (`ui.admin`) From bd138af510b1fc36424cd3d4ce00799dbf6ca201 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Sat, 28 Mar 2020 17:03:21 +0000 Subject: [PATCH 04/21] Provide public key to JS side --- modules/templates/helper.go | 3 +++ templates/base/head.tmpl | 1 + 2 files changed, 4 insertions(+) diff --git a/modules/templates/helper.go b/modules/templates/helper.go index b5b49874276db..27a9ca1201434 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -70,6 +70,9 @@ func NewFuncMap() []template.FuncMap { "AppDomain": func() string { return setting.Domain }, + "WebPushPublicKey": func() string { + return setting.WebPushPublicKey + }, "DisableGravatar": func() bool { return setting.DisableGravatar }, diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index e0765d59d30ed..9a7ea696fe889 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -86,6 +86,7 @@ window.config = { AppSubUrl: '{{AppSubUrl}}', StaticUrlPrefix: '{{StaticUrlPrefix}}', + WebPushPublicKey: '{{WebPushPublicKey}}', csrf: '{{.CsrfToken}}', HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}}, Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}}, From c92df3c8832d9de1d71429c7a062f667a53971e0 Mon Sep 17 00:00:00 2001 From: James Lakin Date: Sat, 28 Mar 2020 23:21:29 +0000 Subject: [PATCH 05/21] Add demo button to enable push subscriptions --- templates/base/head.tmpl | 2 + templates/user/notification/notification.tmpl | 10 ++++- web_src/js/features/pushnotifications.js | 45 +++++++++++++++++++ web_src/js/index.js | 2 + 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 web_src/js/features/pushnotifications.js diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 9a7ea696fe889..ae7874369d4f9 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -12,6 +12,7 @@ navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) { // Registration was successful console.info('ServiceWorker registration successful with scope: ', registration.scope); + window.serviceWorkerRegistration = registration; }, function(err) { // registration failed :( console.info('ServiceWorker registration failed: ', err); @@ -87,6 +88,7 @@ AppSubUrl: '{{AppSubUrl}}', StaticUrlPrefix: '{{StaticUrlPrefix}}', WebPushPublicKey: '{{WebPushPublicKey}}', + ServiceWorkerEnabled: {{if UseServiceWorker}}true{{else}}false{{end}}, csrf: '{{.CsrfToken}}', HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}}, Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}}, diff --git a/templates/user/notification/notification.tmpl b/templates/user/notification/notification.tmpl index c4f744a291738..27517bd608a46 100644 --- a/templates/user/notification/notification.tmpl +++ b/templates/user/notification/notification.tmpl @@ -2,7 +2,15 @@
-

{{.i18n.Tr "notification.notifications"}}

+
+
+

{{.i18n.Tr "notification.notifications"}}

+
+
+
+
+
+