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

Commit327ec0d

Browse files
committed
fix: block system users from sending custom notifications
1 parent2ab1c4d commit327ec0d

File tree

7 files changed

+127
-11
lines changed

7 files changed

+127
-11
lines changed

‎cli/notifications_test.go‎

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import (
1010
"github.com/stretchr/testify/assert"
1111
"github.com/stretchr/testify/require"
1212

13+
"github.com/coder/coder/v2/coderd/database"
14+
"github.com/coder/coder/v2/coderd/database/dbgen"
15+
1316
"github.com/coder/coder/v2/cli/clitest"
1417
"github.com/coder/coder/v2/coderd/coderdtest"
1518
"github.com/coder/coder/v2/coderd/notifications"
@@ -175,11 +178,12 @@ func TestCustomNotifications(t *testing.T) {
175178

176179
notifyEnq:=&notificationstest.FakeEnqueuer{}
177180

178-
// Given: A member user
179181
ownerClient:=coderdtest.New(t,&coderdtest.Options{
180182
DeploymentValues:coderdtest.DeploymentValues(t),
181183
NotificationsEnqueuer:notifyEnq,
182184
})
185+
186+
// Given: A member user
183187
ownerUser:=coderdtest.CreateFirstUser(t,ownerClient)
184188
memberClient,_:=coderdtest.CreateAnotherUser(t,ownerClient,ownerUser.OrganizationID)
185189

@@ -192,23 +196,58 @@ func TestCustomNotifications(t *testing.T) {
192196
varsdkError*codersdk.Error
193197
require.Error(t,err)
194198
require.ErrorAsf(t,err,&sdkError,"error should be of type *codersdk.Error")
195-
assert.Equal(t,http.StatusBadRequest,sdkError.StatusCode())
199+
require.Equal(t,http.StatusBadRequest,sdkError.StatusCode())
196200
require.Equal(t,"Invalid request body",sdkError.Message)
197201

198202
sent:=notifyEnq.Sent(notificationstest.WithTemplateID(notifications.TemplateTestNotification))
199203
require.Len(t,sent,0)
200204
})
201205

206+
t.Run("SystemUserNotAllowed",func(t*testing.T) {
207+
t.Parallel()
208+
209+
notifyEnq:=&notificationstest.FakeEnqueuer{}
210+
211+
ownerClient,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{
212+
DeploymentValues:coderdtest.DeploymentValues(t),
213+
NotificationsEnqueuer:notifyEnq,
214+
})
215+
216+
// Given: A system user (prebuilds system user)
217+
_,token:=dbgen.APIKey(t,db, database.APIKey{
218+
UserID:database.PrebuildsSystemUserID,
219+
LoginType:database.LoginTypeNone,
220+
})
221+
systemUserClient:=codersdk.New(ownerClient.URL)
222+
systemUserClient.SetSessionToken(token)
223+
224+
// When: The system user attempts to send a custom notification
225+
inv,root:=clitest.New(t,"notifications","custom","Custom Title","Custom Message")
226+
clitest.SetupConfig(t,systemUserClient,root)
227+
228+
// Then: an error is expected with no notifications sent
229+
err:=inv.Run()
230+
varsdkError*codersdk.Error
231+
require.Error(t,err)
232+
require.ErrorAsf(t,err,&sdkError,"error should be of type *codersdk.Error")
233+
require.Equal(t,http.StatusForbidden,sdkError.StatusCode())
234+
require.Equal(t,"Forbidden",sdkError.Message)
235+
236+
sent:=notifyEnq.Sent(notificationstest.WithTemplateID(notifications.TemplateTestNotification))
237+
require.Len(t,sent,0)
238+
})
239+
202240
t.Run("Success",func(t*testing.T) {
203241
t.Parallel()
204242

205243
notifyEnq:=&notificationstest.FakeEnqueuer{}
206244

207-
// Given: A member user
208245
ownerClient:=coderdtest.New(t,&coderdtest.Options{
209246
DeploymentValues:coderdtest.DeploymentValues(t),
210247
NotificationsEnqueuer:notifyEnq,
211248
})
249+
250+
// Given: A member user
212251
ownerUser:=coderdtest.CreateFirstUser(t,ownerClient)
213252
memberClient,memberUser:=coderdtest.CreateAnotherUser(t,ownerClient,ownerUser.OrganizationID)
214253

‎coderd/apidoc/docs.go‎

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

‎coderd/apidoc/swagger.json‎

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

‎coderd/database/modelmethods.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,10 @@ func (u User) RBACObject() rbac.Object {
376376
returnrbac.ResourceUserObject(u.ID)
377377
}
378378

379+
func (uUser)IsSystemUser()bool {
380+
returnu.IsSystem
381+
}
382+
379383
func (uGetUsersRow)RBACObject() rbac.Object {
380384
returnrbac.ResourceUserObject(u.ID)
381385
}

‎coderd/notifications.go‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ func (api *API) putUserNotificationPreferences(rw http.ResponseWriter, r *http.R
333333
// @Param request body codersdk.CustomNotification true "Provide a non-empty title or message"
334334
// @Success 204 "No Content"
335335
// @Failure 400 {object} codersdk.Response "Invalid request body"
336+
// @Failure 403 {object} codersdk.Response "System users cannot send custom notifications"
336337
// @Failure 500 {object} codersdk.Response "Failed to send custom notification"
337338
// @Router /notifications/custom [post]
338339
func (api*API)postCustomNotification(rw http.ResponseWriter,r*http.Request) {
@@ -357,17 +358,36 @@ func (api *API) postCustomNotification(rw http.ResponseWriter, r *http.Request)
357358
return
358359
}
359360

360-
userID:=apiKey.UserID
361+
// Block system users from sending custom notifications
362+
user,err:=api.Database.GetUserByID(ctx,apiKey.UserID)
363+
iferr!=nil {
364+
api.Logger.Error(ctx,"send custom notification",slog.Error(err))
365+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
366+
Message:"Failed to send custom notification",
367+
Detail:err.Error(),
368+
})
369+
return
370+
}
371+
ifuser.IsSystemUser() {
372+
api.Logger.Error(ctx,"send custom notification: system user is not allowed",
373+
slog.F("id",user.ID.String()),slog.F("name",user.Name))
374+
httpapi.Write(ctx,rw,http.StatusForbidden, codersdk.Response{
375+
Message:"Forbidden",
376+
Detail:"System users cannot send custom notifications.",
377+
})
378+
return
379+
}
380+
361381
if_,err:=api.NotificationsEnqueuer.Enqueue(
362382
//nolint:gocritic // We need to be notifier to send the notification.
363383
dbauthz.AsNotifier(ctx),
364-
userID,
384+
user.ID,
365385
notifications.TemplateCustomNotification,
366386
map[string]string{
367387
"custom_title":req.Title,
368388
"custom_message":req.Message,
369389
},
370-
userID.String(),
390+
user.ID.String(),
371391
);err!=nil {
372392
api.Logger.Error(ctx,"send custom notification",slog.Error(err))
373393
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{

‎coderd/notifications_test.go‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/coder/coder/v2/coderd/coderdtest"
1313
"github.com/coder/coder/v2/coderd/database"
14+
"github.com/coder/coder/v2/coderd/database/dbgen"
1415
"github.com/coder/coder/v2/coderd/notifications"
1516
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
1617
"github.com/coder/coder/v2/codersdk"
@@ -407,6 +408,45 @@ func TestCustomNotification(t *testing.T) {
407408
require.ErrorAsf(t,err,&sdkError,"error should be of type *codersdk.Error")
408409
require.Equal(t,http.StatusBadRequest,sdkError.StatusCode())
409410
require.Equal(t,"Invalid request body",sdkError.Message)
411+
412+
sent:=notifyEnq.Sent(notificationstest.WithTemplateID(notifications.TemplateTestNotification))
413+
require.Len(t,sent,0)
414+
})
415+
416+
t.Run("SystemUserNotAllowed",func(t*testing.T) {
417+
t.Parallel()
418+
419+
ctx:=testutil.Context(t,testutil.WaitShort)
420+
421+
notifyEnq:=&notificationstest.FakeEnqueuer{}
422+
ownerClient,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{
423+
DeploymentValues:coderdtest.DeploymentValues(t),
424+
NotificationsEnqueuer:notifyEnq,
425+
})
426+
427+
// Given: A system user (prebuilds system user)
428+
_,token:=dbgen.APIKey(t,db, database.APIKey{
429+
UserID:database.PrebuildsSystemUserID,
430+
LoginType:database.LoginTypeNone,
431+
})
432+
systemUserClient:=codersdk.New(ownerClient.URL)
433+
systemUserClient.SetSessionToken(token)
434+
435+
// When: The system user attempts to send a custom notification
436+
err:=systemUserClient.PostCustomNotification(ctx, codersdk.CustomNotification{
437+
Title:"Custom Title",
438+
Message:"Custom Message",
439+
})
440+
441+
// Then: a forbidden error is expected with no notifications sent
442+
varsdkError*codersdk.Error
443+
require.Error(t,err)
444+
require.ErrorAsf(t,err,&sdkError,"error should be of type *codersdk.Error")
445+
require.Equal(t,http.StatusForbidden,sdkError.StatusCode())
446+
require.Equal(t,"Forbidden",sdkError.Message)
447+
448+
sent:=notifyEnq.Sent(notificationstest.WithTemplateID(notifications.TemplateTestNotification))
449+
require.Len(t,sent,0)
410450
})
411451

412452
t.Run("Success",func(t*testing.T) {

‎docs/reference/api/notifications.md‎

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp