fix(coderd): use service account wording in account notifications (#27536)

This commit is contained in:
Atif Ali
2026-08-11 13:16:25 +00:00
committed by GitHub
parent 75e0790cd7
commit d7953bd046
23 changed files with 881 additions and 13 deletions
+64
View File
@@ -11,6 +11,8 @@ import (
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database/dbtime"
"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/schedule/cron"
"github.com/coder/coder/v2/codersdk"
@@ -779,3 +781,65 @@ func TestEnterprisePostUser(t *testing.T) {
require.NotEqual(t, user1.ID, user2.ID)
})
}
// TestServiceAccountNotifications asserts that every account lifecycle
// notification describes a service account as such, so the wording cannot
// regress to "user account" for one of the events.
func TestServiceAccountNotifications(t *testing.T) {
t.Parallel()
notifyEnq := &notificationstest.FakeEnqueuer{}
client, first := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
NotificationsEnqueuer: notifyEnq,
},
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureServiceAccounts: 1,
},
},
})
ctx := testutil.Context(t, testutil.WaitLong)
// requireServiceAccountNotification asserts the owner was notified about the
// service account, and that the notification carries the service wording.
requireServiceAccountNotification := func(t *testing.T, templateID uuid.UUID, serviceAccountID uuid.UUID) {
t.Helper()
sent := notifyEnq.Sent(notificationstest.WithTemplateID(templateID))
require.Len(t, sent, 1)
require.Equal(t, first.UserID, sent[0].UserID)
require.Contains(t, sent[0].Targets, serviceAccountID)
require.Equal(t, "service", sent[0].Labels["account_type"])
}
//nolint:gocritic // The owner is the only user admin, so it is the recipient under test.
serviceAccount, err := client.CreateUserWithOrgs(ctx, codersdk.CreateUserRequestWithOrgs{
OrganizationIDs: []uuid.UUID{first.OrganizationID},
Username: "service-acct-lifecycle",
UserLoginType: codersdk.LoginTypeNone,
ServiceAccount: true,
})
require.NoError(t, err)
requireServiceAccountNotification(t, notifications.TemplateUserAccountCreated, serviceAccount.ID)
// Service accounts are created dormant, so activation comes before
// suspension.
notifyEnq.Clear()
//nolint:gocritic // Only the owner can change another account's status here.
_, err = client.UpdateUserStatus(ctx, serviceAccount.Username, codersdk.UserStatusActive)
require.NoError(t, err)
requireServiceAccountNotification(t, notifications.TemplateUserAccountActivated, serviceAccount.ID)
notifyEnq.Clear()
//nolint:gocritic // Only the owner can change another account's status here.
_, err = client.UpdateUserStatus(ctx, serviceAccount.Username, codersdk.UserStatusSuspended)
require.NoError(t, err)
requireServiceAccountNotification(t, notifications.TemplateUserAccountSuspended, serviceAccount.ID)
notifyEnq.Clear()
//nolint:gocritic // Only the owner can delete another account here.
require.NoError(t, client.DeleteUser(ctx, serviceAccount.ID))
requireServiceAccountNotification(t, notifications.TemplateUserAccountDeleted, serviceAccount.ID)
}