- Notifications
You must be signed in to change notification settings - Fork928
feat: notify about created user account#14010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
c18ada0
1cc3adb
ca2bdde
d6e8964
2d74c4e
3c3b5af
312d9fa
82ec37f
d7b2c73
b81bb6a
00275dd
e356ba8
6bc1d2d
67a5137
6431a0e
42d9ba1
ecc7d30
b2dcb3b
70e2d2c
8696b70
a92d059
b5b0d90
2de1786
b843232
2a53a0b
77c0c28
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DELETE FROM notification_templates WHERE id = '4e19c0ac-94e1-4532-9515-d1801aa283b2'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
INSERT INTO notification_templates (id, name, title_template, body_template, "group", actions) | ||
VALUES ('4e19c0ac-94e1-4532-9515-d1801aa283b2', 'User account created', E'User account "{{.Labels.created_account_name}}" created', | ||
E'Hi {{.UserName}},\n\New user account **{{.Labels.created_account_name}}** has been created.', | ||
'Workspace Events', '[ | ||
{ | ||
"label": "View accounts", | ||
"url": "{{ base_url }}/deployment/users?filter=status%3Aactive" | ||
} | ||
]'::jsonb); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -10,6 +10,7 @@ import ( | ||
"github.com/coder/coder/v2/coderd" | ||
"github.com/coder/coder/v2/coderd/coderdtest/oidctest" | ||
"github.com/coder/coder/v2/coderd/notifications" | ||
"github.com/coder/coder/v2/coderd/rbac/policy" | ||
"github.com/coder/serpent" | ||
@@ -598,6 +599,99 @@ func TestPostUsers(t *testing.T) { | ||
}) | ||
} | ||
func TestNotifyCreatedUser(t *testing.T) { | ||
t.Parallel() | ||
t.Run("OwnerNotified", func(t *testing.T) { | ||
mtojek marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
t.Parallel() | ||
// given | ||
notifyEnq := &testutil.FakeNotificationsEnqueuer{} | ||
adminClient := coderdtest.New(t, &coderdtest.Options{ | ||
NotificationsEnqueuer: notifyEnq, | ||
}) | ||
firstUser := coderdtest.CreateFirstUser(t, adminClient) | ||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) | ||
defer cancel() | ||
// when | ||
user, err := adminClient.CreateUser(ctx, codersdk.CreateUserRequest{ | ||
mtojek marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
OrganizationID: firstUser.OrganizationID, | ||
Email: "another@user.org", | ||
Username: "someone-else", | ||
Password: "SomeSecurePassword!", | ||
}) | ||
require.NoError(t, err) | ||
// then | ||
require.Len(t, notifyEnq.Sent, 1) | ||
require.Equal(t, notifications.TemplateUserAccountCreated, notifyEnq.Sent[0].TemplateID) | ||
require.Equal(t, firstUser.UserID, notifyEnq.Sent[0].UserID) | ||
require.Contains(t, notifyEnq.Sent[0].Targets, user.ID) | ||
require.Equal(t, user.Username, notifyEnq.Sent[0].Labels["created_account_name"]) | ||
}) | ||
t.Run("UserAdminNotified", func(t *testing.T) { | ||
t.Parallel() | ||
// given | ||
notifyEnq := &testutil.FakeNotificationsEnqueuer{} | ||
adminClient := coderdtest.New(t, &coderdtest.Options{ | ||
NotificationsEnqueuer: notifyEnq, | ||
}) | ||
firstUser := coderdtest.CreateFirstUser(t, adminClient) | ||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) | ||
defer cancel() | ||
userAdmin, err := adminClient.CreateUser(ctx, codersdk.CreateUserRequest{ | ||
OrganizationID: firstUser.OrganizationID, | ||
Email: "user-admin@user.org", | ||
Username: "mr-user-admin", | ||
Password: "SomeSecurePassword!", | ||
}) | ||
require.NoError(t, err) | ||
_, err = adminClient.UpdateUserRoles(ctx, userAdmin.Username, codersdk.UpdateRoles{ | ||
Roles: []string{ | ||
rbac.RoleUserAdmin().String(), | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
// when | ||
member, err := adminClient.CreateUser(ctx, codersdk.CreateUserRequest{ | ||
OrganizationID: firstUser.OrganizationID, | ||
Email: "another@user.org", | ||
Username: "someone-else", | ||
Password: "SomeSecurePassword!", | ||
}) | ||
require.NoError(t, err) | ||
// then | ||
require.Len(t, notifyEnq.Sent, 3) | ||
// "User admin" account created, "owner" notified | ||
require.Equal(t, notifications.TemplateUserAccountCreated, notifyEnq.Sent[0].TemplateID) | ||
require.Equal(t, firstUser.UserID, notifyEnq.Sent[0].UserID) | ||
require.Contains(t, notifyEnq.Sent[0].Targets, userAdmin.ID) | ||
require.Equal(t, userAdmin.Username, notifyEnq.Sent[0].Labels["created_account_name"]) | ||
// "Member" account created, "owner" notified | ||
require.Equal(t, notifications.TemplateUserAccountCreated, notifyEnq.Sent[1].TemplateID) | ||
require.Equal(t, firstUser.UserID, notifyEnq.Sent[1].UserID) | ||
require.Contains(t, notifyEnq.Sent[1].Targets, member.ID) | ||
require.Equal(t, member.Username, notifyEnq.Sent[1].Labels["created_account_name"]) | ||
// "Member" account created, "user admin" notified | ||
require.Equal(t, notifications.TemplateUserAccountCreated, notifyEnq.Sent[1].TemplateID) | ||
require.Equal(t, userAdmin.ID, notifyEnq.Sent[2].UserID) | ||
require.Contains(t, notifyEnq.Sent[2].Targets, member.ID) | ||
require.Equal(t, member.Username, notifyEnq.Sent[2].Labels["created_account_name"]) | ||
}) | ||
} | ||
func TestUpdateUserProfile(t *testing.T) { | ||
t.Parallel() | ||
t.Run("UserNotFound", func(t *testing.T) { | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -3476,13 +3476,14 @@ func TestNotifications(t *testing.T) { | ||
// Then | ||
require.NoError(t, err, "mark workspace as dormant") | ||
require.Len(t, notifyEnq.Sent, 2) | ||
// notifyEnq.Sent[0] is an event for created user account | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Nit: would be safer to validate this MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I left it like this on purpose, this is not the aim of this test. Less chance that it will require refining if we alter something in Notifications Enqueuer logic | ||
require.Equal(t, notifyEnq.Sent[1].TemplateID, notifications.TemplateWorkspaceDormant) | ||
require.Equal(t, notifyEnq.Sent[1].UserID, workspace.OwnerID) | ||
require.Contains(t, notifyEnq.Sent[1].Targets, template.ID) | ||
require.Contains(t, notifyEnq.Sent[1].Targets, workspace.ID) | ||
require.Contains(t, notifyEnq.Sent[1].Targets, workspace.OrganizationID) | ||
require.Contains(t, notifyEnq.Sent[1].Targets, workspace.OwnerID) | ||
}) | ||
t.Run("InitiatorIsOwner", func(t *testing.T) { | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -239,6 +239,8 @@ func (api *API) scimPostUser(rw http.ResponseWriter, r *http.Request) { | ||
OrganizationID: defaultOrganization.ID, | ||
}, | ||
LoginType: database.LoginTypeOIDC, | ||
// Do not send notifications to user admins as SCIM endpoint might be called sequentially to all users. | ||
SkipNotifications: true, | ||
mtojek marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
}) | ||
if err != nil { | ||
_ = handlerutil.WriteError(rw, err) | ||
Uh oh!
There was an error while loading.Please reload this page.