| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httptest" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-13 12:11:35 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/apimachinery/identity" | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/infra/log/logtest" | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol" | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 	ac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol" | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/models" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/notifier" | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/notifier/legacy_storage" | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/user" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/web" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRouteGetReceiver(t *testing.T) { | 
					
						
							|  |  |  | 	fakeReceiverSvc := fakes.NewFakeReceiverService() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("returns expected model", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		expected := &models.Receiver{ | 
					
						
							|  |  |  | 			Name: "receiver1", | 
					
						
							|  |  |  | 			Integrations: []*models.Integration{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					UID:    "uid1", | 
					
						
							|  |  |  | 					Name:   "receiver1", | 
					
						
							|  |  |  | 					Config: models.IntegrationConfig{Type: "slack"}, | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) { | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 			return expected, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceiver(&rc, "receiver1") | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Status()) | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		gettables, err := GettableApiReceiverFromReceiver(expected) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		json, err := json.Marshal(gettables) | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.Equal(t, json, resp.Body()) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("builds query from request context and url param", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) { | 
					
						
							|  |  |  | 			return &models.Receiver{}, nil | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceiver(&rc, "receiver1") | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Status()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		call := fakeReceiverSvc.PopMethodCall() | 
					
						
							|  |  |  | 		require.Equal(t, "GetReceiver", call.Method) | 
					
						
							|  |  |  | 		expectedQ := models.GetReceiverQuery{ | 
					
						
							|  |  |  | 			Name:    "receiver1", | 
					
						
							|  |  |  | 			Decrypt: true, | 
					
						
							|  |  |  | 			OrgID:   1, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		require.Equal(t, expectedQ, call.Args[1]) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("should pass along not found response", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) { | 
					
						
							|  |  |  | 			return nil, legacy_storage.ErrReceiverNotFound.Errorf("") | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceiver(&rc, "receiver1") | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusNotFound, resp.Status()) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("should pass along permission denied response", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) { | 
					
						
							|  |  |  | 			return nil, ac.ErrAuthorizationBase.Errorf("") | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceiver(&rc, "receiver1") | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusForbidden, resp.Status()) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRouteGetReceivers(t *testing.T) { | 
					
						
							|  |  |  | 	fakeReceiverSvc := fakes.NewFakeReceiverService() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("returns expected model", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		expected := []*models.Receiver{ | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 				Name: "receiver1", | 
					
						
							|  |  |  | 				Integrations: []*models.Integration{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						UID:    "uid1", | 
					
						
							|  |  |  | 						Name:   "receiver1", | 
					
						
							|  |  |  | 						Config: models.IntegrationConfig{Type: "slack"}, | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.ListReceiversFn = func(ctx context.Context, q models.ListReceiversQuery, u identity.Requester) ([]*models.Receiver, error) { | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 			return expected, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Set("names", "receiver1") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceivers(&rc) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Status()) | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		gettables, err := GettableApiReceiversFromReceivers(expected) | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		jsonBody, err := json.Marshal(gettables) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.JSONEq(t, string(jsonBody), string(resp.Body())) | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("builds query from request context", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.ListReceiversFn = func(ctx context.Context, q models.ListReceiversQuery, u identity.Requester) ([]*models.Receiver, error) { | 
					
						
							|  |  |  | 			return nil, nil | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Set("names", "receiver1") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Add("names", "receiver2") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Set("limit", "1") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Set("offset", "2") | 
					
						
							|  |  |  | 		rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceivers(&rc) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Status()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		call := fakeReceiverSvc.PopMethodCall() | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 		require.Equal(t, "ListReceivers", call.Method) | 
					
						
							|  |  |  | 		expectedQ := models.ListReceiversQuery{ | 
					
						
							|  |  |  | 			Names:  []string{"receiver1", "receiver2"}, | 
					
						
							|  |  |  | 			Limit:  1, | 
					
						
							|  |  |  | 			Offset: 2, | 
					
						
							|  |  |  | 			OrgID:  1, | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		require.Equal(t, expectedQ, call.Args[1]) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("should pass along permission denied response", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		fakeReceiverSvc.ListReceiversFn = func(ctx context.Context, q models.ListReceiversQuery, u identity.Requester) ([]*models.Receiver, error) { | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 			return nil, ac.ErrAuthorizationBase.Errorf("") | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc)) | 
					
						
							|  |  |  | 		rc := testReqCtx("GET") | 
					
						
							|  |  |  | 		resp := handler.handleRouteGetReceivers(&rc) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusForbidden, resp.Status()) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | func TestRouteGetReceiversResponses(t *testing.T) { | 
					
						
							|  |  |  | 	createTestEnv := func(t *testing.T, testConfig string) testEnvironment { | 
					
						
							|  |  |  | 		env := createTestEnv(t, testConfig) | 
					
						
							|  |  |  | 		env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 			Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 				if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingNotificationsRead) { | 
					
						
							|  |  |  | 					return true, nil | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingReceiversList) { | 
					
						
							|  |  |  | 					return true, nil | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return false, nil | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return env | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("list receivers", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 			env := createTestEnv(t, testConfig) | 
					
						
							|  |  |  | 			sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetReceivers(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 			expectedListResponse := `[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b","name":"grafana-default-email","type":"email","disableResolveMessage":false,"secureFields":{}}]},{"name":"multiple integrations","grafana_managed_receiver_configs":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","name":"multiple integrations","type":"prometheus-alertmanager","disableResolveMessage":false,"secureFields":{}},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","name":"multiple integrations","type":"discord","disableResolveMessage":false,"secureFields":{}}]},{"name":"pagerduty test","grafana_managed_receiver_configs":[{"uid":"b9bf06f8-bde2-4438-9d4a-bba0522dcd4d","name":"pagerduty test","type":"pagerduty","disableResolveMessage":false,"secureFields":{}}]},{"name":"slack test","grafana_managed_receiver_configs":[{"uid":"cbfd0976-8228-4126-b672-4419f30a9e50","name":"slack test","type":"slack","disableResolveMessage":false,"secureFields":{}}]}]` | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 			t.Run("limit offset", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var expected []definitions.GettableApiReceiver | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 				err := json.Unmarshal([]byte(expectedListResponse), &expected) | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 				require.NoError(t, err) | 
					
						
							|  |  |  | 				type testcase struct { | 
					
						
							|  |  |  | 					limit    int | 
					
						
							|  |  |  | 					offset   int | 
					
						
							|  |  |  | 					expected []definitions.GettableApiReceiver | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				testcases := []testcase{ | 
					
						
							|  |  |  | 					{limit: 1, offset: 0, expected: expected[:1]}, | 
					
						
							|  |  |  | 					{limit: 2, offset: 0, expected: expected[:2]}, | 
					
						
							|  |  |  | 					{limit: 4, offset: 0, expected: expected[:4]}, | 
					
						
							|  |  |  | 					{limit: 1, offset: 1, expected: expected[1:2]}, | 
					
						
							|  |  |  | 					{limit: 2, offset: 2, expected: expected[2:4]}, | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 					{limit: 2, offset: 99, expected: []definitions.GettableApiReceiver{}}, | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 					{limit: 0, offset: 0, expected: expected}, | 
					
						
							|  |  |  | 					{limit: 0, offset: 1, expected: expected[1:]}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for _, tc := range testcases { | 
					
						
							|  |  |  | 					t.Run(fmt.Sprintf("limit %d offset %d", tc.limit, tc.offset), func(t *testing.T) { | 
					
						
							|  |  |  | 						rc.Context.Req.Form.Set("limit", strconv.Itoa(tc.limit)) | 
					
						
							|  |  |  | 						rc.Context.Req.Form.Set("offset", strconv.Itoa(tc.offset)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						response := sut.RouteGetReceivers(&rc) | 
					
						
							|  |  |  | 						require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						var configs []definitions.GettableApiReceiver | 
					
						
							|  |  |  | 						err := json.Unmarshal(response.Body(), &configs) | 
					
						
							|  |  |  | 						require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 						require.Equal(t, tc.expected, configs) | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 					}) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 			t.Run("decrypt false with read permissions, does not have settings", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetReceivers(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 				require.Equal(t, expectedListResponse, string(response.Body())) | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("decrypt false with only list permissions, does not have settings", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 					Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 						if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingReceiversList) { | 
					
						
							|  |  |  | 							return true, nil | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return false, nil | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetReceivers(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedListResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 			t.Run("decrypt true with all permissions, does not have settings", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 					Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 						return true, nil | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetReceivers(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							| 
									
										
										
										
											2024-08-05 23:49:23 +08:00
										 |  |  | 				require.Equal(t, expectedListResponse, string(response.Body())) | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("get receiver", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 			env := createTestEnv(t, testConfig) | 
					
						
							|  |  |  | 			sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetReceiver(&rc, "grafana-default-email") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("decrypt true without secrets:read permissions returns 403", func(t *testing.T) { | 
					
						
							|  |  |  | 			recPermCheck := false | 
					
						
							|  |  |  | 			env := createTestEnv(t, testConfig) | 
					
						
							|  |  |  | 			env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 				Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 					if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingReceiversReadSecrets) { | 
					
						
							|  |  |  | 						recPermCheck = true | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					return false, nil | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetReceiver(&rc, "grafana-default-email") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.True(t, recPermCheck) | 
					
						
							|  |  |  | 			require.Equal(t, 403, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 			expectedRedactedResponse := `{"name":"multiple integrations","grafana_managed_receiver_configs":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","name":"multiple integrations","type":"prometheus-alertmanager","disableResolveMessage":true,"settings":{"basicAuthPassword":"[REDACTED]","basicAuthUser":"test","url":"http://localhost:9093"},"secureFields":{"basicAuthPassword":true}},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","name":"multiple integrations","type":"discord","disableResolveMessage":false,"settings":{"avatar_url":"some avatar","url":"[REDACTED]","use_discord_username":true},"secureFields":{"url":true}}]}` | 
					
						
							|  |  |  | 			expectedDecryptedResponse := `{"name":"multiple integrations","grafana_managed_receiver_configs":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","name":"multiple integrations","type":"prometheus-alertmanager","disableResolveMessage":true,"settings":{"basicAuthPassword":"testpass","basicAuthUser":"test","url":"http://localhost:9093"},"secureFields":{"basicAuthPassword":true}},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","name":"multiple integrations","type":"discord","disableResolveMessage":false,"settings":{"avatar_url":"some avatar","url":"some url","use_discord_username":true},"secureFields":{"url":true}}]}` | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 			t.Run("decrypt false", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetReceiver(&rc, "multiple integrations") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedRedactedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("decrypt true", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 					Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 						return true, nil | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				sut := createNotificationSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetReceiver(&rc, "multiple integrations") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedDecryptedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func createNotificationSrvSutFromEnv(t *testing.T, env *testEnvironment) NotificationSrv { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	receiverSvc := notifier.NewReceiverService( | 
					
						
							| 
									
										
										
										
											2024-07-30 03:49:10 +08:00
										 |  |  | 		ac.NewReceiverAccess[*models.Receiver](env.ac, false), | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 		legacy_storage.NewAlertmanagerConfigStore(env.configs), | 
					
						
							|  |  |  | 		env.prov, | 
					
						
							| 
									
										
										
										
											2024-08-26 22:47:53 +08:00
										 |  |  | 		env.store, | 
					
						
							| 
									
										
										
										
											2024-07-27 05:45:33 +08:00
										 |  |  | 		env.secrets, | 
					
						
							|  |  |  | 		env.xact, | 
					
						
							|  |  |  | 		env.log, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	return NotificationSrv{ | 
					
						
							|  |  |  | 		logger:          env.log, | 
					
						
							|  |  |  | 		receiverService: receiverSvc, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 02:12:15 +08:00
										 |  |  | func newNotificationSrv(receiverService ReceiverService) *NotificationSrv { | 
					
						
							|  |  |  | 	return &NotificationSrv{ | 
					
						
							|  |  |  | 		logger:          log.NewNopLogger(), | 
					
						
							|  |  |  | 		receiverService: receiverService, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testReqCtx(method string) contextmodel.ReqContext { | 
					
						
							|  |  |  | 	return contextmodel.ReqContext{ | 
					
						
							|  |  |  | 		Context: &web.Context{ | 
					
						
							|  |  |  | 			Req: &http.Request{ | 
					
						
							|  |  |  | 				Header: make(http.Header), | 
					
						
							|  |  |  | 				Form:   make(url.Values), | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Resp: web.NewResponseWriter(method, httptest.NewRecorder()), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		SignedInUser: &user.SignedInUser{ | 
					
						
							|  |  |  | 			OrgID: 1, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Logger: &logtest.Fake{}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |