Skip to content

Commit deb97fc

Browse files
kylecarbsjohnstcn
authored andcommitted
wip
1 parent 811097e commit deb97fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1639
-23
lines changed

cli/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import (
6262
"github.com/coder/wgtunnel/tunnelsdk"
6363

6464
"github.com/coder/coder/v2/coderd/entitlements"
65+
"github.com/coder/coder/v2/coderd/notifications/push"
6566
"github.com/coder/coder/v2/coderd/notifications/reports"
6667
"github.com/coder/coder/v2/coderd/runtimeconfig"
6768

@@ -775,6 +776,12 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
775776
return xerrors.Errorf("set deployment id: %w", err)
776777
}
777778

779+
pushNotifier, err := push.New(ctx, &options.Logger, options.Database)
780+
if err != nil {
781+
return xerrors.Errorf("failed to create push notifier: %w", err)
782+
}
783+
options.PushNotifier = pushNotifier
784+
778785
githubOAuth2ConfigParams, err := getGithubOAuth2ConfigParams(ctx, options.Database, vals)
779786
if err != nil {
780787
return xerrors.Errorf("get github oauth2 config params: %w", err)

coderd/apidoc/docs.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"github.com/coder/coder/v2/coderd/cryptokeys"
4545
"github.com/coder/coder/v2/coderd/entitlements"
4646
"github.com/coder/coder/v2/coderd/idpsync"
47+
"github.com/coder/coder/v2/coderd/notifications/push"
4748
"github.com/coder/coder/v2/coderd/runtimeconfig"
4849

4950
agentproto "github.com/coder/coder/v2/agent/proto"
@@ -260,6 +261,9 @@ type Options struct {
260261
AppEncryptionKeyCache cryptokeys.EncryptionKeycache
261262
OIDCConvertKeyCache cryptokeys.SigningKeycache
262263
Clock quartz.Clock
264+
265+
// PushNotifier is a way to send push notifications to users.
266+
PushNotifier *push.Notifier
263267
}
264268

265269
// @title Coder API
@@ -546,6 +550,7 @@ func New(options *Options) *API {
546550
UserQuietHoursScheduleStore: options.UserQuietHoursScheduleStore,
547551
AccessControlStore: options.AccessControlStore,
548552
Experiments: experiments,
553+
PushNotifier: options.PushNotifier,
549554
healthCheckGroup: &singleflight.Group[string, *healthsdk.HealthcheckReport]{},
550555
Acquirer: provisionerdserver.NewAcquirer(
551556
ctx,
@@ -572,15 +577,16 @@ func New(options *Options) *API {
572577
api.AppearanceFetcher.Store(&f)
573578
api.PortSharer.Store(&portsharing.DefaultPortSharer)
574579
buildInfo := codersdk.BuildInfoResponse{
575-
ExternalURL: buildinfo.ExternalURL(),
576-
Version: buildinfo.Version(),
577-
AgentAPIVersion: AgentAPIVersionREST,
578-
ProvisionerAPIVersion: proto.CurrentVersion.String(),
579-
DashboardURL: api.AccessURL.String(),
580-
WorkspaceProxy: false,
581-
UpgradeMessage: api.DeploymentValues.CLIUpgradeMessage.String(),
582-
DeploymentID: api.DeploymentID,
583-
Telemetry: api.Telemetry.Enabled(),
580+
ExternalURL: buildinfo.ExternalURL(),
581+
Version: buildinfo.Version(),
582+
AgentAPIVersion: AgentAPIVersionREST,
583+
ProvisionerAPIVersion: proto.CurrentVersion.String(),
584+
DashboardURL: api.AccessURL.String(),
585+
WorkspaceProxy: false,
586+
UpgradeMessage: api.DeploymentValues.CLIUpgradeMessage.String(),
587+
DeploymentID: api.DeploymentID,
588+
PushNotificationsPublicKey: api.PushNotifier.VAPIDPublicKey,
589+
Telemetry: api.Telemetry.Enabled(),
584590
}
585591
api.SiteHandler = site.New(&site.Options{
586592
BinFS: binFS,
@@ -1194,6 +1200,10 @@ func New(options *Options) *API {
11941200
r.Get("/", api.userNotificationPreferences)
11951201
r.Put("/", api.putUserNotificationPreferences)
11961202
})
1203+
r.Route("/push", func(r chi.Router) {
1204+
r.Post("/subscription", api.postUserPushNotificationSubscription)
1205+
r.Delete("/subscription", api.deleteUserPushNotificationSubscription)
1206+
})
11971207
})
11981208
})
11991209
})
@@ -1494,8 +1504,10 @@ type API struct {
14941504
TailnetCoordinator atomic.Pointer[tailnet.Coordinator]
14951505
NetworkTelemetryBatcher *tailnet.NetworkTelemetryBatcher
14961506
TailnetClientService *tailnet.ClientService
1497-
QuotaCommitter atomic.Pointer[proto.QuotaCommitter]
1498-
AppearanceFetcher atomic.Pointer[appearance.Fetcher]
1507+
// PushNotifier is a way to send push notifications to users.
1508+
PushNotifier *push.Notifier
1509+
QuotaCommitter atomic.Pointer[proto.QuotaCommitter]
1510+
AppearanceFetcher atomic.Pointer[appearance.Fetcher]
14991511
// WorkspaceProxyHostsFn returns the hosts of healthy workspace proxies
15001512
// for header reasons.
15011513
WorkspaceProxyHostsFn atomic.Pointer[func() []string]

coderd/coderdtest/coderdtest.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import (
7070
"github.com/coder/coder/v2/coderd/httpmw"
7171
"github.com/coder/coder/v2/coderd/notifications"
7272
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
73+
"github.com/coder/coder/v2/coderd/notifications/push"
7374
"github.com/coder/coder/v2/coderd/rbac"
7475
"github.com/coder/coder/v2/coderd/rbac/policy"
7576
"github.com/coder/coder/v2/coderd/runtimeconfig"
@@ -161,6 +162,7 @@ type Options struct {
161162
Logger *slog.Logger
162163
StatsBatcher workspacestats.Batcher
163164

165+
PushNotifier *push.Notifier
164166
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
165167
AllowWorkspaceRenames bool
166168
NewTicker func(duration time.Duration) (<-chan time.Time, func())
@@ -280,6 +282,15 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
280282
require.NoError(t, err, "insert a deployment id")
281283
}
282284

285+
if options.PushNotifier == nil {
286+
// nolint:gocritic // Gets/sets VAPID keys.
287+
pushNotifier, err := push.New(dbauthz.AsSystemRestricted(context.Background()), options.Logger, options.Database)
288+
if err != nil {
289+
panic(xerrors.Errorf("failed to create push notifier: %w", err))
290+
}
291+
options.PushNotifier = pushNotifier
292+
}
293+
283294
if options.DeploymentValues == nil {
284295
options.DeploymentValues = DeploymentValues(t)
285296
}
@@ -530,6 +541,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
530541
TrialGenerator: options.TrialGenerator,
531542
RefreshEntitlements: options.RefreshEntitlements,
532543
TailnetCoordinator: options.Coordinator,
544+
PushNotifier: options.PushNotifier,
533545
BaseDERPMap: derpMap,
534546
DERPMapUpdateFrequency: 150 * time.Millisecond,
535547
CoordinatorResumeTokenProvider: options.CoordinatorResumeTokenProvider,

coderd/database/dbauthz/dbauthz.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,20 @@ func (q *querier) DeleteLicense(ctx context.Context, id int32) (int32, error) {
12451245
return id, nil
12461246
}
12471247

1248+
func (q *querier) DeleteNotificationPushSubscriptionByEndpoint(ctx context.Context, arg database.DeleteNotificationPushSubscriptionByEndpointParams) error {
1249+
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceNotificationPushSubscription.WithOwner(arg.UserID.String())); err != nil {
1250+
return err
1251+
}
1252+
return q.db.DeleteNotificationPushSubscriptionByEndpoint(ctx, arg)
1253+
}
1254+
1255+
func (q *querier) DeleteNotificationPushSubscriptions(ctx context.Context, ids []uuid.UUID) error {
1256+
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
1257+
return err
1258+
}
1259+
return q.db.DeleteNotificationPushSubscriptions(ctx, ids)
1260+
}
1261+
12481262
func (q *querier) DeleteOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) error {
12491263
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceOauth2App); err != nil {
12501264
return err
@@ -1867,6 +1881,13 @@ func (q *querier) GetNotificationMessagesByStatus(ctx context.Context, arg datab
18671881
return q.db.GetNotificationMessagesByStatus(ctx, arg)
18681882
}
18691883

1884+
func (q *querier) GetNotificationPushSubscriptionsByUserID(ctx context.Context, userID uuid.UUID) ([]database.NotificationPushSubscription, error) {
1885+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceNotificationPushSubscription.WithOwner(userID.String())); err != nil {
1886+
return nil, err
1887+
}
1888+
return q.db.GetNotificationPushSubscriptionsByUserID(ctx, userID)
1889+
}
1890+
18701891
func (q *querier) GetNotificationReportGeneratorLogByTemplate(ctx context.Context, arg uuid.UUID) (database.NotificationReportGeneratorLog, error) {
18711892
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
18721893
return database.NotificationReportGeneratorLog{}, err
@@ -1891,6 +1912,13 @@ func (q *querier) GetNotificationTemplatesByKind(ctx context.Context, kind datab
18911912
return nil, sql.ErrNoRows
18921913
}
18931914

1915+
func (q *querier) GetNotificationVAPIDKeys(ctx context.Context) (database.GetNotificationVAPIDKeysRow, error) {
1916+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceDeploymentConfig); err != nil {
1917+
return database.GetNotificationVAPIDKeysRow{}, err
1918+
}
1919+
return q.db.GetNotificationVAPIDKeys(ctx)
1920+
}
1921+
18941922
func (q *querier) GetNotificationsSettings(ctx context.Context) (string, error) {
18951923
// No authz checks
18961924
return q.db.GetNotificationsSettings(ctx)
@@ -3201,6 +3229,13 @@ func (q *querier) InsertMissingGroups(ctx context.Context, arg database.InsertMi
32013229
return q.db.InsertMissingGroups(ctx, arg)
32023230
}
32033231

3232+
func (q *querier) InsertNotificationPushSubscription(ctx context.Context, arg database.InsertNotificationPushSubscriptionParams) (database.NotificationPushSubscription, error) {
3233+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceNotificationPushSubscription.WithOwner(arg.UserID.String())); err != nil {
3234+
return database.NotificationPushSubscription{}, err
3235+
}
3236+
return q.db.InsertNotificationPushSubscription(ctx, arg)
3237+
}
3238+
32043239
func (q *querier) InsertOAuth2ProviderApp(ctx context.Context, arg database.InsertOAuth2ProviderAppParams) (database.OAuth2ProviderApp, error) {
32053240
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOauth2App); err != nil {
32063241
return database.OAuth2ProviderApp{}, err
@@ -4575,6 +4610,13 @@ func (q *querier) UpsertNotificationReportGeneratorLog(ctx context.Context, arg
45754610
return q.db.UpsertNotificationReportGeneratorLog(ctx, arg)
45764611
}
45774612

4613+
func (q *querier) UpsertNotificationVAPIDKeys(ctx context.Context, arg database.UpsertNotificationVAPIDKeysParams) error {
4614+
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
4615+
return err
4616+
}
4617+
return q.db.UpsertNotificationVAPIDKeys(ctx, arg)
4618+
}
4619+
45784620
func (q *querier) UpsertNotificationsSettings(ctx context.Context, value string) error {
45794621
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
45804622
return err

0 commit comments

Comments
 (0)