mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Pubdash: Email sharing handle dashboard deleted (#64247)
dashboard service calls pubdash service when dashboard deleted
This commit is contained in:
parent
154fa2dd00
commit
1a5a280c86
@ -326,6 +326,12 @@ func (hs *HTTPServer) deleteDashboard(c *contextmodel.ReqContext) response.Respo
|
|||||||
hs.log.Error("Failed to disconnect library elements", "dashboard", dash.ID, "user", c.SignedInUser.UserID, "error", err)
|
hs.log.Error("Failed to disconnect library elements", "dashboard", dash.ID, "user", c.SignedInUser.UserID, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deletes all related public dashboard entities
|
||||||
|
err = hs.PublicDashboardsApi.PublicDashboardService.DeleteByDashboard(c.Req.Context(), dash)
|
||||||
|
if err != nil {
|
||||||
|
hs.log.Error("Failed to delete public dashboard")
|
||||||
|
}
|
||||||
|
|
||||||
err = hs.DashboardService.DeleteDashboard(c.Req.Context(), dash.ID, c.OrgID)
|
err = hs.DashboardService.DeleteDashboard(c.Req.Context(), dash.ID, c.OrgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var dashboardErr dashboards.DashboardErr
|
var dashboardErr dashboards.DashboardErr
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||||
|
"github.com/grafana/grafana/pkg/services/publicdashboards/api"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -304,7 +306,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
|||||||
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||||
setUp()
|
setUp()
|
||||||
sc.sqlStore = mockSQLStore
|
sc.sqlStore = mockSQLStore
|
||||||
hs.callDeleteDashboardByUID(t, sc, dashboardService)
|
hs.callDeleteDashboardByUID(t, sc, dashboardService, nil)
|
||||||
|
|
||||||
assert.Equal(t, 403, sc.resp.Code)
|
assert.Equal(t, 403, sc.resp.Code)
|
||||||
}, mockSQLStore)
|
}, mockSQLStore)
|
||||||
@ -342,7 +344,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
|||||||
loggedInUserScenarioWithRole(t, "When calling DELETE on", "DELETE", "/api/dashboards/uid/abcdefghi",
|
loggedInUserScenarioWithRole(t, "When calling DELETE on", "DELETE", "/api/dashboards/uid/abcdefghi",
|
||||||
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||||
setUp()
|
setUp()
|
||||||
hs.callDeleteDashboardByUID(t, sc, dashboardService)
|
hs.callDeleteDashboardByUID(t, sc, dashboardService, nil)
|
||||||
|
|
||||||
assert.Equal(t, 403, sc.resp.Code)
|
assert.Equal(t, 403, sc.resp.Code)
|
||||||
}, mockSQLStore)
|
}, mockSQLStore)
|
||||||
@ -400,23 +402,9 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
|||||||
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
||||||
dashboardService.On("DeleteDashboard", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(nil)
|
dashboardService.On("DeleteDashboard", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(nil)
|
||||||
|
|
||||||
hs.callDeleteDashboardByUID(t, sc, dashboardService)
|
pubdashService := publicdashboards.NewFakePublicDashboardService(t)
|
||||||
|
pubdashService.On("DeleteByDashboard", mock.Anything, mock.Anything).Return(nil)
|
||||||
assert.Equal(t, 200, sc.resp.Code)
|
hs.callDeleteDashboardByUID(t, sc, dashboardService, pubdashService)
|
||||||
}, mockSQLStore)
|
|
||||||
|
|
||||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/id/2/versions/1", "/api/dashboards/id/:dashboardId/versions/:id", role, func(sc *scenarioContext) {
|
|
||||||
setUpInner()
|
|
||||||
sc.sqlStore = mockSQLStore
|
|
||||||
sc.dashboardVersionService = fakeDashboardVersionService
|
|
||||||
hs.callGetDashboardVersion(sc)
|
|
||||||
|
|
||||||
assert.Equal(t, 200, sc.resp.Code)
|
|
||||||
}, mockSQLStore)
|
|
||||||
|
|
||||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/id/2/versions", "/api/dashboards/id/:dashboardId/versions", role, func(sc *scenarioContext) {
|
|
||||||
setUpInner()
|
|
||||||
hs.callGetDashboardVersions(sc)
|
|
||||||
|
|
||||||
assert.Equal(t, 200, sc.resp.Code)
|
assert.Equal(t, 200, sc.resp.Code)
|
||||||
}, mockSQLStore)
|
}, mockSQLStore)
|
||||||
@ -455,7 +443,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
|||||||
loggedInUserScenarioWithRole(t, "When calling DELETE on", "DELETE", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole(t, "When calling DELETE on", "DELETE", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||||
setUpInner()
|
setUpInner()
|
||||||
|
|
||||||
hs.callDeleteDashboardByUID(t, sc, dashboardService)
|
hs.callDeleteDashboardByUID(t, sc, dashboardService, nil)
|
||||||
assert.Equal(t, 403, sc.resp.Code)
|
assert.Equal(t, 403, sc.resp.Code)
|
||||||
}, mockSQLStore)
|
}, mockSQLStore)
|
||||||
})
|
})
|
||||||
@ -495,7 +483,9 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
|||||||
qResult := dashboards.NewDashboard("test")
|
qResult := dashboards.NewDashboard("test")
|
||||||
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
||||||
dashboardService.On("DeleteDashboard", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(nil)
|
dashboardService.On("DeleteDashboard", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(nil)
|
||||||
hs.callDeleteDashboardByUID(t, sc, dashboardService)
|
pubdashService := publicdashboards.NewFakePublicDashboardService(t)
|
||||||
|
pubdashService.On("DeleteByDashboard", mock.Anything, mock.Anything).Return(nil)
|
||||||
|
hs.callDeleteDashboardByUID(t, sc, dashboardService, pubdashService)
|
||||||
|
|
||||||
assert.Equal(t, 200, sc.resp.Code)
|
assert.Equal(t, 200, sc.resp.Code)
|
||||||
}, mockSQLStore)
|
}, mockSQLStore)
|
||||||
@ -538,7 +528,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
loggedInUserScenarioWithRole(t, "When calling DELETE on", "DELETE", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole(t, "When calling DELETE on", "DELETE", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||||
setUpInner()
|
setUpInner()
|
||||||
hs.callDeleteDashboardByUID(t, sc, dashboardService)
|
hs.callDeleteDashboardByUID(t, sc, dashboardService, nil)
|
||||||
|
|
||||||
assert.Equal(t, 403, sc.resp.Code)
|
assert.Equal(t, 403, sc.resp.Code)
|
||||||
}, mockSQLStore)
|
}, mockSQLStore)
|
||||||
@ -1035,8 +1025,10 @@ func (hs *HTTPServer) callGetDashboardVersions(sc *scenarioContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (hs *HTTPServer) callDeleteDashboardByUID(t *testing.T,
|
func (hs *HTTPServer) callDeleteDashboardByUID(t *testing.T,
|
||||||
sc *scenarioContext, mockDashboard *dashboards.FakeDashboardService) {
|
sc *scenarioContext, mockDashboard *dashboards.FakeDashboardService, mockPubdashService *publicdashboards.FakePublicDashboardService) {
|
||||||
hs.DashboardService = mockDashboard
|
hs.DashboardService = mockDashboard
|
||||||
|
pubdashApi := api.ProvideApi(mockPubdashService, nil, nil, featuremgmt.WithFeatures())
|
||||||
|
hs.PublicDashboardsApi = pubdashApi
|
||||||
sc.handlerFunc = hs.DeleteDashboardByUID
|
sc.handlerFunc = hs.DeleteDashboardByUID
|
||||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||||
}
|
}
|
||||||
|
@ -702,7 +702,6 @@ func (d *dashboardStore) deleteDashboard(cmd *dashboards.DeleteDashboardCommand,
|
|||||||
deletes := []string{
|
deletes := []string{
|
||||||
"DELETE FROM dashboard_tag WHERE dashboard_id = ? ",
|
"DELETE FROM dashboard_tag WHERE dashboard_id = ? ",
|
||||||
"DELETE FROM star WHERE dashboard_id = ? ",
|
"DELETE FROM star WHERE dashboard_id = ? ",
|
||||||
"DELETE FROM dashboard_public WHERE dashboard_uid = (SELECT uid FROM dashboard WHERE id = ?)",
|
|
||||||
"DELETE FROM dashboard WHERE id = ?",
|
"DELETE FROM dashboard WHERE id = ?",
|
||||||
"DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?",
|
"DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?",
|
||||||
"DELETE FROM dashboard_version WHERE dashboard_id = ?",
|
"DELETE FROM dashboard_version WHERE dashboard_id = ?",
|
||||||
@ -751,7 +750,6 @@ func (d *dashboardStore) deleteDashboard(cmd *dashboards.DeleteDashboardCommand,
|
|||||||
"DELETE FROM annotation WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
"DELETE FROM annotation WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
||||||
"DELETE FROM dashboard_provisioning WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
"DELETE FROM dashboard_provisioning WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
||||||
"DELETE FROM dashboard_acl WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
"DELETE FROM dashboard_acl WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
||||||
"DELETE FROM dashboard_public WHERE dashboard_uid IN (SELECT uid FROM dashboard WHERE org_id = ? AND folder_id = ?)",
|
|
||||||
}
|
}
|
||||||
for _, sql := range childrenDeletes {
|
for _, sql := range childrenDeletes {
|
||||||
_, err := sess.Exec(sql, dashboard.OrgID, dashboard.ID)
|
_, err := sess.Exec(sql, dashboard.OrgID, dashboard.ID)
|
||||||
|
@ -16,8 +16,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards/database"
|
|
||||||
publicDashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
|
||||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||||
"github.com/grafana/grafana/pkg/services/search/model"
|
"github.com/grafana/grafana/pkg/services/search/model"
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||||
@ -27,7 +25,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIntegrationDashboardDataAccess(t *testing.T) {
|
func TestIntegrationDashboardDataAccess(t *testing.T) {
|
||||||
@ -39,7 +36,6 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
|
|||||||
var savedFolder, savedDash, savedDash2 *dashboards.Dashboard
|
var savedFolder, savedDash, savedDash2 *dashboards.Dashboard
|
||||||
var dashboardStore dashboards.Store
|
var dashboardStore dashboards.Store
|
||||||
var starService star.Service
|
var starService star.Service
|
||||||
var publicDashboardStore *database.PublicDashboardStoreImpl
|
|
||||||
|
|
||||||
setup := func() {
|
setup := func() {
|
||||||
sqlStore, cfg = db.InitTestDBwithCfg(t)
|
sqlStore, cfg = db.InitTestDBwithCfg(t)
|
||||||
@ -53,8 +49,6 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
|
|||||||
insertTestDashboard(t, dashboardStore, "test dash 45", 1, savedFolder.ID, false, "prod")
|
insertTestDashboard(t, dashboardStore, "test dash 45", 1, savedFolder.ID, false, "prod")
|
||||||
savedDash2 = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod")
|
savedDash2 = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod")
|
||||||
insertTestRule(t, sqlStore, savedFolder.OrgID, savedFolder.UID)
|
insertTestRule(t, sqlStore, savedFolder.OrgID, savedFolder.UID)
|
||||||
|
|
||||||
publicDashboardStore = database.ProvideStore(sqlStore)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should return dashboard model", func(t *testing.T) {
|
t.Run("Should return dashboard model", func(t *testing.T) {
|
||||||
@ -246,78 +240,6 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
|
|||||||
require.True(t, errors.Is(err, dashboards.ErrFolderContainsAlertRules))
|
require.True(t, errors.Is(err, dashboards.ErrFolderContainsAlertRules))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Should be able to delete dashboard and related public dashboard", func(t *testing.T) {
|
|
||||||
setup()
|
|
||||||
|
|
||||||
uid := util.GenerateShortUID()
|
|
||||||
cmd := publicDashboardModels.SavePublicDashboardCommand{
|
|
||||||
PublicDashboard: publicDashboardModels.PublicDashboard{
|
|
||||||
Uid: uid,
|
|
||||||
DashboardUid: savedDash.UID,
|
|
||||||
OrgId: savedDash.OrgID,
|
|
||||||
IsEnabled: true,
|
|
||||||
TimeSettings: &publicDashboardModels.TimeSettings{},
|
|
||||||
CreatedBy: 1,
|
|
||||||
CreatedAt: time.Now(),
|
|
||||||
AccessToken: "an-access-token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
_, err := publicDashboardStore.Create(context.Background(), cmd)
|
|
||||||
require.NoError(t, err)
|
|
||||||
pubdashConfig, _ := publicDashboardStore.FindByAccessToken(context.Background(), "an-access-token")
|
|
||||||
require.NotNil(t, pubdashConfig)
|
|
||||||
|
|
||||||
deleteCmd := &dashboards.DeleteDashboardCommand{ID: savedDash.ID, OrgID: savedDash.OrgID}
|
|
||||||
err = dashboardStore.DeleteDashboard(context.Background(), deleteCmd)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
query := dashboards.GetDashboardQuery{UID: savedDash.UID, OrgID: savedDash.OrgID}
|
|
||||||
dash, getErr := dashboardStore.GetDashboard(context.Background(), &query)
|
|
||||||
require.Equal(t, getErr, dashboards.ErrDashboardNotFound)
|
|
||||||
assert.Nil(t, dash)
|
|
||||||
|
|
||||||
pubdashConfig, err = publicDashboardStore.FindByAccessToken(context.Background(), "an-access-token")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Nil(t, pubdashConfig)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Should be able to delete a dashboard folder, with its dashboard and related public dashboard", func(t *testing.T) {
|
|
||||||
setup()
|
|
||||||
|
|
||||||
uid := util.GenerateShortUID()
|
|
||||||
cmd := publicDashboardModels.SavePublicDashboardCommand{
|
|
||||||
PublicDashboard: publicDashboardModels.PublicDashboard{
|
|
||||||
Uid: uid,
|
|
||||||
DashboardUid: savedDash.UID,
|
|
||||||
OrgId: savedDash.OrgID,
|
|
||||||
IsEnabled: true,
|
|
||||||
TimeSettings: &publicDashboardModels.TimeSettings{},
|
|
||||||
CreatedBy: 1,
|
|
||||||
CreatedAt: time.Now(),
|
|
||||||
AccessToken: "an-access-token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
_, err := publicDashboardStore.Create(context.Background(), cmd)
|
|
||||||
require.NoError(t, err)
|
|
||||||
pubdashConfig, _ := publicDashboardStore.FindByAccessToken(context.Background(), "an-access-token")
|
|
||||||
require.NotNil(t, pubdashConfig)
|
|
||||||
|
|
||||||
deleteCmd := &dashboards.DeleteDashboardCommand{ID: savedFolder.ID, ForceDeleteFolderRules: true}
|
|
||||||
err = dashboardStore.DeleteDashboard(context.Background(), deleteCmd)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
query := dashboards.GetDashboardsQuery{
|
|
||||||
DashboardIDs: []int64{savedFolder.ID, savedDash.ID},
|
|
||||||
}
|
|
||||||
queryResult, err := dashboardStore.GetDashboards(context.Background(), &query)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, len(queryResult), 0)
|
|
||||||
|
|
||||||
pubdashConfig, err = publicDashboardStore.FindByAccessToken(context.Background(), "an-access-token")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.Nil(t, pubdashConfig)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Should be able to delete a dashboard folder and its children if force delete rules is enabled", func(t *testing.T) {
|
t.Run("Should be able to delete a dashboard folder and its children if force delete rules is enabled", func(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
deleteCmd := &dashboards.DeleteDashboardCommand{ID: savedFolder.ID, ForceDeleteFolderRules: true}
|
deleteCmd := &dashboards.DeleteDashboardCommand{ID: savedFolder.ID, ForceDeleteFolderRules: true}
|
||||||
|
@ -196,7 +196,7 @@ func (api *Api) DeletePublicDashboard(c *contextmodel.ReqContext) response.Respo
|
|||||||
return response.Err(ErrInvalidUid.Errorf("UpdatePublicDashboard: invalid Uid %s", uid))
|
return response.Err(ErrInvalidUid.Errorf("UpdatePublicDashboard: invalid Uid %s", uid))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := api.PublicDashboardService.Delete(c.Req.Context(), c.OrgID, uid)
|
err := api.PublicDashboardService.Delete(c.Req.Context(), uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Err(err)
|
return response.Err(err)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||||
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define the storage implementation. We're generating the mock implementation
|
// Define the storage implementation. We're generating the mock implementation
|
||||||
@ -255,8 +256,8 @@ func (d *PublicDashboardStoreImpl) Update(ctx context.Context, cmd SavePublicDas
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deletes a public dashboard
|
// Deletes a public dashboard
|
||||||
func (d *PublicDashboardStoreImpl) Delete(ctx context.Context, orgId int64, uid string) (int64, error) {
|
func (d *PublicDashboardStoreImpl) Delete(ctx context.Context, uid string) (int64, error) {
|
||||||
dashboard := &PublicDashboard{OrgId: orgId, Uid: uid}
|
dashboard := &PublicDashboard{Uid: uid}
|
||||||
var affectedRows int64
|
var affectedRows int64
|
||||||
err := d.sqlStore.WithDbSession(ctx, func(sess *db.Session) error {
|
err := d.sqlStore.WithDbSession(ctx, func(sess *db.Session) error {
|
||||||
var err error
|
var err error
|
||||||
@ -267,3 +268,20 @@ func (d *PublicDashboardStoreImpl) Delete(ctx context.Context, orgId int64, uid
|
|||||||
|
|
||||||
return affectedRows, err
|
return affectedRows, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *PublicDashboardStoreImpl) FindByDashboardFolder(ctx context.Context, dashboard *dashboards.Dashboard) ([]*PublicDashboard, error) {
|
||||||
|
if dashboard == nil || !dashboard.IsFolder {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var pubdashes []*PublicDashboard
|
||||||
|
|
||||||
|
err := d.sqlStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
|
return sess.SQL("SELECT * from dashboard_public WHERE (dashboard_uid, org_id) IN (SELECT uid, org_id FROM dashboard WHERE folder_id = ?)", dashboard.ID).Find(&pubdashes)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pubdashes, nil
|
||||||
|
}
|
||||||
|
@ -652,7 +652,7 @@ func TestIntegrationDelete(t *testing.T) {
|
|||||||
t.Run("Delete success", func(t *testing.T) {
|
t.Run("Delete success", func(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
// Do the deletion
|
// Do the deletion
|
||||||
affectedRows, err := publicdashboardStore.Delete(context.Background(), savedPublicDashboard.OrgId, savedPublicDashboard.Uid)
|
affectedRows, err := publicdashboardStore.Delete(context.Background(), savedPublicDashboard.Uid)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, affectedRows, 1)
|
assert.EqualValues(t, affectedRows, 1)
|
||||||
|
|
||||||
@ -665,12 +665,51 @@ func TestIntegrationDelete(t *testing.T) {
|
|||||||
t.Run("Non-existent public dashboard deletion doesn't throw an error", func(t *testing.T) {
|
t.Run("Non-existent public dashboard deletion doesn't throw an error", func(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
|
|
||||||
affectedRows, err := publicdashboardStore.Delete(context.Background(), 15, "non-existent-uid")
|
affectedRows, err := publicdashboardStore.Delete(context.Background(), "non-existent-uid")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, affectedRows, 0)
|
assert.EqualValues(t, affectedRows, 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetDashboardByFolder(t *testing.T) {
|
||||||
|
t.Run("returns nil when dashboard is not a folder", func(t *testing.T) {
|
||||||
|
sqlStore, _ := db.InitTestDBwithCfg(t)
|
||||||
|
dashboard := &dashboards.Dashboard{IsFolder: false}
|
||||||
|
store := ProvideStore(sqlStore)
|
||||||
|
pubdashes, err := store.FindByDashboardFolder(context.Background(), dashboard)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Nil(t, pubdashes)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns nil when dashboard is nil", func(t *testing.T) {
|
||||||
|
sqlStore, _ := db.InitTestDBwithCfg(t)
|
||||||
|
store := ProvideStore(sqlStore)
|
||||||
|
pubdashes, err := store.FindByDashboardFolder(context.Background(), nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Nil(t, pubdashes)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("can get all pubdashes for dashboard folder and org", func(t *testing.T) {
|
||||||
|
sqlStore, cfg := db.InitTestDBwithCfg(t)
|
||||||
|
quotaService := quotatest.New(false, nil)
|
||||||
|
dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||||
|
require.NoError(t, err)
|
||||||
|
pubdashStore := ProvideStore(sqlStore)
|
||||||
|
dashboard := insertTestDashboard(t, dashboardStore, "title", 1, 1, true)
|
||||||
|
pubdash := insertPublicDashboard(t, pubdashStore, dashboard.UID, dashboard.OrgID, true)
|
||||||
|
dashboard2 := insertTestDashboard(t, dashboardStore, "title", 1, 2, true)
|
||||||
|
_ = insertPublicDashboard(t, pubdashStore, dashboard2.UID, dashboard2.OrgID, true)
|
||||||
|
|
||||||
|
pubdashes, err := pubdashStore.FindByDashboardFolder(context.Background(), dashboard)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, pubdashes, 1)
|
||||||
|
assert.Equal(t, pubdash, pubdashes[0])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to insert a dashboard
|
// helper function to insert a dashboard
|
||||||
func insertTestDashboard(t *testing.T, dashboardStore dashboards.Store, title string, orgId int64,
|
func insertTestDashboard(t *testing.T, dashboardStore dashboards.Store, title string, orgId int64,
|
||||||
folderId int64, isFolder bool, tags ...interface{}) *dashboards.Dashboard {
|
folderId int64, isFolder bool, tags ...interface{}) *dashboards.Dashboard {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
// Code generated by mockery v2.16.0. DO NOT EDIT.
|
||||||
|
|
||||||
package publicdashboards
|
package publicdashboards
|
||||||
|
|
||||||
@ -46,13 +46,27 @@ func (_m *FakePublicDashboardService) Create(ctx context.Context, u *user.Signed
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete provides a mock function with given fields: ctx, orgId, uid
|
// Delete provides a mock function with given fields: ctx, uid
|
||||||
func (_m *FakePublicDashboardService) Delete(ctx context.Context, orgId int64, uid string) error {
|
func (_m *FakePublicDashboardService) Delete(ctx context.Context, uid string) error {
|
||||||
ret := _m.Called(ctx, orgId, uid)
|
ret := _m.Called(ctx, uid)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||||
r0 = rf(ctx, orgId, uid)
|
r0 = rf(ctx, uid)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByDashboard provides a mock function with given fields: ctx, dashboard
|
||||||
|
func (_m *FakePublicDashboardService) DeleteByDashboard(ctx context.Context, dashboard *dashboards.Dashboard) error {
|
||||||
|
ret := _m.Called(ctx, dashboard)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *dashboards.Dashboard) error); ok {
|
||||||
|
r0 = rf(ctx, dashboard)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
// Code generated by mockery v2.16.0. DO NOT EDIT.
|
||||||
|
|
||||||
package publicdashboards
|
package publicdashboards
|
||||||
|
|
||||||
@ -14,6 +14,20 @@ type FakePublicDashboardServiceWrapper struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete provides a mock function with given fields: ctx, uid
|
||||||
|
func (_m *FakePublicDashboardServiceWrapper) Delete(ctx context.Context, uid string) error {
|
||||||
|
ret := _m.Called(ctx, uid)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||||
|
r0 = rf(ctx, uid)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// FindByDashboardUid provides a mock function with given fields: ctx, orgId, dashboardUid
|
// FindByDashboardUid provides a mock function with given fields: ctx, orgId, dashboardUid
|
||||||
func (_m *FakePublicDashboardServiceWrapper) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
|
func (_m *FakePublicDashboardServiceWrapper) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
|
||||||
ret := _m.Called(ctx, orgId, dashboardUid)
|
ret := _m.Called(ctx, orgId, dashboardUid)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
// Code generated by mockery v2.16.0. DO NOT EDIT.
|
||||||
|
|
||||||
package publicdashboards
|
package publicdashboards
|
||||||
|
|
||||||
@ -37,20 +37,20 @@ func (_m *FakePublicDashboardStore) Create(ctx context.Context, cmd models.SaveP
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete provides a mock function with given fields: ctx, orgId, uid
|
// Delete provides a mock function with given fields: ctx, uid
|
||||||
func (_m *FakePublicDashboardStore) Delete(ctx context.Context, orgId int64, uid string) (int64, error) {
|
func (_m *FakePublicDashboardStore) Delete(ctx context.Context, uid string) (int64, error) {
|
||||||
ret := _m.Called(ctx, orgId, uid)
|
ret := _m.Called(ctx, uid)
|
||||||
|
|
||||||
var r0 int64
|
var r0 int64
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) int64); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string) int64); ok {
|
||||||
r0 = rf(ctx, orgId, uid)
|
r0 = rf(ctx, uid)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Get(0).(int64)
|
r0 = ret.Get(0).(int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
r1 = rf(ctx, orgId, uid)
|
r1 = rf(ctx, uid)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
@ -169,6 +169,29 @@ func (_m *FakePublicDashboardStore) FindByAccessToken(ctx context.Context, acces
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindByDashboardFolder provides a mock function with given fields: ctx, dashboard
|
||||||
|
func (_m *FakePublicDashboardStore) FindByDashboardFolder(ctx context.Context, dashboard *dashboards.Dashboard) ([]*models.PublicDashboard, error) {
|
||||||
|
ret := _m.Called(ctx, dashboard)
|
||||||
|
|
||||||
|
var r0 []*models.PublicDashboard
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *dashboards.Dashboard) []*models.PublicDashboard); ok {
|
||||||
|
r0 = rf(ctx, dashboard)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*models.PublicDashboard)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *dashboards.Dashboard) error); ok {
|
||||||
|
r1 = rf(ctx, dashboard)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// FindByDashboardUid provides a mock function with given fields: ctx, orgId, dashboardUid
|
// FindByDashboardUid provides a mock function with given fields: ctx, orgId, dashboardUid
|
||||||
func (_m *FakePublicDashboardStore) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
|
func (_m *FakePublicDashboardStore) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
|
||||||
ret := _m.Called(ctx, orgId, dashboardUid)
|
ret := _m.Called(ctx, orgId, dashboardUid)
|
||||||
|
@ -24,7 +24,8 @@ type Service interface {
|
|||||||
Find(ctx context.Context, uid string) (*PublicDashboard, error)
|
Find(ctx context.Context, uid string) (*PublicDashboard, error)
|
||||||
Create(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardDTO) (*PublicDashboard, error)
|
Create(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardDTO) (*PublicDashboard, error)
|
||||||
Update(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardDTO) (*PublicDashboard, error)
|
Update(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardDTO) (*PublicDashboard, error)
|
||||||
Delete(ctx context.Context, orgId int64, uid string) error
|
Delete(ctx context.Context, uid string) error
|
||||||
|
DeleteByDashboard(ctx context.Context, dashboard *dashboards.Dashboard) error
|
||||||
|
|
||||||
GetMetricRequest(ctx context.Context, dashboard *dashboards.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error)
|
GetMetricRequest(ctx context.Context, dashboard *dashboards.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error)
|
||||||
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
|
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
|
||||||
@ -41,6 +42,7 @@ type Service interface {
|
|||||||
//go:generate mockery --name ServiceWrapper --structname FakePublicDashboardServiceWrapper --inpackage --filename public_dashboard_service_wrapper_mock.go
|
//go:generate mockery --name ServiceWrapper --structname FakePublicDashboardServiceWrapper --inpackage --filename public_dashboard_service_wrapper_mock.go
|
||||||
type ServiceWrapper interface {
|
type ServiceWrapper interface {
|
||||||
FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
||||||
|
Delete(ctx context.Context, uid string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate mockery --name Store --structname FakePublicDashboardStore --inpackage --filename public_dashboard_store_mock.go
|
//go:generate mockery --name Store --structname FakePublicDashboardStore --inpackage --filename public_dashboard_store_mock.go
|
||||||
@ -52,9 +54,10 @@ type Store interface {
|
|||||||
FindAll(ctx context.Context, orgId int64) ([]PublicDashboardListResponse, error)
|
FindAll(ctx context.Context, orgId int64) ([]PublicDashboardListResponse, error)
|
||||||
Create(ctx context.Context, cmd SavePublicDashboardCommand) (int64, error)
|
Create(ctx context.Context, cmd SavePublicDashboardCommand) (int64, error)
|
||||||
Update(ctx context.Context, cmd SavePublicDashboardCommand) (int64, error)
|
Update(ctx context.Context, cmd SavePublicDashboardCommand) (int64, error)
|
||||||
Delete(ctx context.Context, orgId int64, uid string) (int64, error)
|
Delete(ctx context.Context, uid string) (int64, error)
|
||||||
|
|
||||||
GetOrgIdByAccessToken(ctx context.Context, accessToken string) (int64, error)
|
GetOrgIdByAccessToken(ctx context.Context, accessToken string) (int64, error)
|
||||||
|
FindByDashboardFolder(ctx context.Context, dashboard *dashboards.Dashboard) ([]*PublicDashboard, error)
|
||||||
ExistsEnabledByAccessToken(ctx context.Context, accessToken string) (bool, error)
|
ExistsEnabledByAccessToken(ctx context.Context, accessToken string) (bool, error)
|
||||||
ExistsEnabledByDashboardUid(ctx context.Context, dashboardUid string) (bool, error)
|
ExistsEnabledByDashboardUid(ctx context.Context, dashboardUid string) (bool, error)
|
||||||
}
|
}
|
||||||
|
@ -329,19 +329,39 @@ func (pd *PublicDashboardServiceImpl) GetOrgIdByAccessToken(ctx context.Context,
|
|||||||
return pd.store.GetOrgIdByAccessToken(ctx, accessToken)
|
return pd.store.GetOrgIdByAccessToken(ctx, accessToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pd *PublicDashboardServiceImpl) Delete(ctx context.Context, orgId int64, uid string) error {
|
func (pd *PublicDashboardServiceImpl) Delete(ctx context.Context, uid string) error {
|
||||||
affectedRows, err := pd.store.Delete(ctx, orgId, uid)
|
return pd.serviceWrapper.Delete(ctx, uid)
|
||||||
if err != nil {
|
|
||||||
return ErrInternalServerError.Errorf("Delete: failed to delete a public dashboard by orgId: %d and Uid: %s %w", orgId, uid, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if affectedRows == 0 {
|
func (pd *PublicDashboardServiceImpl) DeleteByDashboard(ctx context.Context, dashboard *dashboards.Dashboard) error {
|
||||||
return ErrPublicDashboardNotFound.Errorf("Delete: Public dashboard not found by orgId: %d and Uid: %s", orgId, uid)
|
if dashboard.IsFolder {
|
||||||
|
// get all pubdashes for the folder
|
||||||
|
pubdashes, err := pd.store.FindByDashboardFolder(ctx, dashboard)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// delete each pubdash
|
||||||
|
for _, pubdash := range pubdashes {
|
||||||
|
err = pd.serviceWrapper.Delete(ctx, pubdash.Uid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pubdash, err := pd.store.FindByDashboardUid(ctx, dashboard.OrgID, dashboard.UID)
|
||||||
|
if err != nil {
|
||||||
|
return ErrInternalServerError.Errorf("DeleteByDashboard: error finding a public dashboard by dashboard orgId: %d and Uid: %s %w", dashboard.OrgID, dashboard.UID, err)
|
||||||
|
}
|
||||||
|
if pubdash == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return pd.serviceWrapper.Delete(ctx, pubdash.Uid)
|
||||||
|
}
|
||||||
|
|
||||||
// intervalMS and maxQueryData values are being calculated on the frontend for regular dashboards
|
// intervalMS and maxQueryData values are being calculated on the frontend for regular dashboards
|
||||||
// we are doing the same for public dashboards but because this access would be public, we need a way to keep this
|
// we are doing the same for public dashboards but because this access would be public, we need a way to keep this
|
||||||
// values inside reasonable bounds to avoid an attack that could hit data sources with a small interval and a big
|
// values inside reasonable bounds to avoid an attack that could hit data sources with a small interval and a big
|
||||||
|
@ -498,13 +498,13 @@ func TestDeletePublicDashboard(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "Public dashboard not found",
|
Name: "Public dashboard not found",
|
||||||
AffectedRowsResp: 0,
|
AffectedRowsResp: 0,
|
||||||
ExpectedErrResp: ErrPublicDashboardNotFound.Errorf("Delete: Public dashboard not found by orgId: 13 and Uid: uid"),
|
ExpectedErrResp: nil,
|
||||||
StoreRespErr: nil,
|
StoreRespErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Database error",
|
Name: "Database error",
|
||||||
AffectedRowsResp: 0,
|
AffectedRowsResp: 0,
|
||||||
ExpectedErrResp: ErrInternalServerError.Errorf("Delete: failed to delete a public dashboard by orgId: 13 and Uid: uid db error!"),
|
ExpectedErrResp: ErrInternalServerError.Errorf("Delete: failed to delete a public dashboard by Uid: uid db error!"),
|
||||||
StoreRespErr: errors.New("db error!"),
|
StoreRespErr: errors.New("db error!"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -512,14 +512,18 @@ func TestDeletePublicDashboard(t *testing.T) {
|
|||||||
for _, tt := range testCases {
|
for _, tt := range testCases {
|
||||||
t.Run(tt.Name, func(t *testing.T) {
|
t.Run(tt.Name, func(t *testing.T) {
|
||||||
store := NewFakePublicDashboardStore(t)
|
store := NewFakePublicDashboardStore(t)
|
||||||
store.On("Delete", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.AffectedRowsResp, tt.StoreRespErr)
|
store.On("Delete", mock.Anything, mock.Anything).Return(tt.AffectedRowsResp, tt.StoreRespErr)
|
||||||
|
serviceWrapper := &PublicDashboardServiceWrapperImpl{
|
||||||
service := &PublicDashboardServiceImpl{
|
|
||||||
log: log.New("test.logger"),
|
log: log.New("test.logger"),
|
||||||
store: store,
|
store: store,
|
||||||
}
|
}
|
||||||
|
service := &PublicDashboardServiceImpl{
|
||||||
|
log: log.New("test.logger"),
|
||||||
|
store: store,
|
||||||
|
serviceWrapper: serviceWrapper,
|
||||||
|
}
|
||||||
|
|
||||||
err := service.Delete(context.Background(), 13, "uid")
|
err := service.Delete(context.Background(), "uid")
|
||||||
if tt.ExpectedErrResp != nil {
|
if tt.ExpectedErrResp != nil {
|
||||||
assert.Equal(t, tt.ExpectedErrResp.Error(), err.Error())
|
assert.Equal(t, tt.ExpectedErrResp.Error(), err.Error())
|
||||||
assert.Equal(t, tt.ExpectedErrResp.Error(), err.Error())
|
assert.Equal(t, tt.ExpectedErrResp.Error(), err.Error())
|
||||||
@ -966,6 +970,56 @@ func TestPublicDashboardServiceImpl_NewPublicDashboardAccessToken(t *testing.T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteByDashboard(t *testing.T) {
|
||||||
|
t.Run("will return nil when pubdash not found", func(t *testing.T) {
|
||||||
|
store := NewFakePublicDashboardStore(t)
|
||||||
|
pd := &PublicDashboardServiceImpl{store: store, serviceWrapper: ProvideServiceWrapper(store)}
|
||||||
|
dashboard := &dashboards.Dashboard{UID: "1", OrgID: 1, IsFolder: false}
|
||||||
|
store.On("FindByDashboardUid", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
|
||||||
|
|
||||||
|
err := pd.DeleteByDashboard(context.Background(), dashboard)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
})
|
||||||
|
t.Run("will delete pubdash when dashboard deleted", func(t *testing.T) {
|
||||||
|
store := NewFakePublicDashboardStore(t)
|
||||||
|
pd := &PublicDashboardServiceImpl{store: store, serviceWrapper: ProvideServiceWrapper(store)}
|
||||||
|
dashboard := &dashboards.Dashboard{UID: "1", OrgID: 1, IsFolder: false}
|
||||||
|
pubdash := &PublicDashboard{Uid: "2", OrgId: 1, DashboardUid: dashboard.UID}
|
||||||
|
store.On("FindByDashboardUid", mock.Anything, mock.Anything, mock.Anything).Return(pubdash, nil)
|
||||||
|
store.On("Delete", mock.Anything, mock.Anything, mock.Anything).Return(int64(1), nil)
|
||||||
|
|
||||||
|
err := pd.DeleteByDashboard(context.Background(), dashboard)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("will delete pubdashes when dashboard folder deleted", func(t *testing.T) {
|
||||||
|
store := NewFakePublicDashboardStore(t)
|
||||||
|
pd := &PublicDashboardServiceImpl{store: store, serviceWrapper: ProvideServiceWrapper(store)}
|
||||||
|
dashboard := &dashboards.Dashboard{UID: "1", OrgID: 1, IsFolder: true}
|
||||||
|
pubdash1 := &PublicDashboard{Uid: "2", OrgId: 1, DashboardUid: dashboard.UID}
|
||||||
|
pubdash2 := &PublicDashboard{Uid: "3", OrgId: 1, DashboardUid: dashboard.UID}
|
||||||
|
store.On("FindByDashboardFolder", mock.Anything, mock.Anything).Return([]*PublicDashboard{pubdash1, pubdash2}, nil)
|
||||||
|
store.On("Delete", mock.Anything, mock.Anything, mock.Anything).Return(int64(1), nil)
|
||||||
|
store.On("Delete", mock.Anything, mock.Anything, mock.Anything).Return(int64(1), nil)
|
||||||
|
|
||||||
|
err := pd.DeleteByDashboard(context.Background(), dashboard)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateAccessToken(t *testing.T) {
|
||||||
|
accessToken, err := GenerateAccessToken()
|
||||||
|
|
||||||
|
t.Run("length", func(t *testing.T) {
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, 32, len(accessToken))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("no - ", func(t *testing.T) {
|
||||||
|
assert.False(t, strings.Contains("-", accessToken))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func CreateDatasource(dsType string, uid string) struct {
|
func CreateDatasource(dsType string, uid string) struct {
|
||||||
Type *string `json:"type,omitempty"`
|
Type *string `json:"type,omitempty"`
|
||||||
Uid *string `json:"uid,omitempty"`
|
Uid *string `json:"uid,omitempty"`
|
||||||
@ -1070,16 +1124,3 @@ func insertTestDashboard(t *testing.T, dashboardStore dashboards.Store, title st
|
|||||||
dash.Data.Set("uid", dash.UID)
|
dash.Data.Set("uid", dash.UID)
|
||||||
return dash
|
return dash
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateAccessToken(t *testing.T) {
|
|
||||||
accessToken, err := GenerateAccessToken()
|
|
||||||
|
|
||||||
t.Run("length", func(t *testing.T) {
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, 32, len(accessToken))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("no - ", func(t *testing.T) {
|
|
||||||
assert.False(t, strings.Contains("-", accessToken))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@ -43,3 +43,12 @@ func (pd *PublicDashboardServiceWrapperImpl) FindByDashboardUid(ctx context.Cont
|
|||||||
|
|
||||||
return pubdash, nil
|
return pubdash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pd *PublicDashboardServiceWrapperImpl) Delete(ctx context.Context, uid string) error {
|
||||||
|
_, err := pd.store.Delete(ctx, uid)
|
||||||
|
if err != nil {
|
||||||
|
return ErrInternalServerError.Errorf("Delete: failed to delete a public dashboard by Uid: %s %w", uid, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user