Skip to content

Commit 1650818

Browse files
committed
Template method update tests
Signed-off-by: Danny Kopping <danny@coder.com>
1 parent f7a102e commit 1650818

File tree

7 files changed

+347
-26
lines changed

7 files changed

+347
-26
lines changed

coderd/coderd.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,9 +1243,13 @@ func New(options *Options) *API {
12431243
})
12441244
})
12451245
r.Route("/notifications", func(r chi.Router) {
1246-
r.Use(apiKeyMiddleware)
1246+
r.Use(
1247+
apiKeyMiddleware,
1248+
httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentNotifications),
1249+
)
12471250
r.Get("/settings", api.notificationsSettings)
12481251
r.Put("/settings", api.putNotificationsSettings)
1252+
r.Get("/templates/system", api.getSystemNotificationTemplates)
12491253
})
12501254
})
12511255

coderd/notifications.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,44 @@ func (api *API) putNotificationsSettings(rw http.ResponseWriter, r *http.Request
120120

121121
httpapi.Write(r.Context(), rw, http.StatusOK, settings)
122122
}
123+
124+
func (api *API) getSystemNotificationTemplates(rw http.ResponseWriter, r *http.Request) {
125+
ctx := r.Context()
126+
127+
templates, err := api.Database.GetSystemNotificationTemplates(ctx)
128+
if err != nil {
129+
httpapi.Write(r.Context(), rw, http.StatusInternalServerError, codersdk.Response{
130+
Message: "Failed to retrieve system notifications templates.",
131+
Detail: err.Error(),
132+
})
133+
return
134+
}
135+
136+
out, err := convertNotificationTemplates(templates)
137+
if err != nil {
138+
httpapi.Write(r.Context(), rw, http.StatusInternalServerError, codersdk.Response{
139+
Message: "Failed to convert retrieved notifications templates to marshalable form.",
140+
Detail: err.Error(),
141+
})
142+
return
143+
}
144+
145+
httpapi.Write(r.Context(), rw, http.StatusOK, out)
146+
}
147+
148+
func convertNotificationTemplates(in []database.NotificationTemplate) (out []codersdk.NotificationTemplate, err error) {
149+
for _, tmpl := range in {
150+
out = append(out, codersdk.NotificationTemplate{
151+
ID: tmpl.ID,
152+
Name: tmpl.Name,
153+
TitleTemplate: tmpl.TitleTemplate,
154+
BodyTemplate: tmpl.BodyTemplate,
155+
Actions: tmpl.Actions,
156+
Group: tmpl.Group.String,
157+
Method: string(tmpl.Method.NotificationMethod),
158+
IsSystem: tmpl.IsSystem,
159+
})
160+
}
161+
162+
return out, nil
163+
}

coderd/notifications/methods.go

Lines changed: 0 additions & 10 deletions
This file was deleted.

codersdk/notifications.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,29 @@ package codersdk
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
7+
"io"
68
"net/http"
9+
10+
"github.com/google/uuid"
11+
"golang.org/x/xerrors"
712
)
813

914
type NotificationsSettings struct {
1015
NotifierPaused bool `json:"notifier_paused"`
1116
}
1217

