Skip to content

Commit 98e7501

Browse files
committed
feat(coderd): send newly required information to notification templates
1 parent fe94f0d commit 98e7501

File tree

5 files changed

+79
-28
lines changed

5 files changed

+79
-28
lines changed

coderd/templates.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ func (api *API) notifyTemplateDeleted(ctx context.Context, template database.Tem
137137

138138
if _, err := api.NotificationsEnqueuer.Enqueue(ctx, receiverID, notifications.TemplateTemplateDeleted,
139139
map[string]string{
140-
"name": template.Name,
141-
"initiator": initiator.Username,
140+
"name": template.Name,
141+
"display_name": template.DisplayName,
142+
"initiator": initiator.Username,
142143
}, "api-templates-delete",
143144
// Associate this notification with all the related entities.
144145
template.ID, template.OrganizationID,

coderd/templates_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,9 @@ func TestTemplateNotifications(t *testing.T) {
14191419
// Setup template
14201420
version = coderdtest.CreateTemplateVersion(t, client, initiator.OrganizationID, nil)
14211421
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
1422-
template = coderdtest.CreateTemplate(t, client, initiator.OrganizationID, version.ID)
1422+
template = coderdtest.CreateTemplate(t, client, initiator.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
1423+
ctr.DisplayName = "Bobby's Template"
1424+
})
14231425
)
14241426

14251427
// Setup users with different roles
@@ -1455,6 +1457,7 @@ func TestTemplateNotifications(t *testing.T) {
14551457
require.Contains(t, n.Targets, template.ID)
14561458
require.Contains(t, n.Targets, template.OrganizationID)
14571459
require.Equal(t, n.Labels["name"], template.Name)
1460+
require.Equal(t, n.Labels["display_name"], template.DisplayName)
14581461
require.Equal(t, n.Labels["initiator"], coderdtest.FirstUserParams.Username)
14591462
}
14601463
})

coderd/userauth.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,14 +1481,15 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
14811481
Username: params.Username,
14821482
OrganizationIDs: orgIDs,
14831483
},
1484-
LoginType: params.LoginType,
1484+
LoginType: params.LoginType,
1485+
accountCreatorName: "oauth",
14851486
})
14861487
if err != nil {
14871488
return xerrors.Errorf("create user: %w", err)
14881489
}
14891490
}
14901491

1491-
// Activate dormant user on sigin
1492+
// Activate dormant user on sign-in
14921493
if user.Status == database.UserStatusDormant {
14931494
//nolint:gocritic // System needs to update status of the user account (dormant -> active).
14941495
user, err = tx.UpdateUserStatus(dbauthz.AsSystemRestricted(ctx), database.UpdateUserStatusParams{

coderd/users.go

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
194194
Password: createUser.Password,
195195
OrganizationIDs: []uuid.UUID{defaultOrg.ID},
196196
},
197-
LoginType: database.LoginTypePassword,
197+
LoginType: database.LoginTypePassword,
198+
accountCreatorName: "coder",
198199
})
199200
if err != nil {
200201
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -479,10 +480,22 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
479480
return
480481
}
481482

483+
apiKey := httpmw.APIKey(r)
484+
485+
accountCreator, err := api.Database.GetUserByID(ctx, apiKey.UserID)
486+
if err != nil {
487+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
488+
Message: "Unable to determine the details of the actor creating the account.",
489+
})
490+
return
491+
}
492+
482493
user, err := api.CreateUser(ctx, api.Database, CreateUserRequest{
483494
CreateUserRequestWithOrgs: req,
484495
LoginType: loginType,
496+
accountCreatorName: accountCreator.Name,
485497
})
498+
486499
if dbauthz.IsNotAuthorizedError(err) {
487500
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
488501
Message: "You are not authorized to create users.",
@@ -576,11 +589,24 @@ func (api *API) deleteUser(rw http.ResponseWriter, r *http.Request) {
576589
return
577590
}
578591

592+
apiKey := httpmw.APIKey(r)
593+
594+
accountDeleter, err := api.Database.GetUserByID(ctx, apiKey.UserID)
595+
if err != nil {
596+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
597+
Message: "Unable to determine the details of the actor deleting the account.",
598+
})
599+
return
600+
}
601+
579602
for _, u := range userAdmins {
580603
if _, err := api.NotificationsEnqueuer.Enqueue(ctx, u.ID, notifications.TemplateUserAccountDeleted,
581604
map[string]string{
582-
"deleted_account_name": user.Username,
583-
}, "api-users-delete",
605+
"deleted_account_name": user.Username,
606+
"deleted_account_user_name": user.Name,
607+
"account_deleter_user_name": accountDeleter.Name,
608+
},
609+
"api-users-delete",
584610
user.ID,
585611
); err != nil {
586612
api.Logger.Warn(ctx, "unable to notify about deleted user", slog.F("deleted_user", user.Username), slog.Error(err))
@@ -844,6 +870,14 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW
844870
}
845871
}
846872

873+
actingUser, err := api.Database.GetUserByID(ctx, apiKey.UserID)
874+
if err != nil {
875+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
876+
Message: "Unable to determine the details of the actor creating the account.",
877+
})
878+
return
879+
}
880+
847881
targetUser, err := api.Database.UpdateUserStatus(ctx, database.UpdateUserStatusParams{
848882
ID: user.ID,
849883
Status: status,
@@ -858,7 +892,7 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW
858892
}
859893
aReq.New = targetUser
860894

861-
err = api.notifyUserStatusChanged(ctx, user, status)
895+
err = api.notifyUserStatusChanged(ctx, actingUser.Name, user, status)
862896
if err != nil {
863897
api.Logger.Warn(ctx, "unable to notify about changed user's status", slog.F("affected_user", user.Username), slog.Error(err))
864898
}
@@ -871,24 +905,33 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW
871905
})
872906
return
873907
}
908+
874909
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.User(targetUser, organizations))
875910
}
876911
}
877912

878-
func (api *API) notifyUserStatusChanged(ctx context.Context, user database.User, status database.UserStatus) error {
879-
var key string
913+
func (api *API) notifyUserStatusChanged(ctx context.Context, actingUserName string, targetUser database.User, status database.UserStatus) error {
914+
var labels map[string]string
880915
var adminTemplateID, personalTemplateID uuid.UUID
881916
switch status {
882917
case database.UserStatusSuspended:
883-
key = "suspended_account_name"
918+
labels = map[string]string{
919+
"suspended_account_name": targetUser.Username,
920+
"suspended_account_user_name": targetUser.Name,
921+
"account_suspender_user_name": actingUserName,
922+
}
884923
adminTemplateID = notifications.TemplateUserAccountSuspended
885924
personalTemplateID = notifications.TemplateYourAccountSuspended
886925
case database.UserStatusActive:
887-
key = "activated_account_name"
926+
labels = map[string]string{
927+
"activated_account_name": targetUser.Username,
928+
"activated_account_user_name": targetUser.Name,
929+
"account_activator_user_name": actingUserName,
930+
}
888931
adminTemplateID = notifications.TemplateUserAccountActivated
889932
personalTemplateID = notifications.TemplateYourAccountActivated
890933
default:
891-
api.Logger.Error(ctx, "user status is not supported", slog.F("username", user.Username), slog.F("user_status", string(status)))
934+
api.Logger.Error(ctx, "user status is not supported", slog.F("username", targetUser.Username), slog.F("user_status", string(status)))
892935
return xerrors.Errorf("unable to notify admins as the user's status is unsupported")
893936
}
894937

@@ -900,21 +943,17 @@ func (api *API) notifyUserStatusChanged(ctx context.Context, user database.User,
900943
// Send notifications to user admins and affected user
901944
for _, u := range userAdmins {
902945
if _, err := api.NotificationsEnqueuer.Enqueue(ctx, u.ID, adminTemplateID,
903-
map[string]string{
904-
key: user.Username,
905-
}, "api-put-user-status",
906-
user.ID,
946+
labels, "api-put-user-status",
947+
targetUser.ID,
907948
); err != nil {
908-
api.Logger.Warn(ctx, "unable to notify about changed user's status", slog.F("affected_user", user.Username), slog.Error(err))
949+
api.Logger.Warn(ctx, "unable to notify about changed user's status", slog.F("affected_user", targetUser.Username), slog.Error(err))
909950
}
910951
}
911-
if _, err := api.NotificationsEnqueuer.Enqueue(ctx, user.ID, personalTemplateID,
912-
map[string]string{
913-
key: user.Username,
914-
}, "api-put-user-status",
915-
user.ID,
952+
if _, err := api.NotificationsEnqueuer.Enqueue(ctx, targetUser.ID, personalTemplateID,
953+
labels, "api-put-user-status",
954+
targetUser.ID,
916955
); err != nil {
917-
api.Logger.Warn(ctx, "unable to notify user about status change of their account", slog.F("affected_user", user.Username), slog.Error(err))
956+
api.Logger.Warn(ctx, "unable to notify user about status change of their account", slog.F("affected_user", targetUser.Username), slog.Error(err))
918957
}
919958
return nil
920959
}
@@ -1280,8 +1319,9 @@ func (api *API) organizationByUserAndName(rw http.ResponseWriter, r *http.Reques
12801319

12811320
type CreateUserRequest struct {
12821321
codersdk.CreateUserRequestWithOrgs
1283-
LoginType database.LoginType
1284-
SkipNotifications bool
1322+
LoginType database.LoginType
1323+
SkipNotifications bool
1324+
accountCreatorName string
12851325
}
12861326

12871327
func (api *API) CreateUser(ctx context.Context, store database.Store, req CreateUserRequest) (database.User, error) {
@@ -1365,13 +1405,16 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
13651405
for _, u := range userAdmins {
13661406
if _, err := api.NotificationsEnqueuer.Enqueue(ctx, u.ID, notifications.TemplateUserAccountCreated,
13671407
map[string]string{
1368-
"created_account_name": user.Username,
1408+
"created_account_name": user.Username,
1409+
"created_account_user_name": user.Name,
1410+
"account_creator": req.accountCreatorName,
13691411
}, "api-users-create",
13701412
user.ID,
13711413
); err != nil {
13721414
api.Logger.Warn(ctx, "unable to notify about created user", slog.F("created_user", user.Username), slog.Error(err))
13731415
}
13741416
}
1417+
13751418
return user, err
13761419
}
13771420

coderd/users_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ func TestNotifyDeletedUser(t *testing.T) {
513513
require.Equal(t, firstUser.UserID, notifyEnq.Sent[1].UserID)
514514
require.Contains(t, notifyEnq.Sent[1].Targets, user.ID)
515515
require.Equal(t, user.Username, notifyEnq.Sent[1].Labels["deleted_account_name"])
516+
require.Equal(t, user.Name, notifyEnq.Sent[1].Labels["deleted_account_user_name"])
517+
// Not sure where to get the following just yet
518+
// require.Equal(t, , notifyEnq.Sent[1].Labels["account_deleter_user_name"])
516519
})
517520

518521
t.Run("UserAdminNotified", func(t *testing.T) {

0 commit comments

Comments
 (0)