From 12420260ef35068c7244313d4a840f62848a84e1 Mon Sep 17 00:00:00 2001 From: idafurjes <36131195+idafurjes@users.noreply.github.com> Date: Mon, 31 Jan 2022 17:24:52 +0100 Subject: [PATCH] Remove bus from org invite api (#44530) * Remove bus from org invite api * Fix lint * Remove comment --- pkg/api/api.go | 8 +- pkg/api/org_invite.go | 46 +- pkg/api/signup.go | 4 +- .../ngalert/notifier/channels/email_test.go | 10 +- .../ngalert/notifier/channels/testing.go | 9 +- pkg/services/notifications/mock.go | 17 +- pkg/services/notifications/notifications.go | 11 +- .../send_email_integration_test.go | 2 +- .../alerting/api_notification_channel_test.go | 622 +++++++++--------- 9 files changed, 373 insertions(+), 356 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 515a3caa8ff..ea6c3859c08 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -120,7 +120,7 @@ func (hs *HTTPServer) registerRoutes() { r.Post("/api/user/signup/step2", routing.Wrap(hs.SignUpStep2)) // invited - r.Get("/api/user/invite/:code", routing.Wrap(GetInviteInfoByCode)) + r.Get("/api/user/invite/:code", routing.Wrap(hs.GetInviteInfoByCode)) r.Post("/api/user/invite/complete", routing.Wrap(hs.CompleteInvite)) // reset password @@ -216,9 +216,9 @@ func (hs *HTTPServer) registerRoutes() { orgRoute.Delete("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUserForCurrentOrg)) // invites - orgRoute.Get("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(GetPendingOrgInvites)) - orgRoute.Post("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), quota("user"), routing.Wrap(AddOrgInvite)) - orgRoute.Patch("/invites/:code/revoke", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(RevokeInvite)) + orgRoute.Get("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(hs.GetPendingOrgInvites)) + orgRoute.Post("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), quota("user"), routing.Wrap(hs.AddOrgInvite)) + orgRoute.Patch("/invites/:code/revoke", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(hs.RevokeInvite)) // prefs orgRoute.Get("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsPreferencesRead)), routing.Wrap(hs.GetOrgPreferences)) diff --git a/pkg/api/org_invite.go b/pkg/api/org_invite.go index 651af77e244..957053455dd 100644 --- a/pkg/api/org_invite.go +++ b/pkg/api/org_invite.go @@ -17,10 +17,10 @@ import ( "github.com/grafana/grafana/pkg/web" ) -func GetPendingOrgInvites(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetPendingOrgInvites(c *models.ReqContext) response.Response { query := models.GetTempUsersQuery{OrgId: c.OrgId, Status: models.TmpUserInvitePending} - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetTempUsersQuery(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to get invites from db", err) } @@ -31,7 +31,7 @@ func GetPendingOrgInvites(c *models.ReqContext) response.Response { return response.JSON(200, query.Result) } -func AddOrgInvite(c *models.ReqContext) response.Response { +func (hs *HTTPServer) AddOrgInvite(c *models.ReqContext) response.Response { inviteDto := dtos.AddInviteForm{} if err := web.Bind(c.Req, &inviteDto); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) @@ -42,12 +42,12 @@ func AddOrgInvite(c *models.ReqContext) response.Response { // first try get existing user userQuery := models.GetUserByLoginQuery{LoginOrEmail: inviteDto.LoginOrEmail} - if err := bus.Dispatch(c.Req.Context(), &userQuery); err != nil { + if err := hs.SQLStore.GetUserByLogin(c.Req.Context(), &userQuery); err != nil { if !errors.Is(err, models.ErrUserNotFound) { return response.Error(500, "Failed to query db for existing user check", err) } } else { - return inviteExistingUserToOrg(c, userQuery.Result, &inviteDto) + return hs.inviteExistingUserToOrg(c, userQuery.Result, &inviteDto) } if setting.DisableLoginForm { @@ -68,7 +68,7 @@ func AddOrgInvite(c *models.ReqContext) response.Response { cmd.Role = inviteDto.Role cmd.RemoteAddr = c.Req.RemoteAddr - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.CreateTempUser(c.Req.Context(), &cmd); err != nil { return response.Error(500, "Failed to save invite to database", err) } @@ -86,7 +86,7 @@ func AddOrgInvite(c *models.ReqContext) response.Response { }, } - if err := bus.Dispatch(c.Req.Context(), &emailCmd); err != nil { + if err := hs.AlertNG.NotificationService.SendEmailCommandHandler(c.Req.Context(), &emailCmd); err != nil { if errors.Is(err, models.ErrSmtpNotEnabled) { return response.Error(412, err.Error(), err) } @@ -95,7 +95,7 @@ func AddOrgInvite(c *models.ReqContext) response.Response { } emailSentCmd := models.UpdateTempUserWithEmailSentCommand{Code: cmd.Result.Code} - if err := bus.Dispatch(c.Req.Context(), &emailSentCmd); err != nil { + if err := hs.SQLStore.UpdateTempUserWithEmailSent(c.Req.Context(), &emailSentCmd); err != nil { return response.Error(500, "Failed to update invite with email sent info", err) } @@ -105,10 +105,10 @@ func AddOrgInvite(c *models.ReqContext) response.Response { return response.Success(fmt.Sprintf("Created invite for %s", inviteDto.LoginOrEmail)) } -func inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto *dtos.AddInviteForm) response.Response { +func (hs *HTTPServer) inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto *dtos.AddInviteForm) response.Response { // user exists, add org role createOrgUserCmd := models.AddOrgUserCommand{OrgId: c.OrgId, UserId: user.Id, Role: inviteDto.Role} - if err := bus.Dispatch(c.Req.Context(), &createOrgUserCmd); err != nil { + if err := hs.SQLStore.AddOrgUser(c.Req.Context(), &createOrgUserCmd); err != nil { if errors.Is(err, models.ErrOrgUserAlreadyAdded) { return response.Error(412, fmt.Sprintf("User %s is already added to organization", inviteDto.LoginOrEmail), err) } @@ -126,7 +126,7 @@ func inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto }, } - if err := bus.Dispatch(c.Req.Context(), &emailCmd); err != nil { + if err := hs.AlertNG.NotificationService.SendEmailCommandHandler(c.Req.Context(), &emailCmd); err != nil { return response.Error(500, "Failed to send email invited_to_org", err) } } @@ -137,8 +137,8 @@ func inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto }) } -func RevokeInvite(c *models.ReqContext) response.Response { - if ok, rsp := updateTempUserStatus(c.Req.Context(), web.Params(c.Req)[":code"], models.TmpUserRevoked); !ok { +func (hs *HTTPServer) RevokeInvite(c *models.ReqContext) response.Response { + if ok, rsp := hs.updateTempUserStatus(c.Req.Context(), web.Params(c.Req)[":code"], models.TmpUserRevoked); !ok { return rsp } @@ -148,9 +148,9 @@ func RevokeInvite(c *models.ReqContext) response.Response { // GetInviteInfoByCode gets a pending user invite corresponding to a certain code. // A response containing an InviteInfo object is returned if the invite is found. // If a (pending) invite is not found, 404 is returned. -func GetInviteInfoByCode(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetInviteInfoByCode(c *models.ReqContext) response.Response { query := models.GetTempUserByCodeQuery{Code: web.Params(c.Req)[":code"]} - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetTempUserByCode(c.Req.Context(), &query); err != nil { if errors.Is(err, models.ErrTempUserNotFound) { return response.Error(404, "Invite not found", nil) } @@ -177,7 +177,7 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext) response.Response { } query := models.GetTempUserByCodeQuery{Code: completeInvite.InviteCode} - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetTempUserByCode(c.Req.Context(), &query); err != nil { if errors.Is(err, models.ErrTempUserNotFound) { return response.Error(404, "Invite not found", nil) } @@ -213,7 +213,7 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext) response.Response { return response.Error(500, "failed to publish event", err) } - if ok, rsp := applyUserInvite(c.Req.Context(), user, invite, true); !ok { + if ok, rsp := hs.applyUserInvite(c.Req.Context(), user, invite, true); !ok { return rsp } @@ -231,33 +231,33 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext) response.Response { }) } -func updateTempUserStatus(ctx context.Context, code string, status models.TempUserStatus) (bool, response.Response) { +func (hs *HTTPServer) updateTempUserStatus(ctx context.Context, code string, status models.TempUserStatus) (bool, response.Response) { // update temp user status updateTmpUserCmd := models.UpdateTempUserStatusCommand{Code: code, Status: status} - if err := bus.Dispatch(ctx, &updateTmpUserCmd); err != nil { + if err := hs.SQLStore.UpdateTempUserStatus(ctx, &updateTmpUserCmd); err != nil { return false, response.Error(500, "Failed to update invite status", err) } return true, nil } -func applyUserInvite(ctx context.Context, user *models.User, invite *models.TempUserDTO, setActive bool) (bool, response.Response) { +func (hs *HTTPServer) applyUserInvite(ctx context.Context, user *models.User, invite *models.TempUserDTO, setActive bool) (bool, response.Response) { // add to org addOrgUserCmd := models.AddOrgUserCommand{OrgId: invite.OrgId, UserId: user.Id, Role: invite.Role} - if err := bus.Dispatch(ctx, &addOrgUserCmd); err != nil { + if err := hs.SQLStore.AddOrgUser(ctx, &addOrgUserCmd); err != nil { if !errors.Is(err, models.ErrOrgUserAlreadyAdded) { return false, response.Error(500, "Error while trying to create org user", err) } } // update temp user status - if ok, rsp := updateTempUserStatus(ctx, invite.Code, models.TmpUserCompleted); !ok { + if ok, rsp := hs.updateTempUserStatus(ctx, invite.Code, models.TmpUserCompleted); !ok { return false, rsp } if setActive { // set org to active - if err := bus.Dispatch(ctx, &models.SetUsingOrgCommand{OrgId: invite.OrgId, UserId: user.Id}); err != nil { + if err := hs.SQLStore.SetUsingOrg(ctx, &models.SetUsingOrgCommand{OrgId: invite.OrgId, UserId: user.Id}); err != nil { return false, response.Error(500, "Failed to set org as active", err) } } diff --git a/pkg/api/signup.go b/pkg/api/signup.go index c38822213b4..f3568d03daf 100644 --- a/pkg/api/signup.go +++ b/pkg/api/signup.go @@ -110,7 +110,7 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext) response.Response { } // mark temp user as completed - if ok, rsp := updateTempUserStatus(c.Req.Context(), form.Code, models.TmpUserCompleted); !ok { + if ok, rsp := hs.updateTempUserStatus(c.Req.Context(), form.Code, models.TmpUserCompleted); !ok { return rsp } @@ -122,7 +122,7 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext) response.Response { apiResponse := util.DynMap{"message": "User sign up completed successfully", "code": "redirect-to-landing-page"} for _, invite := range invitesQuery.Result { - if ok, rsp := applyUserInvite(c.Req.Context(), user, invite, false); !ok { + if ok, rsp := hs.applyUserInvite(c.Req.Context(), user, invite, false); !ok { return rsp } apiResponse["code"] = "redirect-to-select-org" diff --git a/pkg/services/ngalert/notifier/channels/email_test.go b/pkg/services/ngalert/notifier/channels/email_test.go index c2ef2879e49..42a738ba196 100644 --- a/pkg/services/ngalert/notifier/channels/email_test.go +++ b/pkg/services/ngalert/notifier/channels/email_test.go @@ -66,11 +66,11 @@ func TestEmailNotifier(t *testing.T) { require.True(t, ok) expected := map[string]interface{}{ - "subject": emailSender.Email.Subject, - "to": emailSender.Email.To, - "single_email": emailSender.Email.SingleEmail, - "template": emailSender.Email.Template, - "data": emailSender.Email.Data, + "subject": emailSender.EmailSync.Subject, + "to": emailSender.EmailSync.To, + "single_email": emailSender.EmailSync.SingleEmail, + "template": emailSender.EmailSync.Template, + "data": emailSender.EmailSync.Data, } require.Equal(t, map[string]interface{}{ "subject": "[FIRING:1] (AlwaysFiring warning)", diff --git a/pkg/services/ngalert/notifier/channels/testing.go b/pkg/services/ngalert/notifier/channels/testing.go index 04eecfc53e7..3fac1346bc6 100644 --- a/pkg/services/ngalert/notifier/channels/testing.go +++ b/pkg/services/ngalert/notifier/channels/testing.go @@ -29,7 +29,8 @@ func resetTimeNow() { type notificationServiceMock struct { Webhook models.SendWebhookSync - Email models.SendEmailCommandSync + EmailSync models.SendEmailCommandSync + Emailx models.SendEmailCommand ShouldError error } @@ -38,7 +39,11 @@ func (ns *notificationServiceMock) SendWebhookSync(ctx context.Context, cmd *mod return ns.ShouldError } func (ns *notificationServiceMock) SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error { - ns.Email = *cmd + ns.EmailSync = *cmd + return ns.ShouldError +} +func (ns *notificationServiceMock) SendEmailCommandHandler(ctx context.Context, cmd *models.SendEmailCommand) error { + ns.Emailx = *cmd return ns.ShouldError } diff --git a/pkg/services/notifications/mock.go b/pkg/services/notifications/mock.go index e8da638a85a..14229fc797d 100644 --- a/pkg/services/notifications/mock.go +++ b/pkg/services/notifications/mock.go @@ -8,11 +8,13 @@ import ( type NotificationServiceMock struct { Webhook models.SendWebhookSync - Email models.SendEmailCommandSync + EmailSync models.SendEmailCommandSync + Email models.SendEmailCommand ShouldError error - WebhookHandler func(context.Context, *models.SendWebhookSync) error - EmailHandler func(context.Context, *models.SendEmailCommandSync) error + WebhookHandler func(context.Context, *models.SendWebhookSync) error + EmailHandlerSync func(context.Context, *models.SendEmailCommandSync) error + EmailHandler func(context.Context, *models.SendEmailCommand) error } func (ns *NotificationServiceMock) SendWebhookSync(ctx context.Context, cmd *models.SendWebhookSync) error { @@ -22,7 +24,16 @@ func (ns *NotificationServiceMock) SendWebhookSync(ctx context.Context, cmd *mod } return ns.ShouldError } + func (ns *NotificationServiceMock) SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error { + ns.EmailSync = *cmd + if ns.EmailHandlerSync != nil { + return ns.EmailHandlerSync(ctx, cmd) + } + return ns.ShouldError +} + +func (ns *NotificationServiceMock) SendEmailCommandHandler(ctx context.Context, cmd *models.SendEmailCommand) error { ns.Email = *cmd if ns.EmailHandler != nil { return ns.EmailHandler(ctx, cmd) diff --git a/pkg/services/notifications/notifications.go b/pkg/services/notifications/notifications.go index 6fe5e51185c..eae202d6a04 100644 --- a/pkg/services/notifications/notifications.go +++ b/pkg/services/notifications/notifications.go @@ -22,6 +22,7 @@ type WebhookSender interface { } type EmailSender interface { SendEmailCommandHandlerSync(ctx context.Context, cmd *models.SendEmailCommandSync) error + SendEmailCommandHandler(ctx context.Context, cmd *models.SendEmailCommand) error } type Service interface { WebhookSender @@ -45,7 +46,7 @@ func ProvideService(bus bus.Bus, cfg *setting.Cfg, mailer Mailer) (*Notification ns.Bus.AddHandler(ns.sendResetPasswordEmail) ns.Bus.AddHandler(ns.validateResetPasswordCode) - ns.Bus.AddHandler(ns.sendEmailCommandHandler) + ns.Bus.AddHandler(ns.SendEmailCommandHandler) ns.Bus.AddHandler(ns.SendEmailCommandHandlerSync) ns.Bus.AddHandler(ns.SendWebhookSync) @@ -151,7 +152,7 @@ func (ns *NotificationService) SendEmailCommandHandlerSync(ctx context.Context, return err } -func (ns *NotificationService) sendEmailCommandHandler(ctx context.Context, cmd *models.SendEmailCommand) error { +func (ns *NotificationService) SendEmailCommandHandler(ctx context.Context, cmd *models.SendEmailCommand) error { message, err := ns.buildEmailMessage(cmd) if err != nil { @@ -167,7 +168,7 @@ func (ns *NotificationService) sendResetPasswordEmail(ctx context.Context, cmd * if err != nil { return err } - return ns.sendEmailCommandHandler(ctx, &models.SendEmailCommand{ + return ns.SendEmailCommandHandler(ctx, &models.SendEmailCommand{ To: []string{cmd.User.Email}, Template: tmplResetPassword, Data: map[string]interface{}{ @@ -211,7 +212,7 @@ func (ns *NotificationService) signUpStartedHandler(ctx context.Context, evt *ev return nil } - err := ns.sendEmailCommandHandler(ctx, &models.SendEmailCommand{ + err := ns.SendEmailCommandHandler(ctx, &models.SendEmailCommand{ To: []string{evt.Email}, Template: tmplSignUpStarted, Data: map[string]interface{}{ @@ -234,7 +235,7 @@ func (ns *NotificationService) signUpCompletedHandler(ctx context.Context, evt * return nil } - return ns.sendEmailCommandHandler(ctx, &models.SendEmailCommand{ + return ns.SendEmailCommandHandler(ctx, &models.SendEmailCommand{ To: []string{evt.Email}, Template: tmplWelcomeOnSignUp, Data: map[string]interface{}{ diff --git a/pkg/services/notifications/send_email_integration_test.go b/pkg/services/notifications/send_email_integration_test.go index ba9ae8e5dbb..d4ab18ec24f 100644 --- a/pkg/services/notifications/send_email_integration_test.go +++ b/pkg/services/notifications/send_email_integration_test.go @@ -57,7 +57,7 @@ func TestEmailIntegrationTest(t *testing.T) { Template: "alert_notification", } - err := ns.sendEmailCommandHandler(context.Background(), cmd) + err := ns.SendEmailCommandHandler(context.Background(), cmd) require.NoError(t, err) sentMsg := <-ns.mailQueue diff --git a/pkg/tests/api/alerting/api_notification_channel_test.go b/pkg/tests/api/alerting/api_notification_channel_test.go index fea13dad135..e519221ca75 100644 --- a/pkg/tests/api/alerting/api_notification_channel_test.go +++ b/pkg/tests/api/alerting/api_notification_channel_test.go @@ -53,8 +53,8 @@ func TestTestReceivers(t *testing.T) { testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) // nolint resp := postRequest(t, testReceiversURL, `{ - "receivers": [] -}`, http.StatusBadRequest) + "receivers": [] + }`, http.StatusBadRequest) t.Cleanup(func() { err := resp.Body.Close() require.NoError(t, err) @@ -84,27 +84,27 @@ func TestTestReceivers(t *testing.T) { }) mockEmails := &mockEmailHandler{} - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) // nolint resp := postRequest(t, testReceiversURL, `{ - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid": "", - "name": "receiver-1", - "type": "email", - "disableResolveMessage": false, - "settings": { - "addresses":"example@email.com" - }, - "secureFields": {} - } - ] - }] -}`, http.StatusOK) + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid": "", + "name": "receiver-1", + "type": "email", + "disableResolveMessage": false, + "settings": { + "addresses":"example@email.com" + }, + "secureFields": {} + } + ] + }] + }`, http.StatusOK) t.Cleanup(func() { err := resp.Body.Close() require.NoError(t, err) @@ -119,28 +119,28 @@ func TestTestReceivers(t *testing.T) { require.Len(t, result.Receivers[0].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "summary": "Notification test", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "alertname": "TestAlert", - "instance": "Grafana" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "ok" + "alert": { + "annotations": { + "summary": "Notification test", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "TestAlert", + "instance": "Grafana" } - ] - }], - "notified_at": "%s" -}`, + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "ok" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) require.JSONEq(t, expectedJSON, string(b)) @@ -168,25 +168,25 @@ func TestTestReceivers(t *testing.T) { }) mockEmails := &mockEmailHandler{} - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) // nolint resp := postRequest(t, testReceiversURL, `{ - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid": "", - "name": "receiver-1", - "type": "email", - "disableResolveMessage": false, - "settings": {}, - "secureFields": {} - } - ] - }] -}`, http.StatusBadRequest) + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid": "", + "name": "receiver-1", + "type": "email", + "disableResolveMessage": false, + "settings": {}, + "secureFields": {} + } + ] + }] + }`, http.StatusBadRequest) t.Cleanup(func() { require.NoError(t, resp.Body.Close()) }) @@ -200,29 +200,29 @@ func TestTestReceivers(t *testing.T) { require.Len(t, result.Receivers[0].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "summary": "Notification test", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "alertname": "TestAlert", - "instance": "Grafana" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "failed", - "error": "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings" + "alert": { + "annotations": { + "summary": "Notification test", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "TestAlert", + "instance": "Grafana" } - ] - }], - "notified_at": "%s" -}`, + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "failed", + "error": "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) require.JSONEq(t, expectedJSON, string(b)) @@ -249,26 +249,26 @@ func TestTestReceivers(t *testing.T) { mockEmails := &mockEmailHandlerWithTimeout{ timeout: 5 * time.Second, } - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) req, err := http.NewRequest(http.MethodPost, testReceiversURL, strings.NewReader(`{ - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid": "", - "name": "receiver-1", - "type": "email", - "disableResolveMessage": false, - "settings": { - "addresses":"example@email.com" - }, - "secureFields": {} - } - ] - }] -}`)) + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid": "", + "name": "receiver-1", + "type": "email", + "disableResolveMessage": false, + "settings": { + "addresses":"example@email.com" + }, + "secureFields": {} + } + ] + }] + }`)) require.NoError(t, err) req.Header.Set("Content-Type", "application/json") req.Header.Set("Request-Timeout", "1") @@ -289,29 +289,29 @@ func TestTestReceivers(t *testing.T) { require.Len(t, result.Receivers[0].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "summary": "Notification test", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "alertname": "TestAlert", - "instance": "Grafana" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "failed", - "error": "the receiver timed out: context deadline exceeded" + "alert": { + "annotations": { + "summary": "Notification test", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "TestAlert", + "instance": "Grafana" } - ] - }], - "notified_at": "%s" -}`, + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "failed", + "error": "the receiver timed out: context deadline exceeded" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) require.JSONEq(t, expectedJSON, string(b)) @@ -338,38 +338,38 @@ func TestTestReceivers(t *testing.T) { mockEmails := &mockEmailHandlerWithTimeout{ timeout: 5 * time.Second, } - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) req, err := http.NewRequest(http.MethodPost, testReceiversURL, strings.NewReader(`{ - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid": "", - "name": "receiver-1", - "type": "email", - "disableResolveMessage": false, - "settings": {}, - "secureFields": {} - } - ] - }, { - "name":"receiver-2", - "grafana_managed_receiver_configs": [ - { - "uid": "", - "name": "receiver-2", - "type": "email", - "disableResolveMessage": false, - "settings": { - "addresses":"example@email.com" - }, - "secureFields": {} - } - ] - }] -}`)) + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid": "", + "name": "receiver-1", + "type": "email", + "disableResolveMessage": false, + "settings": {}, + "secureFields": {} + } + ] + }, { + "name":"receiver-2", + "grafana_managed_receiver_configs": [ + { + "uid": "", + "name": "receiver-2", + "type": "email", + "disableResolveMessage": false, + "settings": { + "addresses":"example@email.com" + }, + "secureFields": {} + } + ] + }] + }`)) require.NoError(t, err) req.Header.Set("Content-Type", "application/json") req.Header.Set("Request-Timeout", "1") @@ -391,39 +391,39 @@ func TestTestReceivers(t *testing.T) { require.Len(t, result.Receivers[1].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "summary": "Notification test", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + "alert": { + "annotations": { + "summary": "Notification test", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "TestAlert", + "instance": "Grafana" + } }, - "labels": { - "alertname": "TestAlert", - "instance": "Grafana" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "failed", - "error": "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings" - } - ] - }, { - "name":"receiver-2", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-2", - "uid": "%s", - "status": "failed", - "error": "the receiver timed out: context deadline exceeded" - } - ] - }], - "notified_at": "%s" -}`, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "failed", + "error": "the receiver is invalid: failed to validate receiver \"receiver-1\" of type \"email\": could not find addresses in settings" + } + ] + }, { + "name":"receiver-2", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-2", + "uid": "%s", + "status": "failed", + "error": "the receiver timed out: context deadline exceeded" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.Receivers[1].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) @@ -451,36 +451,36 @@ func TestTestReceiversAlertCustomization(t *testing.T) { }) mockEmails := &mockEmailHandler{} - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) // nolint resp := postRequest(t, testReceiversURL, `{ - "alert": { - "annotations": { - "annotation1": "value1", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "label1": "value1" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid":"", - "name":"receiver-1", - "type":"email", - "disableResolveMessage":false, - "settings":{ - "addresses":"example@email.com" - }, - "secureFields":{} + "alert": { + "annotations": { + "annotation1": "value1", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "label1": "value1" } - ] - }] -}`, http.StatusOK) + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid":"", + "name":"receiver-1", + "type":"email", + "disableResolveMessage":false, + "settings":{ + "addresses":"example@email.com" + }, + "secureFields":{} + } + ] + }] + }`, http.StatusOK) t.Cleanup(func() { err := resp.Body.Close() require.NoError(t, err) @@ -495,30 +495,30 @@ func TestTestReceiversAlertCustomization(t *testing.T) { require.Len(t, result.Receivers[0].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "annotation1": "value1", - "summary": "Notification test", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "alertname": "TestAlert", - "instance": "Grafana", - "label1": "value1" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "ok" + "alert": { + "annotations": { + "annotation1": "value1", + "summary": "Notification test", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "TestAlert", + "instance": "Grafana", + "label1": "value1" } - ] - }], - "notified_at": "%s" -}`, + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "ok" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) require.JSONEq(t, expectedJSON, string(b)) @@ -546,33 +546,33 @@ func TestTestReceiversAlertCustomization(t *testing.T) { }) mockEmails := &mockEmailHandler{} - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) // nolint resp := postRequest(t, testReceiversURL, `{ - "alert": { - "annotations": { - "summary": "This is a custom annotation", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid":"", - "name":"receiver-1", - "type":"email", - "disableResolveMessage":false, - "settings":{ - "addresses":"example@email.com" - }, - "secureFields":{} + "alert": { + "annotations": { + "summary": "This is a custom annotation", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" } - ] - }] -}`, http.StatusOK) + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid":"", + "name":"receiver-1", + "type":"email", + "disableResolveMessage":false, + "settings":{ + "addresses":"example@email.com" + }, + "secureFields":{} + } + ] + }] + }`, http.StatusOK) t.Cleanup(func() { err := resp.Body.Close() require.NoError(t, err) @@ -587,28 +587,28 @@ func TestTestReceiversAlertCustomization(t *testing.T) { require.Len(t, result.Receivers[0].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "summary": "This is a custom annotation", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "alertname": "TestAlert", - "instance": "Grafana" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "ok" + "alert": { + "annotations": { + "summary": "This is a custom annotation", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "TestAlert", + "instance": "Grafana" } - ] - }], - "notified_at": "%s" -}`, + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "ok" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) require.JSONEq(t, expectedJSON, string(b)) @@ -636,32 +636,32 @@ func TestTestReceiversAlertCustomization(t *testing.T) { }) mockEmails := &mockEmailHandler{} - env.NotificationService.EmailHandler = mockEmails.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmails.sendEmailCommandHandlerSync testReceiversURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/receivers/test", grafanaListedAddr) // nolint resp := postRequest(t, testReceiversURL, `{ - "alert": { - "labels": { - "alertname": "This is a custom label" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "uid":"", - "name":"receiver-1", - "type":"email", - "disableResolveMessage":false, - "settings":{ - "addresses":"example@email.com" - }, - "secureFields":{} + "alert": { + "labels": { + "alertname": "This is a custom label" } - ] - }] -}`, http.StatusOK) + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "uid":"", + "name":"receiver-1", + "type":"email", + "disableResolveMessage":false, + "settings":{ + "addresses":"example@email.com" + }, + "secureFields":{} + } + ] + }] + }`, http.StatusOK) t.Cleanup(func() { err := resp.Body.Close() require.NoError(t, err) @@ -676,28 +676,28 @@ func TestTestReceiversAlertCustomization(t *testing.T) { require.Len(t, result.Receivers[0].Configs, 1) expectedJSON := fmt.Sprintf(`{ - "alert": { - "annotations": { - "summary": "Notification test", - "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" - }, - "labels": { - "alertname": "This is a custom label", - "instance": "Grafana" - } - }, - "receivers": [{ - "name":"receiver-1", - "grafana_managed_receiver_configs": [ - { - "name": "receiver-1", - "uid": "%s", - "status": "ok" + "alert": { + "annotations": { + "summary": "Notification test", + "__value_string__": "[ metric='foo' labels={instance=bar} value=10 ]" + }, + "labels": { + "alertname": "This is a custom label", + "instance": "Grafana" } - ] - }], - "notified_at": "%s" -}`, + }, + "receivers": [{ + "name":"receiver-1", + "grafana_managed_receiver_configs": [ + { + "name": "receiver-1", + "uid": "%s", + "status": "ok" + } + ] + }], + "notified_at": "%s" + }`, result.Receivers[0].Configs[0].UID, result.NotifiedAt.Format(time.RFC3339Nano)) require.JSONEq(t, expectedJSON, string(b)) @@ -744,7 +744,7 @@ func TestNotificationChannels(t *testing.T) { channels.ThreemaGwBaseURL = fmt.Sprintf("http://%s/threema_recv/threema_test", mockChannel.server.Addr) channels.GetBoundary = func() string { return "abcd" } - env.NotificationService.EmailHandler = mockEmail.sendEmailCommandHandlerSync + env.NotificationService.EmailHandlerSync = mockEmail.sendEmailCommandHandlerSync // As we are using a NotificationService mock here, but he test expects real NotificationService - // we try to issue a real POST request here env.NotificationService.WebhookHandler = func(_ context.Context, cmd *models.SendWebhookSync) error {