10000 feat(coderd): add webpush package by johnstcn · Pull Request #17091 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

feat(coderd): add webpush package #17091

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

Merged
merged 40 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a980379
wip
kylecarbs Mar 17, 2025
bc02200
fix migration number
johnstcn Mar 25, 2025
2ecae9d
make fmt
johnstcn Mar 25, 2025
84e3ace
fix tests
johnstcn Mar 25, 2025
377eaab
add cli command to regenerate vapid keypair and remove existing subsc…
johnstcn Mar 25, 2025
982acef
remove dbauthz system usage
johnstcn Mar 25, 2025
d82073e
add test endpoint for push notifications
johnstcn Mar 25, 2025
fc59c70
make linter happy
johnstcn Mar 25, 2025
cbff3ca
test push notifications endpoint
johnstcn Mar 25, 2025
9e7e1dc
add deployment config for push notifications
johnstcn Mar 25, 2025
1315a46
add test for push notifications being enabled
johnstcn Mar 25, 2025
85db78c
rename migration
johnstcn Mar 25, 2025
892388a
skip vapid keypair test on non-postgres;
johnstcn Mar 25, 2025
e600b7d
fix some tests
johnstcn Mar 25, 2025
eef2038
hide subscribe button
johnstcn Mar 25, 2025
46f7519
conditionally hide push notification button
johnstcn Mar 25, 2025
4408090
Revert "conditionally hide push notification button"
johnstcn Mar 25, 2025
204ab4a
fix data race caused by webpush-go mutating msg []byte
johnstcn Mar 25, 2025
0535ed6
Remove deployment config for push notifications in favour of Experime…
johnstcn Mar 26, 2025
9f1f4f9
push notification -> webpush
johnstcn Mar 26, 2025
29bba04
notification -> webpush
johnstcn Mar 26, 2025
46c2cd8
move to webpush package
johnstcn Mar 26, 2025
960c5db
webpush: refactor notification test and send logic
johnstcn Mar 26, 2025
aa22161
move endpoints under webpush beside notifications
johnstcn Mar 26, 2025
57d84a9
skip apidocgen for push notification endpoints
johnstcn Mar 26, 2025
ef22b35
make webpush endpoints 404 if experiment not enabled
johnstcn Mar 26, 2025
9a1a605
auth on test notification endpoint
johnstcn Mar 26, 2025
e8b6083
fix ts
johnstcn Mar 26, 2025
5331f9c
ui fixes
johnstcn Mar 26, 2025
449f882
fixup migrations
johnstcn Mar 26, 2025
e5fd00e
fix check_unstaged.sh again
johnstcn Mar 26, 2025
bcf108a
make bee jenn
johnstcn Mar 26, 2025
eb7b102
address comments
johnstcn Mar 26, 2025
9b5ed09
address more comments + renaming
johnstcn Mar 26, 2025
c06558e
move out check_unstaged.sh changes to separate PR
johnstcn Mar 26, 2025
10ac9fb
remove site changes
johnstcn Mar 26, 2025
a114ddb
fixup! remove site changes
johnstcn Mar 26, 2025
ca72676
nits
johnstcn Mar 27, 2025
3b1dc70
make gen
johnstcn Mar 27, 2025
12808f1
gen
johnstcn Mar 27, 2025
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
Prev Previous commit
Next Next commit
move to webpush package
  • Loading branch information
johnstcn committed Mar 26, 2025
commit 46c2cd8c612ca88b5e3cee156cdeb4d4a565092e
8 changes: 4 additions & 4 deletions cli/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ import (
"github.com/coder/wgtunnel/tunnelsdk"

"github.com/coder/coder/v2/coderd/entitlements"
"github.com/coder/coder/v2/coderd/notifications/push"
"github.com/coder/coder/v2/coderd/notifications/reports"
"github.com/coder/coder/v2/coderd/runtimeconfig"
"github.com/coder/coder/v2/coderd/webpush"

"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/cli/clilog"
Expand Down Expand Up @@ -779,17 +779,17 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
// Manage push notifications.
experiments := coderd.ReadExperiments(options.Logger, options.DeploymentValues.Experiments.Value())
if experiments.Enabled(codersdk.ExperimentWebPush) {
webpusher, err := push.New(ctx, &options.Logger, options.Database)
webpusher, err := webpush.New(ctx, &options.Logger, options.Database)
if err != nil {
options.Logger.Error(ctx, "failed to create web push dispatcher", slog.Error(err))
options.Logger.Warn(ctx, "web push notifications will not work until the VAPID keys are regenerated")
webpusher = &push.NoopWebpusher{
webpusher = &webpush.NoopWebpusher{
Msg: "Web Push notifications are disabled due to a system error. Please contact your Coder administrator.",
}
}
options.WebpushDispatcher = webpusher
} else {
options.WebpushDispatcher = &push.NoopWebpusher{
options.WebpushDispatcher = &webpush.NoopWebpusher{
Msg: "Web Push notifications are an experimental feature and are disabled by default. Enable the 'web-push' experiment to use this feature.",
}
}
Expand Down
4 changes: 2 additions & 2 deletions cli/server_regenerate_vapid_keypair.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/awsiamrds"
"github.com/coder/coder/v2/coderd/notifications/push"
"github.com/coder/coder/v2/coderd/webpush"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
)
Expand Down Expand Up @@ -81,7 +81,7 @@ func (r *RootCmd) newRegenerateVapidKeypairCommand() *serpent.Command {
return xerrors.Errorf("VAPID keypair regeneration failed: %w", err)
}

if _, _, err := push.RegenerateVAPIDKeys(ctx, db); err != nil {
if _, _, err := webpush.RegenerateVAPIDKeys(ctx, db); err != nil {
return xerrors.Errorf("regenerate vapid keypair: %w", err)
}

Expand Down
12 changes: 6 additions & 6 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ import (
"github.com/coder/coder/v2/coderd/cryptokeys"
"github.com/coder/coder/v2/coderd/entitlements"
"github.com/coder/coder/v2/coderd/idpsync"
"github.com/coder/coder/v2/coderd/notifications/push"
"github.com/coder/coder/v2/coderd/runtimeconfig"
"github.com/coder/coder/v2/coderd/webpush"

agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/buildinfo"
Expand Down Expand Up @@ -263,7 +263,7 @@ type Options struct {
Clock quartz.Clock

// WebpushDispatcher is a way to send notifications over Web Push.
WebpushDispatcher push.Dispatcher
WebpushDispatcher webpush.Dispatcher
}

// @title Coder API
Expand Down Expand Up @@ -550,7 +550,7 @@ func New(options *Options) *API {
UserQuietHoursScheduleStore: options.UserQuietHoursScheduleStore,
AccessControlStore: options.AccessControlStore,
Experiments: experiments,
PushNotifier: options.WebpushDispatcher,
WebpushDispatcher: options.WebpushDispatcher,
healthCheckGroup: &singleflight.Group[string, *healthsdk.HealthcheckReport]{},
Acquirer: provisionerdserver.NewAcquirer(
ctx,
Expand Down Expand Up @@ -585,7 +585,7 @@ func New(options *Options) *API {
WorkspaceProxy: false,
UpgradeMessage: api.DeploymentValues.CLIUpgradeMessage.String(),
DeploymentID: api.DeploymentID,
WebPushPublicKey: api.PushNotifier.PublicKey(),
WebPushPublicKey: api.WebpushDispatcher.PublicKey(),
Telemetry: api.Telemetry.Enabled(),
}
api.SiteHandler = site.New(&site.Options{
Expand Down Expand Up @@ -1505,8 +1505,8 @@ type API struct {
TailnetCoordinator atomic.Pointer[tailnet.Coordinator]
NetworkTelemetryBatcher *tailnet.NetworkTelemetryBatcher
TailnetClientService *tailnet.ClientService
// PushNotifier is a way to send push notifications to users.
PushNotifier push.Dispatcher
// WebpushDispatcher is a way to send notifications to users via Web Push.
WebpushDispatcher webpush.Dispatcher
QuotaCommitter atomic.Pointer[proto.QuotaCommitter]
AppearanceFetcher atomic.Pointer[appearance.Fetcher]
// WorkspaceProxyHostsFn returns the hosts of healthy workspace proxies
Expand Down
12 changes: 6 additions & 6 deletions coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ import (
"github.com/coder/coder/v2/coderd/httpmw"
"github.com/coder/coder/v2/coderd/notifications"
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
"github.com/coder/coder/v2/coderd/notifications/push"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/coderd/runtimeconfig"
Expand All @@ -79,6 +78,7 @@ import (
"github.com/coder/coder/v2/coderd/unhanger"
"github.com/coder/coder/v2/coderd/updatecheck"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/coderd/webpush"
"github.com/coder/coder/v2/coderd/workspaceapps"
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
"github.com/coder/coder/v2/coderd/workspacestats"
Expand Down Expand Up @@ -162,7 +162,7 @@ type Options struct {
Logger *slog.Logger
StatsBatcher workspacestats.Batcher

PushNotifier push.Dispatcher
WebpushDispatcher webpush.Dispatcher
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
AllowWorkspaceRenames bool
NewTicker func(duration time.Duration) (<-chan time.Time, func())
Expand Down Expand Up @@ -282,13 +282,13 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
require.NoError(t, err, "insert a deployment id")
}

if options.PushNotifier == nil {
if options.WebpushDispatcher == nil {
// nolint:gocritic // Gets/sets VAPID keys.
pushNotifier, err := push.New(dbauthz.AsNotifier(context.Background()), options.Logger, options.Database)
pushNotifier, err := webpush.New(dbauthz.AsNotifier(context.Background()), options.Logger, options.Database)
if err != nil {
panic(xerrors.Errorf("failed to create push notifier: %w", err))
}
options.PushNotifier = pushNotifier
options.WebpushDispatcher = pushNotifier
}

if options.DeploymentValues == nil {
Expand Down Expand Up @@ -541,7 +541,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
TrialGenerator: options.TrialGenerator,
RefreshEntitlements: options.RefreshEntitlements,
TailnetCoordinator: options.Coordinator,
WebpushDispatcher: options.PushNotifier,
WebpushDispatcher: options.WebpushDispatcher,
BaseDERPMap: derpMap,
DERPMapUpdateFrequency: 150 * time.Millisecond,
CoordinatorResumeTokenProvider: options.CoordinatorResumeTokenProvider,
Expand Down
6 changes: 3 additions & 3 deletions coderd/notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ func (api *API) postUserWebpushSubscription(rw http.ResponseWriter, r *http.Requ
P256dh: req.P256DHKey,
},
}, &webpush.Options{
VAPIDPublicKey: api.PushNotifier.PublicKey(),
VAPIDPrivateKey: api.PushNotifier.PrivateKey(),
VAPIDPublicKey: api.WebpushDispatcher.PublicKey(),
VAPIDPrivateKey: api.WebpushDispatcher.PrivateKey(),
})
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Expand Down Expand Up @@ -448,7 +448,7 @@ func (api *API) postUserPushNotificationTest(rw http.ResponseWriter, r *http.Req
ctx := r.Context()
user := httpmw.UserParam(r)

if err := api.PushNotifier.Dispatch(ctx, user.ID, codersdk.WebpushMessage{
if err := api.WebpushDispatcher.Dispatch(ctx, user.ID, codersdk.WebpushMessage{
Title: "It's working!",
Body: "You've subscribed to push notifications.",
}); err != nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package push
package webpush

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package push_test
package webpush_test

import (
"context"
Expand All @@ -16,7 +16,7 @@ import (
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/notifications/push"
"github.com/coder/coder/v2/coderd/webpush"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
)
Expand Down Expand Up @@ -242,16 +242,16 @@ func TestPush(t *testing.T) {
})
}

// setupPushTest creates a common test setup for push notification tests
func setupPushTest(ctx context.Context, t *testing.T, handlerFunc func(w http.ResponseWriter, r *http.Request)) (push.Dispatcher, database.Store, string) {
// setupPushTest creates a common test setup for webpush notification tests
func setupPushTest(ctx context.Context, t *testing.T, handlerFunc func(w http.ResponseWriter, r *http.Request)) (webpush.Dispatcher, database.Store, string) {
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
db, _ := dbtestutil.NewDB(t)

server := httptest.NewServer(http.HandlerFunc(handlerFunc))
t.Cleanup(server.Close)

manager, err := push.New(ctx, &logger, db)
require.NoError(t, err, "Failed to create push manager")
manager, err := webpush.New(ctx, &logger, db)
require.NoError(t, err, "Failed to create webpush manager")

return manager, db, server.URL
}
0