fix: send workspace create/update notifications to template admins only (#16071)

Relates to https://github.com/coder/coder/issues/15845

Rather than sending the notification to the user, we send it to the
template admins. We also do not send it to the person that created the
request.
This commit is contained in:
Danielle Maywood
2025-01-15 17:43:11 +00:00
committed by GitHub
parent cd62e3934a
commit 3e3de0588a
4 changed files with 103 additions and 33 deletions

View File

@ -565,19 +565,20 @@ func TestWorkspaceBuildResources(t *testing.T) {
func TestWorkspaceBuildWithUpdatedTemplateVersionSendsNotification(t *testing.T) {
t.Parallel()
t.Run("OnlyOneNotification", func(t *testing.T) {
t.Run("NoRepeatedNotifications", func(t *testing.T) {
t.Parallel()
notify := &notificationstest.FakeEnqueuer{}
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, NotificationsEnqueuer: notify})
first := coderdtest.CreateFirstUser(t, client)
templateAdminClient, templateAdmin := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleTemplateAdmin())
userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
// Create a template with an initial version
version := coderdtest.CreateTemplateVersion(t, client, first.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, first.OrganizationID, version.ID)
version := coderdtest.CreateTemplateVersion(t, templateAdminClient, first.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdminClient, version.ID)
template := coderdtest.CreateTemplate(t, templateAdminClient, first.OrganizationID, version.ID)
// Create a workspace using this template
workspace := coderdtest.CreateWorkspace(t, userClient, template.ID)
@ -585,10 +586,10 @@ func TestWorkspaceBuildWithUpdatedTemplateVersionSendsNotification(t *testing.T)
coderdtest.MustTransitionWorkspace(t, userClient, workspace.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)
// Create a new version of the template
newVersion := coderdtest.CreateTemplateVersion(t, client, first.OrganizationID, nil, func(ctvr *codersdk.CreateTemplateVersionRequest) {
newVersion := coderdtest.CreateTemplateVersion(t, templateAdminClient, first.OrganizationID, nil, func(ctvr *codersdk.CreateTemplateVersionRequest) {
ctvr.TemplateID = template.ID
})
coderdtest.AwaitTemplateVersionJobCompleted(t, client, newVersion.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdminClient, newVersion.ID)
// Create a workspace build using this new template version
build := coderdtest.CreateWorkspaceBuild(t, userClient, workspace, database.WorkspaceTransitionStart, func(cwbr *codersdk.CreateWorkspaceBuildRequest) {
@ -597,21 +598,45 @@ func TestWorkspaceBuildWithUpdatedTemplateVersionSendsNotification(t *testing.T)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, userClient, build.ID)
coderdtest.MustTransitionWorkspace(t, userClient, workspace.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)
// Create the workspace build _again_. We are doing this to ensure we only create 1 notification.
// Create the workspace build _again_. We are doing this to
// ensure we do not create _another_ notification. This is
// separate to the notifications subsystem dedupe mechanism
// as this build shouldn't create a notification. It shouldn't
// create another notification as this new build isn't changing
// the template version.
build = coderdtest.CreateWorkspaceBuild(t, userClient, workspace, database.WorkspaceTransitionStart, func(cwbr *codersdk.CreateWorkspaceBuildRequest) {
cwbr.TemplateVersionID = newVersion.ID
})
coderdtest.AwaitWorkspaceBuildJobCompleted(t, userClient, build.ID)
coderdtest.MustTransitionWorkspace(t, userClient, workspace.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)
// Ensure we receive only 1 workspace manually updated notification
// We're going to have two notifications (one for the first user and one for the template admin)
// By ensuring we only have these two, we are sure the second build didn't trigger more
// notifications.
sent := notify.Sent(notificationstest.WithTemplateID(notifications.TemplateWorkspaceManuallyUpdated))
require.Len(t, sent, 1)
require.Equal(t, user.ID, sent[0].UserID)
require.Len(t, sent, 2)
receivers := make([]uuid.UUID, len(sent))
for idx, notif := range sent {
receivers[idx] = notif.UserID
}
// Check the notification was sent to the first user and template admin
// (both of whom have the "template admin" role), and explicitly not the
// workspace owner (since they initiated the workspace build).
require.Contains(t, receivers, templateAdmin.ID)
require.Contains(t, receivers, first.UserID)
require.NotContains(t, receivers, user.ID)
require.Contains(t, sent[0].Targets, template.ID)
require.Contains(t, sent[0].Targets, workspace.ID)
require.Contains(t, sent[0].Targets, workspace.OrganizationID)
require.Contains(t, sent[0].Targets, workspace.OwnerID)
require.Contains(t, sent[1].Targets, template.ID)
require.Contains(t, sent[1].Targets, workspace.ID)
require.Contains(t, sent[1].Targets, workspace.OrganizationID)
require.Contains(t, sent[1].Targets, workspace.OwnerID)
})
t.Run("ToCorrectUser", func(t *testing.T) {
@ -621,12 +646,13 @@ func TestWorkspaceBuildWithUpdatedTemplateVersionSendsNotification(t *testing.T)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, NotificationsEnqueuer: notify})
first := coderdtest.CreateFirstUser(t, client)
userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
templateAdminClient, templateAdmin := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleTemplateAdmin())
userClient, _ := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
// Create a template with an initial version
version := coderdtest.CreateTemplateVersion(t, client, first.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, first.OrganizationID, version.ID)
version := coderdtest.CreateTemplateVersion(t, templateAdminClient, first.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdminClient, version.ID)
template := coderdtest.CreateTemplate(t, templateAdminClient, first.OrganizationID, version.ID)
// Create a workspace using this template
workspace := coderdtest.CreateWorkspace(t, userClient, template.ID)
@ -634,10 +660,10 @@ func TestWorkspaceBuildWithUpdatedTemplateVersionSendsNotification(t *testing.T)
coderdtest.MustTransitionWorkspace(t, userClient, workspace.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)
// Create a new version of the template
newVersion := coderdtest.CreateTemplateVersion(t, client, first.OrganizationID, nil, func(ctvr *codersdk.CreateTemplateVersionRequest) {
newVersion := coderdtest.CreateTemplateVersion(t, templateAdminClient, first.OrganizationID, nil, func(ctvr *codersdk.CreateTemplateVersionRequest) {
ctvr.TemplateID = template.ID
})
coderdtest.AwaitTemplateVersionJobCompleted(t, client, newVersion.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdminClient, newVersion.ID)
// Create a workspace build using this new template version from a different user
ctx := testutil.Context(t, testutil.WaitShort)
@ -652,7 +678,7 @@ func TestWorkspaceBuildWithUpdatedTemplateVersionSendsNotification(t *testing.T)
// Ensure we receive only 1 workspace manually updated notification and to the right user
sent := notify.Sent(notificationstest.WithTemplateID(notifications.TemplateWorkspaceManuallyUpdated))
require.Len(t, sent, 1)
require.Equal(t, user.ID, sent[0].UserID)
require.Equal(t, templateAdmin.ID, sent[0].UserID)
require.Contains(t, sent[0].Targets, template.ID)
require.Contains(t, sent[0].Targets, workspace.ID)
require.Contains(t, sent[0].Targets, workspace.OrganizationID)