diff --git a/pkg/services/publicdashboards/api/query_test.go b/pkg/services/publicdashboards/api/query_test.go index 7b44066d721..26a5db68ee9 100644 --- a/pkg/services/publicdashboards/api/query_test.go +++ b/pkg/services/publicdashboards/api/query_test.go @@ -324,7 +324,7 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) store := publicdashboardsStore.ProvideStore(db) cfg := setting.NewCfg() ac := acmock.New() - ws := &publicdashboards.FakePublicDashboardServiceWrapper{} + ws := publicdashboardsService.ProvideServiceWrapper(store) cfg.RBACEnabled = false service := publicdashboardsService.ProvideService(cfg, store, qds, annotationsService, ac, ws) pubdash, err := service.Create(context.Background(), &user.SignedInUser{}, savePubDashboardCmd) diff --git a/pkg/services/publicdashboards/models/errors.go b/pkg/services/publicdashboards/models/errors.go index 7a122248440..b73217201cb 100644 --- a/pkg/services/publicdashboards/models/errors.go +++ b/pkg/services/publicdashboards/models/errors.go @@ -20,6 +20,7 @@ var ( ErrInvalidMaxDataPoints = errutil.NewBase(errutil.StatusBadRequest, "publicdashboards.maxDataPoints", errutil.WithPublicMessage("maxDataPoints should be greater than 0")) ErrInvalidTimeRange = errutil.NewBase(errutil.StatusBadRequest, "publicdashboards.invalidTimeRange", errutil.WithPublicMessage("Invalid time range")) ErrInvalidShareType = errutil.NewBase(errutil.StatusBadRequest, "publicdashboards.invalidShareType", errutil.WithPublicMessage("Invalid share type")) + ErrDashboardIsPublic = errutil.NewBase(errutil.StatusBadRequest, "publicdashboards.dashboardIsPublic", errutil.WithPublicMessage("Dashboard is already public")) ErrPublicDashboardNotEnabled = errutil.NewBase(errutil.StatusForbidden, "publicdashboards.notEnabled", errutil.WithPublicMessage("Public dashboard paused")) ) diff --git a/pkg/services/publicdashboards/service/query_test.go b/pkg/services/publicdashboards/service/query_test.go index ecc0aff01db..1ac490d1bff 100644 --- a/pkg/services/publicdashboards/service/query_test.go +++ b/pkg/services/publicdashboards/service/query_test.go @@ -651,7 +651,7 @@ func TestGetQueryDataResponse(t *testing.T) { dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotatest.New(false, nil)) require.NoError(t, err) publicdashboardStore := database.ProvideStore(sqlStore) - + serviceWrapper := ProvideServiceWrapper(publicdashboardStore) fakeQueryService := &query.FakeQueryService{} fakeQueryService.On("QueryData", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&backend.QueryDataResponse{}, nil) @@ -660,6 +660,7 @@ func TestGetQueryDataResponse(t *testing.T) { store: publicdashboardStore, intervalCalculator: intervalv2.NewCalculator(), QueryDataService: fakeQueryService, + serviceWrapper: serviceWrapper, } publicDashboardQueryDTO := PublicDashboardQueryDTO{ @@ -1180,7 +1181,7 @@ func TestBuildMetricRequest(t *testing.T) { dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotatest.New(false, nil)) require.NoError(t, err) publicdashboardStore := database.ProvideStore(sqlStore) - + serviceWrapper := ProvideServiceWrapper(publicdashboardStore) publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil) nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true, []map[string]interface{}{}, nil) from, to := internal.GetTimeRangeFromDashboard(t, publicDashboard.Data) @@ -1189,6 +1190,7 @@ func TestBuildMetricRequest(t *testing.T) { log: log.New("test.logger"), store: publicdashboardStore, intervalCalculator: intervalv2.NewCalculator(), + serviceWrapper: serviceWrapper, } publicDashboardQueryDTO := PublicDashboardQueryDTO{ diff --git a/pkg/services/publicdashboards/service/service.go b/pkg/services/publicdashboards/service/service.go index ee624c73a26..13f15941748 100644 --- a/pkg/services/publicdashboards/service/service.go +++ b/pkg/services/publicdashboards/service/service.go @@ -152,13 +152,14 @@ func (pd *PublicDashboardServiceImpl) Create(ctx context.Context, u *user.Signed return nil, err } - // verify public dashboard does not exist and that we didn't get one from the - // request - existingPubdash, err := pd.store.Find(ctx, dto.PublicDashboard.Uid) - if err != nil { - return nil, ErrInternalServerError.Errorf("Create: failed to find the public dashboard: %w", err) - } else if existingPubdash != nil { - return nil, ErrBadRequest.Errorf("Create: public dashboard already exists: %s", dto.PublicDashboard.Uid) + // validate the dashboard does not already have a public dashboard + existingPubdash, err := pd.FindByDashboardUid(ctx, u.OrgID, dto.DashboardUid) + if err != nil && !errors.Is(err, ErrPublicDashboardNotFound) { + return nil, err + } + + if existingPubdash != nil { + return nil, ErrDashboardIsPublic.Errorf("Create: public dashboard for dashboard %s already exists", dto.DashboardUid) } // set default value for time settings @@ -314,7 +315,7 @@ func (pd *PublicDashboardServiceImpl) NewPublicDashboardAccessToken(ctx context. return accessToken, nil } } - return "", ErrInternalServerError.Errorf("failed to generate a unique accesssToken for public dashboard") + return "", ErrInternalServerError.Errorf("failed to generate a unique accessToken for public dashboard") } // FindAll Returns a list of public dashboards by orgId diff --git a/pkg/services/publicdashboards/service/service_test.go b/pkg/services/publicdashboards/service/service_test.go index 2c55926288d..7489d0b28d4 100644 --- a/pkg/services/publicdashboards/service/service_test.go +++ b/pkg/services/publicdashboards/service/service_test.go @@ -329,10 +329,14 @@ func TestCreatePublicDashboard(t *testing.T) { publicDashboardStore.On("FindDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) publicDashboardStore.On("Find", mock.Anything, mock.Anything).Return(nil, nil) publicDashboardStore.On("FindByAccessToken", mock.Anything, mock.Anything).Return(pubdash, nil) + publicDashboardStore.On("FindByDashboardUid", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrPublicDashboardNotFound.Errorf("")) + + serviceWrapper := ProvideServiceWrapper(publicDashboardStore) service := &PublicDashboardServiceImpl{ - log: log.New("test.logger"), - store: publicDashboardStore, + log: log.New("test.logger"), + store: publicDashboardStore, + serviceWrapper: serviceWrapper, } dto := &SavePublicDashboardDTO{ @@ -348,7 +352,7 @@ func TestCreatePublicDashboard(t *testing.T) { _, err := service.Create(context.Background(), SignedInUser, dto) require.Error(t, err) - require.Equal(t, err, ErrInternalServerError.Errorf("failed to generate a unique accesssToken for public dashboard")) + require.Equal(t, err, ErrInternalServerError.Errorf("failed to generate a unique accessToken for public dashboard")) publicDashboardStore.AssertNotCalled(t, "Create") }) @@ -356,12 +360,20 @@ func TestCreatePublicDashboard(t *testing.T) { sqlStore := db.InitTestDB(t) dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotatest.New(false, nil)) require.NoError(t, err) - publicdashboardStore := database.ProvideStore(sqlStore) + dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil) + publicdashboardStore := &FakePublicDashboardStore{} + publicdashboardStore.On("FindByDashboardUid", mock.Anything, mock.Anything, mock.Anything).Return(&PublicDashboard{Uid: "newPubdashUid"}, nil) + publicdashboardStore.On("FindDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) + publicdashboardStore.On("Find", mock.Anything, mock.Anything).Return(nil, nil) + + serviceWrapper := ProvideServiceWrapper(publicdashboardStore) + service := &PublicDashboardServiceImpl{ - log: log.New("test.logger"), - store: publicdashboardStore, + log: log.New("test.logger"), + store: publicdashboardStore, + serviceWrapper: serviceWrapper, } dto := &SavePublicDashboardDTO{ @@ -376,30 +388,9 @@ func TestCreatePublicDashboard(t *testing.T) { } savedPubdash, err := service.Create(context.Background(), SignedInUser, dto) - require.NoError(t, err) - - // attempt to overwrite settings - dto = &SavePublicDashboardDTO{ - DashboardUid: dashboard.UID, - OrgId: dashboard.OrgID, - UserId: 8, - PublicDashboard: &PublicDashboard{ - Uid: savedPubdash.Uid, - OrgId: 9, - DashboardUid: "abc1234", - CreatedBy: 9, - CreatedAt: time.Time{}, - - IsEnabled: true, - AnnotationsEnabled: true, - TimeSettings: timeSettings, - AccessToken: "NOTAREALUUID", - }, - } - - _, err = service.Create(context.Background(), SignedInUser, dto) - require.Error(t, err) - assert.True(t, ErrBadRequest.Is(err)) + assert.Error(t, err) + assert.Nil(t, savedPubdash) + assert.True(t, ErrDashboardIsPublic.Is(err)) }) t.Run("Validate pubdash has default share value", func(t *testing.T) { @@ -445,11 +436,13 @@ func TestUpdatePublicDashboard(t *testing.T) { dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService) require.NoError(t, err) publicdashboardStore := database.ProvideStore(sqlStore) + serviceWrapper := ProvideServiceWrapper(publicdashboardStore) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil) service := &PublicDashboardServiceImpl{ - log: log.New("test.logger"), - store: publicdashboardStore, + log: log.New("test.logger"), + store: publicdashboardStore, + serviceWrapper: serviceWrapper, } dto := &SavePublicDashboardDTO{ @@ -512,11 +505,14 @@ func TestUpdatePublicDashboard(t *testing.T) { dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService) require.NoError(t, err) publicdashboardStore := database.ProvideStore(sqlStore) + serviceWrapper := ProvideServiceWrapper(publicdashboardStore) + dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil) service := &PublicDashboardServiceImpl{ - log: log.New("test.logger"), - store: publicdashboardStore, + log: log.New("test.logger"), + store: publicdashboardStore, + serviceWrapper: serviceWrapper, } dto := &SavePublicDashboardDTO{