Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit952821b

Browse files
committed
Basic implementation
Signed-off-by: Danny Kopping <danny@coder.com>
1 parent03673e5 commit952821b

File tree

4 files changed

+211
-0
lines changed

4 files changed

+211
-0
lines changed

‎coderd/coderd.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,10 @@ func New(options *Options) *API {
12521252
r.Route("/templates",func(r chi.Router) {
12531253
r.Get("/system",api.systemNotificationTemplates)
12541254
})
1255+
r.Route("/preferences",func(r chi.Router) {
1256+
r.Get("/",api.userNotificationPreferences)
1257+
r.Put("/",api.putUserNotificationPreferences)
1258+
})
12551259
})
12561260
})
12571261

‎coderd/notifications.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,90 @@ func (api *API) systemNotificationTemplates(rw http.ResponseWriter, r *http.Requ
141141
httpapi.Write(r.Context(),rw,http.StatusOK,out)
142142
}
143143

144+
// @Summary TODO Get notification templates pertaining to system events
145+
// @ID TODO system-notification-templates
146+
// @Security TODO CoderSessionToken
147+
// @Produce TODO json
148+
// @Tags TODO Notifications
149+
// @Success TODO 200 {array} codersdk.NotificationTemplate
150+
// @Router TODO /notifications/templates/system [get]
151+
func (api*API)userNotificationPreferences(rw http.ResponseWriter,r*http.Request) {
152+
ctx:=r.Context()
153+
key:=httpmw.APIKey(r)
154+
155+
if!api.Authorize(r,policy.ActionReadPersonal,rbac.ResourceNotificationPreference) {
156+
httpapi.Write(ctx,rw,http.StatusForbidden, codersdk.Response{
157+
Message:"Insufficient permissions to update notification preferences.",
158+
})
159+
return
160+
}
161+
162+
prefs,err:=api.Database.GetUserNotificationPreferences(ctx,key.UserID)
163+
iferr!=nil {
164+
httpapi.Write(r.Context(),rw,http.StatusInternalServerError, codersdk.Response{
165+
Message:"Failed to retrieve user notification preferences.",
166+
Detail:err.Error(),
167+
})
168+
return
169+
}
170+
171+
out:=convertNotificationPreferences(prefs)
172+
httpapi.Write(r.Context(),rw,http.StatusOK,out)
173+
}
174+
175+
// @Summary TODO Get notification templates pertaining to system events
176+
// @ID TODO system-notification-templates
177+
// @Security TODO CoderSessionToken
178+
// @Produce TODO json
179+
// @Tags TODO Notifications
180+
// @Success TODO 200 {array} codersdk.NotificationTemplate
181+
// @Router TODO /notifications/templates/system [put]
182+
func (api*API)putUserNotificationPreferences(rw http.ResponseWriter,r*http.Request) {
183+
ctx:=r.Context()
184+
185+
if!api.Authorize(r,policy.ActionUpdatePersonal,rbac.ResourceNotificationPreference) {
186+
httpapi.Write(ctx,rw,http.StatusForbidden, codersdk.Response{
187+
Message:"Insufficient permissions to update notification preferences.",
188+
})
189+
return
190+
}
191+
192+
varprefs codersdk.UpdateUserNotificationPreferences
193+
if!httpapi.Read(ctx,rw,r,&prefs) {
194+
return
195+
}
196+
197+
input:= database.UpdateUserNotificationPreferencesParams{
198+
NotificationTemplateIds:make([]uuid.UUID,0,len(prefs.TemplateDisabledMap)),
199+
Disableds:make([]bool,0,len(prefs.TemplateDisabledMap)),
200+
}
201+
fortmplID,disabled:=rangeprefs.TemplateDisabledMap {
202+
id,err:=uuid.Parse(tmplID)
203+
iferr!=nil {
204+
httpapi.Write(r.Context(),rw,http.StatusBadRequest, codersdk.Response{
205+
Message:"Unable to parse notification template UUID.",
206+
Detail:err.Error(),
207+
})
208+
return
209+
}
210+
211+
input.NotificationTemplateIds=append(input.NotificationTemplateIds,id)
212+
input.Disableds=append(input.Disableds,disabled)
213+
}
214+
215+
updated,err:=api.Database.UpdateUserNotificationPreferences(ctx,input)
216+
iferr!=nil {
217+
httpapi.Write(r.Context(),rw,http.StatusInternalServerError, codersdk.Response{
218+
Message:"Failed to update notifications preferences.",
219+
Detail:err.Error(),
220+
})
221+
return
222+
}
223+
224+
out:=convertNotificationPreferences(updated)
225+
httpapi.Write(r.Context(),rw,http.StatusOK,out)
226+
}
227+
144228
funcconvertNotificationTemplates(in []database.NotificationTemplate) (out []codersdk.NotificationTemplate) {
145229
for_,tmpl:=rangein {
146230
out=append(out, codersdk.NotificationTemplate{
@@ -157,3 +241,15 @@ func convertNotificationTemplates(in []database.NotificationTemplate) (out []cod
157241

158242
returnout
159243
}
244+
245+
funcconvertNotificationPreferences(in []database.NotificationPreference) (out []codersdk.NotificationPreference) {
246+
for_,pref:=rangein {
247+
out=append(out, codersdk.NotificationPreference{
248+
NotificationTemplateID:pref.NotificationTemplateID,
249+
Disabled:pref.Disabled,
250+
UpdatedAt:pref.UpdatedAt,
251+
})
252+
}
253+
254+
returnout
255+
}

‎coderd/notifications_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/stretchr/testify/require"
88

99
"github.com/coder/coder/v2/coderd/coderdtest"
10+
"github.com/coder/coder/v2/coderd/notifications"
1011
"github.com/coder/coder/v2/codersdk"
1112
"github.com/coder/coder/v2/testutil"
1213
)
@@ -103,3 +104,52 @@ func TestUpdateNotificationsSettings(t *testing.T) {
103104
require.Equal(t,expected.NotifierPaused,actual.NotifierPaused)
104105
})
105106
}
107+
108+
funcTestNotificationPreferences(t*testing.T) {
109+
t.Parallel()
110+
111+
t.Run("Initial state",func(t*testing.T) {
112+
t.Parallel()
113+
114+
ctx:=testutil.Context(t,testutil.WaitShort)
115+
116+
// Given: the first user in its initial state.
117+
client:=coderdtest.New(t,createOpts(t))
118+
_=coderdtest.CreateFirstUser(t,client)
119+
120+
// When: calling the API.
121+
prefs,err:=client.GetUserNotificationPreferences(ctx)
122+
require.NoError(t,err)
123+
124+
// Then: no preferences will be returned.
125+
require.Len(t,prefs,0)
126+
})
127+
128+
t.Run("Disable a template",func(t*testing.T) {
129+
t.Parallel()
130+
131+
ctx:=testutil.Context(t,testutil.WaitShort)
132+
template:=notifications.TemplateWorkspaceDormant
133+
134+
// Given: the first user with no set preferences.
135+
client:=coderdtest.New(t,createOpts(t))
136+
_=coderdtest.CreateFirstUser(t,client)
137+
138+
prefs,err:=client.GetUserNotificationPreferences(ctx)
139+
require.NoError(t,err)
140+
require.Len(t,prefs,0)
141+
142+
// When: calling the API.
143+
prefs,err=client.UpdateUserNotificationPreferences(ctx, codersdk.UpdateUserNotificationPreferences{
144+
TemplateDisabledMap:map[string]bool{
145+
template.String():true,
146+
},
147+
})
148+
require.NoError(t,err)
149+
150+
// Then: the single preference will be returned.
151+
require.Len(t,prefs,1)
152+
require.Equal(t,template,prefs[0].NotificationTemplateID)
153+
require.True(t,prefs[0].Disabled)
154+
})
155+
}

‎codersdk/notifications.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"net/http"
9+
"time"
910

1011
"github.com/google/uuid"
1112
"golang.org/x/xerrors"
@@ -26,6 +27,12 @@ type NotificationTemplate struct {
2627
Kindstring`json:"kind"`
2728
}
2829

30+
typeNotificationPreferencestruct {
31+
NotificationTemplateID uuid.UUID`json:"id" format:"uuid"`
32+
Disabledbool`json:"disabled"`
33+
UpdatedAt time.Time`json:"updated_at" format:"date-time"`
34+
}
35+
2936
// GetNotificationsSettings retrieves the notifications settings, which currently just describes whether all
3037
// notifications are paused from sending.
3138
func (c*Client)GetNotificationsSettings(ctx context.Context) (NotificationsSettings,error) {
@@ -105,6 +112,60 @@ func (c *Client) GetSystemNotificationTemplates(ctx context.Context) ([]Notifica
105112
returntemplates,nil
106113
}
107114

115+
// GetUserNotificationPreferences TODO
116+
func (c*Client)GetUserNotificationPreferences(ctx context.Context) ([]NotificationPreference,error) {
117+
res,err:=c.Request(ctx,http.MethodGet,"/api/v2/notifications/preferences",nil)
118+
iferr!=nil {
119+
returnnil,err
120+
}
121+
deferres.Body.Close()
122+
123+
ifres.StatusCode!=http.StatusOK {
124+
returnnil,ReadBodyAsError(res)
125+
}
126+
127+
varprefs []NotificationPreference
128+
body,err:=io.ReadAll(res.Body)
129+
iferr!=nil {
130+
returnnil,xerrors.Errorf("read response body: %w",err)
131+
}
132+
133+
iferr:=json.Unmarshal(body,&prefs);err!=nil {
134+
returnnil,xerrors.Errorf("unmarshal response body: %w",err)
135+
}
136+
137+
returnprefs,nil
138+
}
139+
140+
// UpdateUserNotificationPreferences TODO
141+
func (c*Client)UpdateUserNotificationPreferences(ctx context.Context,reqUpdateUserNotificationPreferences) ([]NotificationPreference,error) {
142+
res,err:=c.Request(ctx,http.MethodPut,"/api/v2/notifications/preferences",req)
143+
iferr!=nil {
144+
returnnil,err
145+
}
146+
deferres.Body.Close()
147+
148+
ifres.StatusCode!=http.StatusOK {
149+
returnnil,ReadBodyAsError(res)
150+
}
151+
152+
varprefs []NotificationPreference
153+
body,err:=io.ReadAll(res.Body)
154+
iferr!=nil {
155+
returnnil,xerrors.Errorf("read response body: %w",err)
156+
}
157+
158+
iferr:=json.Unmarshal(body,&prefs);err!=nil {
159+
returnnil,xerrors.Errorf("unmarshal response body: %w",err)
160+
}
161+
162+
returnprefs,nil
163+
}
164+
108165
typeUpdateNotificationTemplateMethodstruct {
109166
Methodstring`json:"method,omitempty" example:"webhook"`
110167
}
168+
169+
typeUpdateUserNotificationPreferencesstruct {
170+
TemplateDisabledMapmap[string]bool`json:"template_disabled_map"`
171+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp