diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index cf1773f637a02..f74197e234fa8 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -1929,6 +1929,7 @@ func (q *FakeQuerier) FetchNewMessageMetadata(_ context.Context, arg database.Fe return database.FetchNewMessageMetadataRow{ UserEmail: user.Email, UserName: userName, + UserUsername: user.Username, NotificationName: "Some notification", Actions: actions, UserID: arg.UserID, diff --git a/coderd/database/migrations/000230_notifications_fix_username.down.sql b/coderd/database/migrations/000230_notifications_fix_username.down.sql new file mode 100644 index 0000000000000..4c3e7dda9b03d --- /dev/null +++ b/coderd/database/migrations/000230_notifications_fix_username.down.sql @@ -0,0 +1,3 @@ +UPDATE notification_templates +SET + actions = REPLACE(actions::text, '@{{.UserUsername}}', '@{{.UserName}}')::jsonb; diff --git a/coderd/database/migrations/000230_notifications_fix_username.up.sql b/coderd/database/migrations/000230_notifications_fix_username.up.sql new file mode 100644 index 0000000000000..bfd01ae3c8637 --- /dev/null +++ b/coderd/database/migrations/000230_notifications_fix_username.up.sql @@ -0,0 +1,3 @@ +UPDATE notification_templates +SET + actions = REPLACE(actions::text, '@{{.UserName}}', '@{{.UserUsername}}')::jsonb; diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index d67448fa09b47..b761e451b3041 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -3546,7 +3546,8 @@ SELECT nt.name AS notificatio nt.actions AS actions, u.id AS user_id, u.email AS user_email, - COALESCE(NULLIF(u.name, ''), NULLIF(u.username, ''))::text AS user_name + COALESCE(NULLIF(u.name, ''), NULLIF(u.username, ''))::text AS user_name, + COALESCE(u.username, '') AS user_username FROM notification_templates nt, users u WHERE nt.id = $1 @@ -3564,6 +3565,7 @@ type FetchNewMessageMetadataRow struct { UserID uuid.UUID `db:"user_id" json:"user_id"` UserEmail string `db:"user_email" json:"user_email"` UserName string `db:"user_name" json:"user_name"` + UserUsername string `db:"user_username" json:"user_username"` } // This is used to build up the notification_message's JSON payload. @@ -3576,6 +3578,7 @@ func (q *sqlQuerier) FetchNewMessageMetadata(ctx context.Context, arg FetchNewMe &i.UserID, &i.UserEmail, &i.UserName, + &i.UserUsername, ) return i, err } diff --git a/coderd/database/queries/notifications.sql b/coderd/database/queries/notifications.sql index edbb0fd6f5d58..2fd372e9df029 100644 --- a/coderd/database/queries/notifications.sql +++ b/coderd/database/queries/notifications.sql @@ -4,7 +4,8 @@ SELECT nt.name AS notificatio nt.actions AS actions, u.id AS user_id, u.email AS user_email, - COALESCE(NULLIF(u.name, ''), NULLIF(u.username, ''))::text AS user_name + COALESCE(NULLIF(u.name, ''), NULLIF(u.username, ''))::text AS user_name, + COALESCE(u.username, '') AS user_username FROM notification_templates nt, users u WHERE nt.id = @notification_template_id diff --git a/coderd/notifications/enqueuer.go b/coderd/notifications/enqueuer.go index d73826142f7ca..32822dd6ab9d7 100644 --- a/coderd/notifications/enqueuer.go +++ b/coderd/notifications/enqueuer.go @@ -94,9 +94,10 @@ func (s *StoreEnqueuer) buildPayload(ctx context.Context, userID, templateID uui NotificationName: metadata.NotificationName, - UserID: metadata.UserID.String(), - UserEmail: metadata.UserEmail, - UserName: metadata.UserName, + UserID: metadata.UserID.String(), + UserEmail: metadata.UserEmail, + UserName: metadata.UserName, + UserUsername: metadata.UserUsername, Labels: labels, // No actions yet diff --git a/coderd/notifications/notifications_test.go b/coderd/notifications/notifications_test.go index 481244bf21f2a..7d55ac01c5b52 100644 --- a/coderd/notifications/notifications_test.go +++ b/coderd/notifications/notifications_test.go @@ -201,12 +201,13 @@ func TestWebhookDispatch(t *testing.T) { require.NoError(t, err) const ( - email = "bob@coder.com" - name = "Robert McBobbington" + email = "bob@coder.com" + name = "Robert McBobbington" + username = "bob" ) user := dbgen.User(t, db, database.User{ Email: email, - Username: "bob", + Username: username, Name: name, }) @@ -229,6 +230,7 @@ func TestWebhookDispatch(t *testing.T) { // UserName is coalesced from `name` and `username`; in this case `name` wins. // This is not strictly necessary for this test, but it's testing some side logic which is too small for its own test. require.Equal(t, payload.Payload.UserName, name) + require.Equal(t, payload.Payload.UserUsername, username) // Right now we don't have a way to query notification templates by ID in dbmem, and it's not necessary to add this // just to satisfy this test. We can safely assume that as long as this value is not empty that the given value was delivered. require.NotEmpty(t, payload.Payload.NotificationName) diff --git a/coderd/notifications/render/gotmpl_test.go b/coderd/notifications/render/gotmpl_test.go index 0cb95bccfcb43..ec2ec7ffe6237 100644 --- a/coderd/notifications/render/gotmpl_test.go +++ b/coderd/notifications/render/gotmpl_test.go @@ -42,10 +42,11 @@ func TestGoTemplate(t *testing.T) { name: "render workspace URL", in: `[{ "label": "View workspace", - "url": "{{ base_url }}/@{{.UserName}}/{{.Labels.name}}" + "url": "{{ base_url }}/@{{.UserUsername}}/{{.Labels.name}}" }]`, payload: types.MessagePayload{ - UserName: "johndoe", + UserName: "John Doe", + UserUsername: "johndoe", Labels: map[string]string{ "name": "my-workspace", }, diff --git a/coderd/notifications/types/payload.go b/coderd/notifications/types/payload.go index f6b18215e5357..ba666219af654 100644 --- a/coderd/notifications/types/payload.go +++ b/coderd/notifications/types/payload.go @@ -9,9 +9,10 @@ type MessagePayload struct { NotificationName string `json:"notification_name"` - UserID string `json:"user_id"` - UserEmail string `json:"user_email"` - UserName string `json:"user_name"` + UserID string `json:"user_id"` + UserEmail string `json:"user_email"` + UserName string `json:"user_name"` + UserUsername string `json:"user_username"` Actions []TemplateAction `json:"actions"` Labels map[string]string `json:"labels"`