mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
fix(coderd): ensure correct RBAC when enqueueing notifications (#15478)
- Assert rbac in fake notifications enqueuer - Move fake notifications enqueuer to separate notificationstest package - Update dbauthz rbac policy to allow provisionerd and autostart to create and read notification messages - Update tests as required
This commit is contained in:
@ -208,7 +208,8 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S
|
||||
for _, ws := range markedForDeletion {
|
||||
dormantTime := dbtime.Now().Add(opts.TimeTilDormantAutoDelete)
|
||||
_, err = s.enqueuer.Enqueue(
|
||||
ctx,
|
||||
// nolint:gocritic // Need actor to enqueue notification
|
||||
dbauthz.AsNotifier(ctx),
|
||||
ws.OwnerID,
|
||||
notifications.TemplateWorkspaceMarkedForDeletion,
|
||||
map[string]string{
|
||||
|
@ -16,9 +16,11 @@ import (
|
||||
"cdr.dev/slog/sloggers/slogtest"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||
"github.com/coder/coder/v2/coderd/database/dbgen"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
||||
"github.com/coder/coder/v2/coderd/notifications"
|
||||
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
|
||||
agplschedule "github.com/coder/coder/v2/coderd/schedule"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/cryptorand"
|
||||
@ -673,7 +675,7 @@ func TestNotifications(t *testing.T) {
|
||||
}
|
||||
|
||||
// Setup dependencies
|
||||
notifyEnq := testutil.FakeNotificationsEnqueuer{}
|
||||
notifyEnq := notificationstest.FakeEnqueuer{}
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
|
||||
const userQuietHoursSchedule = "CRON_TZ=UTC 0 0 * * *" // midnight UTC
|
||||
userQuietHoursStore, err := schedule.NewEnterpriseUserQuietHoursScheduleStore(userQuietHoursSchedule, true)
|
||||
@ -685,21 +687,23 @@ func TestNotifications(t *testing.T) {
|
||||
|
||||
// Lower the dormancy TTL to ensure the schedule recalculates deadlines and
|
||||
// triggers notifications.
|
||||
_, err = templateScheduleStore.Set(ctx, db, template, agplschedule.TemplateScheduleOptions{
|
||||
// nolint:gocritic // Need an actor in the context.
|
||||
_, err = templateScheduleStore.Set(dbauthz.AsNotifier(ctx), db, template, agplschedule.TemplateScheduleOptions{
|
||||
TimeTilDormant: timeTilDormant / 2,
|
||||
TimeTilDormantAutoDelete: timeTilDormant / 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// We should expect a notification for each dormant workspace.
|
||||
require.Len(t, notifyEnq.Sent, len(dormantWorkspaces))
|
||||
sent := notifyEnq.Sent()
|
||||
require.Len(t, sent, len(dormantWorkspaces))
|
||||
for i, dormantWs := range dormantWorkspaces {
|
||||
require.Equal(t, notifyEnq.Sent[i].UserID, dormantWs.OwnerID)
|
||||
require.Equal(t, notifyEnq.Sent[i].TemplateID, notifications.TemplateWorkspaceMarkedForDeletion)
|
||||
require.Contains(t, notifyEnq.Sent[i].Targets, template.ID)
|
||||
require.Contains(t, notifyEnq.Sent[i].Targets, dormantWs.ID)
|
||||
require.Contains(t, notifyEnq.Sent[i].Targets, dormantWs.OrganizationID)
|
||||
require.Contains(t, notifyEnq.Sent[i].Targets, dormantWs.OwnerID)
|
||||
require.Equal(t, sent[i].UserID, dormantWs.OwnerID)
|
||||
require.Equal(t, sent[i].TemplateID, notifications.TemplateWorkspaceMarkedForDeletion)
|
||||
require.Contains(t, sent[i].Targets, template.ID)
|
||||
require.Contains(t, sent[i].Targets, dormantWs.ID)
|
||||
require.Contains(t, sent[i].Targets, dormantWs.OrganizationID)
|
||||
require.Contains(t, sent[i].Targets, dormantWs.OwnerID)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/coderdtest/oidctest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/cryptorand"
|
||||
"github.com/coder/coder/v2/enterprise/coderd"
|
||||
@ -122,7 +123,7 @@ func TestScim(t *testing.T) {
|
||||
// given
|
||||
scimAPIKey := []byte("hi")
|
||||
mockAudit := audit.NewMock()
|
||||
notifyEnq := &testutil.FakeNotificationsEnqueuer{}
|
||||
notifyEnq := ¬ificationstest.FakeEnqueuer{}
|
||||
client, _ := coderdenttest.New(t, &coderdenttest.Options{
|
||||
Options: &coderdtest.Options{
|
||||
Auditor: mockAudit,
|
||||
@ -172,7 +173,7 @@ func TestScim(t *testing.T) {
|
||||
assert.Len(t, userRes.Users[0].OrganizationIDs, 1)
|
||||
|
||||
// Expect zero notifications (SkipNotifications = true)
|
||||
require.Empty(t, notifyEnq.Sent)
|
||||
require.Empty(t, notifyEnq.Sent())
|
||||
})
|
||||
|
||||
t.Run("OK_Bearer", func(t *testing.T) {
|
||||
@ -184,7 +185,7 @@ func TestScim(t *testing.T) {
|
||||
// given
|
||||
scimAPIKey := []byte("hi")
|
||||
mockAudit := audit.NewMock()
|
||||
notifyEnq := &testutil.FakeNotificationsEnqueuer{}
|
||||
notifyEnq := ¬ificationstest.FakeEnqueuer{}
|
||||
client, _ := coderdenttest.New(t, &coderdenttest.Options{
|
||||
Options: &coderdtest.Options{
|
||||
Auditor: mockAudit,
|
||||
@ -228,7 +229,7 @@ func TestScim(t *testing.T) {
|
||||
assert.Len(t, userRes.Users[0].OrganizationIDs, 1)
|
||||
|
||||
// Expect zero notifications (SkipNotifications = true)
|
||||
require.Empty(t, notifyEnq.Sent)
|
||||
require.Empty(t, notifyEnq.Sent())
|
||||
})
|
||||
|
||||
t.Run("OKNoDefault", func(t *testing.T) {
|
||||
@ -240,7 +241,7 @@ func TestScim(t *testing.T) {
|
||||
// given
|
||||
scimAPIKey := []byte("hi")
|
||||
mockAudit := audit.NewMock()
|
||||
notifyEnq := &testutil.FakeNotificationsEnqueuer{}
|
||||
notifyEnq := ¬ificationstest.FakeEnqueuer{}
|
||||
dv := coderdtest.DeploymentValues(t)
|
||||
dv.OIDC.OrganizationAssignDefault = false
|
||||
client, _ := coderdenttest.New(t, &coderdenttest.Options{
|
||||
@ -287,7 +288,7 @@ func TestScim(t *testing.T) {
|
||||
assert.Len(t, userRes.Users[0].OrganizationIDs, 0)
|
||||
|
||||
// Expect zero notifications (SkipNotifications = true)
|
||||
require.Empty(t, notifyEnq.Sent)
|
||||
require.Empty(t, notifyEnq.Sent())
|
||||
})
|
||||
|
||||
t.Run("Duplicate", func(t *testing.T) {
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/notifications"
|
||||
"github.com/coder/coder/v2/coderd/notifications/notificationstest"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
@ -39,7 +40,7 @@ func TestTemplates(t *testing.T) {
|
||||
t.Run("Deprecated", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
notifyEnq := &testutil.FakeNotificationsEnqueuer{}
|
||||
notifyEnq := ¬ificationstest.FakeEnqueuer{}
|
||||
owner, user := coderdenttest.New(t, &coderdenttest.Options{
|
||||
Options: &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
@ -81,8 +82,8 @@ func TestTemplates(t *testing.T) {
|
||||
assert.True(t, updated.Deprecated)
|
||||
assert.NotEmpty(t, updated.DeprecationMessage)
|
||||
|
||||
notifs := []*testutil.Notification{}
|
||||
for _, notif := range notifyEnq.Sent {
|
||||
notifs := []*notificationstest.FakeNotification{}
|
||||
for _, notif := range notifyEnq.Sent() {
|
||||
if notif.TemplateID == notifications.TemplateTemplateDeprecated {
|
||||
notifs = append(notifs, notif)
|
||||
}
|
||||
|
Reference in New Issue
Block a user