Skip to content

Commit 11eacb8

Browse files
authored
feat: add notification dispatch methods endpoint (#14150)
1 parent 7bb1ee0 commit 11eacb8

File tree

9 files changed

+249
-0
lines changed

9 files changed

+249
-0
lines changed

coderd/apidoc/docs.go

Lines changed: 42 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: 38 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,7 @@ func New(options *Options) *API {
12581258
r.Route("/templates", func(r chi.Router) {
12591259
r.Get("/system", api.systemNotificationTemplates)
12601260
})
1261+
r.Get("/dispatch-methods", api.notificationDispatchMethods)
12611262
})
12621263
})
12631264

coderd/notifications.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,25 @@ func (api *API) systemNotificationTemplates(rw http.ResponseWriter, r *http.Requ
144144
httpapi.Write(r.Context(), rw, http.StatusOK, out)
145145
}
146146

147+
// @Summary Get notification dispatch methods
148+
// @ID get-notification-dispatch-methods
149+
// @Security CoderSessionToken
150+
// @Produce json
151+
// @Tags Notifications
152+
// @Success 200 {array} codersdk.NotificationMethodsResponse
153+
// @Router /notifications/dispatch-methods [get]
154+
func (api *API) notificationDispatchMethods(rw http.ResponseWriter, r *http.Request) {
155+
var methods []string
156+
for _, nm := range database.AllNotificationMethodValues() {
157+
methods = append(methods, string(nm))
158+
}
159+
160+
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.NotificationMethodsResponse{
161+
AvailableNotificationMethods: methods,
162+
DefaultNotificationMethod: api.DeploymentValues.Notifications.Method.Value(),
163+
})
164+
}
165+
147166
// @Summary Get user notification preferences
148167
// @ID get-user-notification-preferences
149168
// @Security CoderSessionToken

coderd/notifications_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ import (
55
"testing"
66

77
"github.com/stretchr/testify/require"
8+
"golang.org/x/exp/slices"
9+
10+
"github.com/coder/serpent"
811

912
"github.com/coder/coder/v2/coderd/coderdtest"
13+
"github.com/coder/coder/v2/coderd/database"
1014
"github.com/coder/coder/v2/coderd/notifications"
1115
"github.com/coder/coder/v2/codersdk"
1216
"github.com/coder/coder/v2/testutil"
@@ -265,3 +269,52 @@ func TestNotificationPreferences(t *testing.T) {
265269
require.True(t, found, "dormant notification preference was not found")
266270
})
267271
}
272+
273+
func TestNotificationDispatchMethods(t *testing.T) {
274+
t.Parallel()
275+
276+
defaultOpts := createOpts(t)
277+
webhookOpts := createOpts(t)
278+
webhookOpts.DeploymentValues.Notifications.Method = serpent.String(database.NotificationMethodWebhook)
279+
280+
tests := []struct {
281+
name string
282+
opts *coderdtest.Options
283+
expectedDefault string
284+
}{
285+
{
286+
name: "default",
287+
opts: defaultOpts,
288+
expectedDefault: string(database.NotificationMethodSmtp),
289+
},
290+
{
291+
name: "non-default",
292+
opts: webhookOpts,
293+
expectedDefault: string(database.NotificationMethodWebhook),
294+
},
295+
}
296+
297+
var allMethods []string
298+
for _, nm := range database.AllNotificationMethodValues() {
299+
allMethods = append(allMethods, string(nm))
300+
}
301+
slices.Sort(allMethods)
302+
303+
// nolint:paralleltest // Not since Go v1.22.
304+
for _, tc := range tests {
305+
t.Run(tc.name, func(t *testing.T) {
306+
t.Parallel()
307+
308+
ctx := testutil.Context(t, testutil.WaitShort)
309+
api := coderdtest.New(t, tc.opts)
310+
_ = coderdtest.CreateFirstUser(t, api)
311+
312+
resp, err := api.GetNotificationDispatchMethods(ctx)
313+
require.NoError(t, err)
314+
315+
slices.Sort(resp.AvailableNotificationMethods)
316+
require.EqualValues(t, resp.AvailableNotificationMethods, allMethods)
317+
require.Equal(t, tc.expectedDefault, resp.DefaultNotificationMethod)
318+
})
319+
}
320+
}

codersdk/notifications.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ type NotificationTemplate struct {
2727
Kind string `json:"kind"`
2828
}
2929

30+
type NotificationMethodsResponse struct {
31+
AvailableNotificationMethods []string `json:"available"`
32+
DefaultNotificationMethod string `json:"default"`
33+
}
34+
3035
type NotificationPreference struct {
3136
NotificationTemplateID uuid.UUID `json:"id" format:"uuid"`
3237
Disabled bool `json:"disabled"`
@@ -162,6 +167,31 @@ func (c *Client) UpdateUserNotificationPreferences(ctx context.Context, userID u
162167
return prefs, nil
163168
}
164169

170+
// GetNotificationDispatchMethods the available and default notification dispatch methods.
171+
func (c *Client) GetNotificationDispatchMethods(ctx context.Context) (NotificationMethodsResponse, error) {
172+
res, err := c.Request(ctx, http.MethodGet, "/api/v2/notifications/dispatch-methods", nil)
173+
if err != nil {
174+
return NotificationMethodsResponse{}, err
175+
}
176+
defer res.Body.Close()
177+
178+
if res.StatusCode != http.StatusOK {
179+
return NotificationMethodsResponse{}, ReadBodyAsError(res)
180+
}
181+
182+
var resp NotificationMethodsResponse
183+
body, err := io.ReadAll(res.Body)
184+
if err != nil {
185+
return NotificationMethodsResponse{}, xerrors.Errorf("read response body: %w", err)
186+
}
187+
188+
if err := json.Unmarshal(body, &resp); err != nil {
189+
return NotificationMethodsResponse{}, xerrors.Errorf("unmarshal response body: %w", err)
190+
}
191+
192+
return resp, nil
193+
}
194+
165195
type UpdateNotificationTemplateMethod struct {
166196
Method string `json:"method,omitempty" example:"webhook"`
167197
}

docs/api/notifications.md

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

docs/api/schemas.md

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

site/src/api/typesGenerated.ts

Lines changed: 6 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)