diff --git a/pkg/services/publicdashboards/api/query.go b/pkg/services/publicdashboards/api/query.go index a5ef7eea240..39ea9ccfb60 100644 --- a/pkg/services/publicdashboards/api/query.go +++ b/pkg/services/publicdashboards/api/query.go @@ -21,7 +21,7 @@ func (api *Api) ViewPublicDashboard(c *contextmodel.ReqContext) response.Respons return response.Err(ErrInvalidAccessToken.Errorf("ViewPublicDashboard: invalid access token")) } - pubdash, dash, err := api.PublicDashboardService.FindPublicDashboardAndDashboardByAccessToken( + pubdash, dash, err := api.PublicDashboardService.FindEnabledPublicDashboardAndDashboardByAccessToken( c.Req.Context(), accessToken, ) diff --git a/pkg/services/publicdashboards/api/query_test.go b/pkg/services/publicdashboards/api/query_test.go index 5db699d08c0..7b44066d721 100644 --- a/pkg/services/publicdashboards/api/query_test.go +++ b/pkg/services/publicdashboards/api/query_test.go @@ -83,7 +83,7 @@ func TestAPIViewPublicDashboard(t *testing.T) { for _, test := range testCases { t.Run(test.Name, func(t *testing.T) { service := publicdashboards.NewFakePublicDashboardService(t) - service.On("FindPublicDashboardAndDashboardByAccessToken", mock.Anything, mock.AnythingOfType("string")). + service.On("FindEnabledPublicDashboardAndDashboardByAccessToken", mock.Anything, mock.AnythingOfType("string")). Return(&PublicDashboard{Uid: "pubdashuid"}, test.DashboardResult, test.Err).Maybe() cfg := setting.NewCfg() diff --git a/pkg/services/publicdashboards/public_dashboard_service_mock.go b/pkg/services/publicdashboards/public_dashboard_service_mock.go index a0bd21ac7e5..3b5d0c6815e 100644 --- a/pkg/services/publicdashboards/public_dashboard_service_mock.go +++ b/pkg/services/publicdashboards/public_dashboard_service_mock.go @@ -254,6 +254,38 @@ func (_m *FakePublicDashboardService) FindDashboard(ctx context.Context, orgId i return r0, r1 } +// FindEnabledDashboardAndDashboardByAccessToken provides a mock function with given fields: ctx, accessToken +func (_m *FakePublicDashboardService) FindEnabledPublicDashboardAndDashboardByAccessToken(ctx context.Context, accessToken string) (*models.PublicDashboard, *dashboards.Dashboard, error) { + ret := _m.Called(ctx, accessToken) + + var r0 *models.PublicDashboard + if rf, ok := ret.Get(0).(func(context.Context, string) *models.PublicDashboard); ok { + r0 = rf(ctx, accessToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*models.PublicDashboard) + } + } + + var r1 *dashboards.Dashboard + if rf, ok := ret.Get(1).(func(context.Context, string) *dashboards.Dashboard); ok { + r1 = rf(ctx, accessToken) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*dashboards.Dashboard) + } + } + + var r2 error + if rf, ok := ret.Get(2).(func(context.Context, string) error); ok { + r2 = rf(ctx, accessToken) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // FindPublicDashboardAndDashboardByAccessToken provides a mock function with given fields: ctx, accessToken func (_m *FakePublicDashboardService) FindPublicDashboardAndDashboardByAccessToken(ctx context.Context, accessToken string) (*models.PublicDashboard, *dashboards.Dashboard, error) { ret := _m.Called(ctx, accessToken) diff --git a/pkg/services/publicdashboards/publicdashboard.go b/pkg/services/publicdashboards/publicdashboard.go index 93bb2e96b61..a1b69547dfa 100644 --- a/pkg/services/publicdashboards/publicdashboard.go +++ b/pkg/services/publicdashboards/publicdashboard.go @@ -16,6 +16,7 @@ import ( //go:generate mockery --name Service --structname FakePublicDashboardService --inpackage --filename public_dashboard_service_mock.go type Service interface { FindPublicDashboardAndDashboardByAccessToken(ctx context.Context, accessToken string) (*PublicDashboard, *dashboards.Dashboard, error) + FindEnabledPublicDashboardAndDashboardByAccessToken(ctx context.Context, accessToken string) (*PublicDashboard, *dashboards.Dashboard, error) FindByAccessToken(ctx context.Context, accessToken string) (*PublicDashboard, error) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error) FindAnnotations(ctx context.Context, reqDTO AnnotationsQueryDTO, accessToken string) ([]AnnotationEvent, error) diff --git a/pkg/services/publicdashboards/service/query.go b/pkg/services/publicdashboards/service/query.go index 9706253f163..2831090b93f 100644 --- a/pkg/services/publicdashboards/service/query.go +++ b/pkg/services/publicdashboards/service/query.go @@ -18,7 +18,7 @@ import ( // FindAnnotations returns annotations for a public dashboard func (pd *PublicDashboardServiceImpl) FindAnnotations(ctx context.Context, reqDTO models.AnnotationsQueryDTO, accessToken string) ([]models.AnnotationEvent, error) { - pub, dash, err := pd.FindPublicDashboardAndDashboardByAccessToken(ctx, accessToken) + pub, dash, err := pd.FindEnabledPublicDashboardAndDashboardByAccessToken(ctx, accessToken) if err != nil { return nil, err } @@ -119,7 +119,7 @@ func (pd *PublicDashboardServiceImpl) GetMetricRequest(ctx context.Context, dash // GetQueryDataResponse returns a query data response for the given panel and query func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context, skipCache bool, queryDto models.PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) { - publicDashboard, dashboard, err := pd.FindPublicDashboardAndDashboardByAccessToken(ctx, accessToken) + publicDashboard, dashboard, err := pd.FindEnabledPublicDashboardAndDashboardByAccessToken(ctx, accessToken) if err != nil { return nil, err } diff --git a/pkg/services/publicdashboards/service/service.go b/pkg/services/publicdashboards/service/service.go index 2c292f9e9f8..6cca9ab0ab0 100644 --- a/pkg/services/publicdashboards/service/service.go +++ b/pkg/services/publicdashboards/service/service.go @@ -105,6 +105,20 @@ func (pd *PublicDashboardServiceImpl) FindByAccessToken(ctx context.Context, acc return pubdash, nil } +// FindEnabledPublicDashboardAndDashboardByAccessToken Gets public dashboard and a dashboard by access token if public dashboard is enabled +func (pd *PublicDashboardServiceImpl) FindEnabledPublicDashboardAndDashboardByAccessToken(ctx context.Context, accessToken string) (*PublicDashboard, *dashboards.Dashboard, error) { + pubdash, dash, err := pd.FindPublicDashboardAndDashboardByAccessToken(ctx, accessToken) + if err != nil { + return pubdash, dash, err + } + + if !pubdash.IsEnabled { + return nil, nil, ErrPublicDashboardNotEnabled.Errorf("FindEnabledPublicDashboardAndDashboardByAccessToken: Public dashboard is not enabled accessToken: %s", accessToken) + } + + return pubdash, dash, err +} + // FindPublicDashboardAndDashboardByAccessToken Gets public dashboard and a dashboard by access token func (pd *PublicDashboardServiceImpl) FindPublicDashboardAndDashboardByAccessToken(ctx context.Context, accessToken string) (*PublicDashboard, *dashboards.Dashboard, error) { pubdash, err := pd.FindByAccessToken(ctx, accessToken) @@ -112,10 +126,6 @@ func (pd *PublicDashboardServiceImpl) FindPublicDashboardAndDashboardByAccessTok return nil, nil, err } - if !pubdash.IsEnabled { - return nil, nil, ErrPublicDashboardNotEnabled.Errorf("FindPublicDashboardAndDashboardByAccessToken: Public dashboard is paused accessToken: %s", accessToken) - } - dash, err := pd.store.FindDashboard(ctx, pubdash.OrgId, pubdash.DashboardUid) if err != nil { return nil, nil, err diff --git a/pkg/services/publicdashboards/service/service_test.go b/pkg/services/publicdashboards/service/service_test.go index 6ae0ef9568f..15fe107312c 100644 --- a/pkg/services/publicdashboards/service/service_test.go +++ b/pkg/services/publicdashboards/service/service_test.go @@ -67,15 +67,15 @@ func TestGetPublicDashboard(t *testing.T) { DashResp: &dashboards.Dashboard{UID: "mydashboard", Data: dashboardData}, }, { - Name: "returns ErrPublicDashboardNotFound when isEnabled is false", + Name: "returns dashboard when isEnabled is false", AccessToken: "abc123", StoreResp: &storeResp{ pd: &PublicDashboard{AccessToken: "abcdToken", IsEnabled: false}, - d: &dashboards.Dashboard{UID: "mydashboard"}, + d: &dashboards.Dashboard{UID: "mydashboard", Data: dashboardData}, err: nil, }, - ErrResp: ErrPublicDashboardNotFound, - DashResp: nil, + ErrResp: nil, + DashResp: &dashboards.Dashboard{UID: "mydashboard", Data: dashboardData}, }, { Name: "returns ErrPublicDashboardNotFound if PublicDashboard missing", @@ -121,6 +121,72 @@ func TestGetPublicDashboard(t *testing.T) { } } +func TestGetEnabledPublicDashboard(t *testing.T) { + type storeResp struct { + pd *PublicDashboard + d *dashboards.Dashboard + err error + } + + testCases := []struct { + Name string + AccessToken string + StoreResp *storeResp + ErrResp error + DashResp *dashboards.Dashboard + }{ + { + Name: "returns a dashboard", + AccessToken: "abc123", + StoreResp: &storeResp{ + pd: &PublicDashboard{AccessToken: "abcdToken", IsEnabled: true}, + d: &dashboards.Dashboard{UID: "mydashboard", Data: dashboardData}, + err: nil, + }, + ErrResp: nil, + DashResp: &dashboards.Dashboard{UID: "mydashboard", Data: dashboardData}, + }, + { + Name: "returns ErrPublicDashboardNotFound when isEnabled is false", + AccessToken: "abc123", + StoreResp: &storeResp{ + pd: &PublicDashboard{AccessToken: "abcdToken", IsEnabled: false}, + d: &dashboards.Dashboard{UID: "mydashboard"}, + err: nil, + }, + ErrResp: ErrPublicDashboardNotFound, + DashResp: nil, + }, + } + + for _, test := range testCases { + t.Run(test.Name, func(t *testing.T) { + fakeStore := FakePublicDashboardStore{} + service := &PublicDashboardServiceImpl{ + log: log.New("test.logger"), + store: &fakeStore, + } + + fakeStore.On("FindByAccessToken", mock.Anything, mock.Anything).Return(test.StoreResp.pd, test.StoreResp.err) + fakeStore.On("FindDashboard", mock.Anything, mock.Anything, mock.Anything).Return(test.StoreResp.d, test.StoreResp.err) + + pdc, dash, err := service.FindEnabledPublicDashboardAndDashboardByAccessToken(context.Background(), test.AccessToken) + if test.ErrResp != nil { + assert.Error(t, test.ErrResp, err) + } else { + require.NoError(t, err) + } + + assert.Equal(t, test.DashResp, dash) + + if test.DashResp != nil { + assert.NotNil(t, dash.CreatedBy) + assert.Equal(t, test.StoreResp.pd, pdc) + } + }) + } +} + // We're using sqlite here because testing all of the behaviors with mocks in // the correct order is convoluted. func TestCreatePublicDashboard(t *testing.T) {