Skip to content

Commit bf392ff

Browse files
authored
feat: add killswitch for notifications (coder#13794)
1 parent 542fff7 commit bf392ff

31 files changed

+774
-25
lines changed

coderd/apidoc/docs.go

Lines changed: 75 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: 65 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/audit/diff.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type Auditable interface {
2020
database.WorkspaceProxy |
2121
database.AuditOAuthConvertState |
2222
database.HealthSettings |
23+
database.NotificationsSettings |
2324
database.OAuth2ProviderApp |
2425
database.OAuth2ProviderAppSecret |
2526
database.CustomRole |

coderd/audit/request.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ func ResourceTarget[T Auditable](tgt T) string {
9999
return string(typed.ToLoginType)
100100
case database.HealthSettings:
101101
return "" // no target?
102+
case database.NotificationsSettings:
103+
return "" // no target?
102104
case database.OAuth2ProviderApp:
103105
return typed.Name
104106
case database.OAuth2ProviderAppSecret:
@@ -142,6 +144,9 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
142144
case database.HealthSettings:
143145
// Artificial ID for auditing purposes
144146
return typed.ID
147+
case database.NotificationsSettings:
148+
// Artificial ID for auditing purposes
149+
return typed.ID
145150
case database.OAuth2ProviderApp:
146151
return typed.ID
147152
case database.OAuth2ProviderAppSecret:
@@ -183,6 +188,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
183188
return database.ResourceTypeConvertLogin
184189
case database.HealthSettings:
185190
return database.ResourceTypeHealthSettings
191+
case database.NotificationsSettings:
192+
return database.ResourceTypeNotificationsSettings
186193
case database.OAuth2ProviderApp:
187194
return database.ResourceTypeOauth2ProviderApp
188195
case database.OAuth2ProviderAppSecret:
@@ -225,6 +232,9 @@ func ResourceRequiresOrgID[T Auditable]() bool {
225232
case database.HealthSettings:
226233
// Artificial ID for auditing purposes
227234
return false
235+
case database.NotificationsSettings:
236+
// Artificial ID for auditing purposes
237+
return false
228238
case database.OAuth2ProviderApp:
229239
return false
230240
case database.OAuth2ProviderAppSecret:

coderd/coderd.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,11 @@ func New(options *Options) *API {
12431243
})
12441244
})
12451245
})
1246+
r.Route("/notifications", func(r chi.Router) {
1247+
r.Use(apiKeyMiddleware)
1248+
r.Get("/settings", api.notificationsSettings)
1249+
r.Put("/settings", api.putNotificationsSettings)
1250+
})
12461251
})
12471252

12481253
if options.SwaggerEndpoint {

coderd/database/dbauthz/dbauthz.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,11 @@ func (q *querier) GetNotificationMessagesByStatus(ctx context.Context, arg datab
14791479
return q.db.GetNotificationMessagesByStatus(ctx, arg)
14801480
}
14811481

1482+
func (q *querier) GetNotificationsSettings(ctx context.Context) (string, error) {
1483+
// No authz checks
1484+
return q.db.GetNotificationsSettings(ctx)
1485+
}
1486+
14821487
func (q *querier) GetOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderApp, error) {
14831488
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOauth2App); err != nil {
14841489
return database.OAuth2ProviderApp{}, err
@@ -3687,6 +3692,13 @@ func (q *querier) UpsertLogoURL(ctx context.Context, value string) error {
36873692
return q.db.UpsertLogoURL(ctx, value)
36883693
}
36893694

3695+
func (q *querier) UpsertNotificationsSettings(ctx context.Context, value string) error {
3696+
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
3697+
return err
3698+
}
3699+
return q.db.UpsertNotificationsSettings(ctx, value)
3700+
}
3701+
36903702
func (q *querier) UpsertOAuthSigningKey(ctx context.Context, value string) error {
36913703
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
36923704
return err

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,6 +2350,12 @@ func (s *MethodTestSuite) TestSystemFunctions() {
23502350
s.Run("UpsertHealthSettings", s.Subtest(func(db database.Store, check *expects) {
23512351
check.Args("foo").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
23522352
}))
2353+
s.Run("GetNotificationsSettings", s.Subtest(func(db database.Store, check *expects) {
2354+
check.Args().Asserts()
2355+
}))
2356+
s.Run("UpsertNotificationsSettings", s.Subtest(func(db database.Store, check *expects) {
2357+
check.Args("foo").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
2358+
}))
23532359
s.Run("GetDeploymentWorkspaceAgentStats", s.Subtest(func(db database.Store, check *expects) {
23542360
check.Args(time.Time{}).Asserts()
23552361
}))

coderd/database/dbmem/dbmem.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ type data struct {
199199
lastUpdateCheck []byte
200200
announcementBanners []byte
201201
healthSettings []byte
202+
notificationsSettings []byte
202203
applicationName string
203204
logoURL string
204205
appSecurityKey string
@@ -2771,6 +2772,17 @@ func (q *FakeQuerier) GetNotificationMessagesByStatus(_ context.Context, arg dat
27712772
return out, nil
27722773
}
27732774

2775+
func (q *FakeQuerier) GetNotificationsSettings(_ context.Context) (string, error) {
2776+
q.mutex.RLock()
2777+
defer q.mutex.RUnlock()
2778+
2779+
if q.notificationsSettings == nil {
2780+
return "{}", nil
2781+
}
2782+
2783+
return string(q.notificationsSettings), nil
2784+
}
2785+
27742786
func (q *FakeQuerier) GetOAuth2ProviderAppByID(_ context.Context, id uuid.UUID) (database.OAuth2ProviderApp, error) {
27752787
q.mutex.Lock()
27762788
defer q.mutex.Unlock()
@@ -8668,8 +8680,8 @@ func (q *FakeQuerier) UpsertDefaultProxy(_ context.Context, arg database.UpsertD
86688680
}
86698681

86708682
func (q *FakeQuerier) UpsertHealthSettings(_ context.Context, data string) error {
8671-
q.mutex.RLock()
8672-
defer q.mutex.RUnlock()
8683+
q.mutex.Lock()
8684+
defer q.mutex.Unlock()
86738685

86748686
q.healthSettings = []byte(data)
86758687
return nil
@@ -8717,13 +8729,21 @@ func (q *FakeQuerier) UpsertLastUpdateCheck(_ context.Context, data string) erro
87178729
}
87188730

87198731
func (q *FakeQuerier) UpsertLogoURL(_ context.Context, data string) error {
8720-
q.mutex.RLock()
8721-
defer q.mutex.RUnlock()
8732+
q.mutex.Lock()
8733+
defer q.mutex.Unlock()
87228734

87238735
q.logoURL = data
87248736
return nil
87258737
}
87268738

8739+
func (q *FakeQuerier) UpsertNotificationsSettings(_ context.Context, data string) error {
8740+
q.mutex.Lock()
8741+
defer q.mutex.Unlock()
8742+
8743+
q.notificationsSettings = []byte(data)
8744+
return nil
8745+
}
8746+
87278747
func (q *FakeQuerier) UpsertOAuthSigningKey(_ context.Context, value string) error {
87288748
q.mutex.Lock()
87298749
defer q.mutex.Unlock()

coderd/database/dbmetrics/dbmetrics.go

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

0 commit comments

Comments
 (0)