18+
type NotificationTemplate struct {
19+
ID uuid.UUID `json:"id" format:"uuid"`
20+
Name string `json:"name"`
21+
TitleTemplate string `json:"title_template"`
22+
BodyTemplate string `json:"body_template"`
23+
Actions []byte `json:"actions"`
24+
Group string `json:"group"`
25+
Method string `json:"method"`
26+
IsSystem bool `json:"is_system"`
27+
}
28+
1329
func (c *Client) GetNotificationsSettings(ctx context.Context) (NotificationsSettings, error) {
1430
res, err := c.Request(ctx, http.MethodGet, "/api/v2/notifications/settings", nil)
1531
if err != nil {
@@ -39,6 +55,49 @@ func (c *Client) PutNotificationsSettings(ctx context.Context, settings Notifica
3955
return nil
4056
}
4157

58+
func (c *Client) UpdateNotificationTemplateMethod(ctx context.Context, notificationTemplateId uuid.UUID, method string) error {
59+
res, err := c.Request(ctx, http.MethodPost,
60+
fmt.Sprintf("/api/v2/notifications/templates/%s/method", notificationTemplateId),
61+
UpdateNotificationTemplateMethod{Method: method},
62+
)
63+
if err != nil {
64+
return err
65+
}
66+
defer res.Body.Close()
67+
68+
if res.StatusCode == http.StatusNotModified {
69+
return nil
70+
}
71+
if res.StatusCode != http.StatusOK {
72+
return ReadBodyAsError(res)
73+
}
74+
return nil
75+
}
76+
77+
func (c *Client) GetSystemNotificationTemplates(ctx context.Context) ([]NotificationTemplate, error) {
78+
res, err := c.Request(ctx, http.MethodGet, "/api/v2/notifications/templates/system", nil)
79+
if err != nil {
80+
return nil, err
81+
}
82+
defer res.Body.Close()
83+
84+
if res.StatusCode != http.StatusOK {
85+
return nil, ReadBodyAsError(res)
86+
}
87+
88+
var templates []NotificationTemplate
89+
body, err := io.ReadAll(res.Body)
90+
if err != nil {
91+
return nil, xerrors.Errorf("read response body: %w", err)
92+
}
93+
94+
if err := json.Unmarshal(body, &templates); err != nil {
95+
return nil, xerrors.Errorf("unmarshal response body: %w", err)
96+
}
97+
98+
return templates, nil
99+
}
100+
42101
type UpdateNotificationTemplateMethod struct {
43102
Method string `json:"method,omitempty" example:"webhook"`
44103
}

enterprise/coderd/coderd.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -387,15 +387,11 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
387387
r.Post("/jfrog/xray-scan", api.postJFrogXrayScan)
388388
r.Get("/jfrog/xray-scan", api.jFrogXrayScan)
389389
})
390-
r.Route("/notifications/templates", func(r chi.Router) {
391-
r.Use(apiKeyMiddleware)
392-
r.Route("/{notification_template}", func(r chi.Router) {
393-
r.Use(
394-
httpmw.ExtractNotificationTemplateParam(options.Database),
395-
)
396-
r.Post("/method", api.updateNotificationTemplateMethod)
397-
})
398-
})
390+
r.With(
391+
apiKeyMiddleware,
392+
httpmw.RequireExperiment(api.AGPL.Experiments, codersdk.ExperimentNotifications),
393+
httpmw.ExtractNotificationTemplateParam(options.Database),
394+
).Post("/notifications/templates/{notification_template}/method", api.updateNotificationTemplateMethod)
399395
})
400396

401397
if len(options.SCIMAPIKey) != 0 {

enterprise/coderd/notifications.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/coder/coder/v2/coderd/database"
1212
"github.com/coder/coder/v2/coderd/httpapi"
1313
"github.com/coder/coder/v2/coderd/httpmw"
14-
"github.com/coder/coder/v2/coderd/notifications"
1514
"github.com/coder/coder/v2/codersdk"
1615
)
1716

@@ -23,9 +22,7 @@ import (
2322
// @Success 200
2423
// @Router /notifications/templates/{notification_template}/method [post]
2524
func (api *API) updateNotificationTemplateMethod(rw http.ResponseWriter, r *http.Request) {
26-
// TODO: authorization (admin/template admin)
27-
// auth := httpmw.UserAuthorization(r)
28-
25+
// TODO: authorization (restrict to admin/template admin?)
2926
var (
3027
ctx = r.Context()
3128
template = httpmw.NotificationTemplateParam(r)
@@ -44,14 +41,20 @@ func (api *API) updateNotificationTemplateMethod(rw http.ResponseWriter, r *http
4441
}
4542

4643
var nm database.NullNotificationMethod
47-
if err := nm.Scan(req.Method); err != nil || !nm.Valid || string(nm.NotificationMethod) == "" {
44+
if err := nm.Scan(req.Method); err != nil || !nm.Valid || !nm.NotificationMethod.Valid() {
45+
vals := database.AllNotificationMethodValues()
46+
acceptable := make([]string, len(vals))
47+
for i, v := range vals {
48+
acceptable[i] = string(v)
49+
}
50+
4851
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
4952
Message: "Invalid request to update notification template method",
5053
Validations: []codersdk.ValidationError{
5154
{
5255
Field: "method",
5356
Detail: fmt.Sprintf("%q is not a valid method; %s are the available options",
54-
req.Method, strings.Join(notifications.ValidNotificationMethods(), ", "),
57+
req.Method, strings.Join(acceptable, ", "),
5558
),
5659
},
5760
},

0 commit comments

Comments
 (0)