mirror of
https://github.com/grafana/grafana.git
synced 2025-02-16 18:34:52 -06:00
PublicDashboards: Add validation deletion (#75336)
This commit is contained in:
parent
3fc925364f
commit
42fb42a90d
@ -220,10 +220,15 @@ func (api *Api) UpdatePublicDashboard(c *contextmodel.ReqContext) response.Respo
|
|||||||
func (api *Api) DeletePublicDashboard(c *contextmodel.ReqContext) response.Response {
|
func (api *Api) DeletePublicDashboard(c *contextmodel.ReqContext) response.Response {
|
||||||
uid := web.Params(c.Req)[":uid"]
|
uid := web.Params(c.Req)[":uid"]
|
||||||
if !validation.IsValidShortUID(uid) {
|
if !validation.IsValidShortUID(uid) {
|
||||||
return response.Err(ErrInvalidUid.Errorf("UpdatePublicDashboard: invalid Uid %s", uid))
|
return response.Err(ErrInvalidUid.Errorf("DeletePublicDashboard: invalid Uid %s", uid))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := api.PublicDashboardService.Delete(c.Req.Context(), uid)
|
dashboardUid := web.Params(c.Req)[":dashboardUid"]
|
||||||
|
if !validation.IsValidShortUID(dashboardUid) {
|
||||||
|
return response.Err(ErrInvalidUid.Errorf("DeletePublicDashboard: invalid dashboard Uid %s", dashboardUid))
|
||||||
|
}
|
||||||
|
|
||||||
|
err := api.PublicDashboardService.Delete(c.Req.Context(), uid, dashboardUid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Err(err)
|
return response.Err(err)
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,13 @@ 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, uid
|
// Delete provides a mock function with given fields: ctx, uid, dashboardUid
|
||||||
func (_m *FakePublicDashboardService) Delete(ctx context.Context, uid string) error {
|
func (_m *FakePublicDashboardService) Delete(ctx context.Context, uid string, dashboardUid string) error {
|
||||||
ret := _m.Called(ctx, uid)
|
ret := _m.Called(ctx, uid, dashboardUid)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||||
r0 = rf(ctx, uid)
|
r0 = rf(ctx, uid, dashboardUid)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ 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, uid string) error
|
Delete(ctx context.Context, uid string, dashboardUid string) error
|
||||||
DeleteByDashboard(ctx context.Context, dashboard *dashboards.Dashboard) 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)
|
||||||
|
@ -332,7 +332,20 @@ 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, uid string) error {
|
func (pd *PublicDashboardServiceImpl) Delete(ctx context.Context, uid string, dashboardUid string) error {
|
||||||
|
// get existing public dashboard if exists
|
||||||
|
existingPubdash, err := pd.store.Find(ctx, uid)
|
||||||
|
if err != nil {
|
||||||
|
return ErrInternalServerError.Errorf("Delete: failed to find public dashboard by uid: %s: %w", uid, err)
|
||||||
|
}
|
||||||
|
if existingPubdash == nil {
|
||||||
|
return ErrPublicDashboardNotFound.Errorf("Delete: public dashboard not found by uid: %s", uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate the public dashboard belongs to the dashboard
|
||||||
|
if existingPubdash.DashboardUid != dashboardUid {
|
||||||
|
return ErrInvalidUid.Errorf("Delete: the public dashboard does not belong to the dashboard")
|
||||||
|
}
|
||||||
return pd.serviceWrapper.Delete(ctx, uid)
|
return pd.serviceWrapper.Delete(ctx, uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1295,36 +1295,64 @@ func assertOldValueIfNull(t *testing.T, expectedValue bool, oldValue bool, nulla
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeletePublicDashboard(t *testing.T) {
|
func TestDeletePublicDashboard(t *testing.T) {
|
||||||
testCases := []struct {
|
pubdash := &PublicDashboard{Uid: "2", OrgId: 1, DashboardUid: "uid"}
|
||||||
Name string
|
|
||||||
|
type mockFindResponse struct {
|
||||||
|
PublicDashboard *PublicDashboard
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockDeleteResponse struct {
|
||||||
AffectedRowsResp int64
|
AffectedRowsResp int64
|
||||||
ExpectedErrResp error
|
|
||||||
StoreRespErr error
|
StoreRespErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
ExpectedErrResp error
|
||||||
|
mockFindStore *mockFindResponse
|
||||||
|
mockDeleteStore *mockDeleteResponse
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Name: "Successfully deletes a public dashboards",
|
Name: "Successfully deletes a public dashboard",
|
||||||
AffectedRowsResp: 1,
|
ExpectedErrResp: nil,
|
||||||
ExpectedErrResp: nil,
|
mockFindStore: &mockFindResponse{pubdash, nil},
|
||||||
StoreRespErr: nil,
|
mockDeleteStore: &mockDeleteResponse{1, nil},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Public dashboard not found",
|
Name: "Public dashboard not found",
|
||||||
AffectedRowsResp: 0,
|
ExpectedErrResp: ErrInternalServerError.Errorf("Delete: failed to find public dashboard by uid: pubdashUID: error"),
|
||||||
ExpectedErrResp: nil,
|
mockFindStore: &mockFindResponse{pubdash, errors.New("error")},
|
||||||
StoreRespErr: nil,
|
mockDeleteStore: &mockDeleteResponse{0, nil},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Database error",
|
Name: "Public dashboard not found by UID",
|
||||||
AffectedRowsResp: 0,
|
ExpectedErrResp: ErrPublicDashboardNotFound.Errorf("Delete: public dashboard not found by uid: pubdashUID"),
|
||||||
ExpectedErrResp: ErrInternalServerError.Errorf("Delete: failed to delete a public dashboard by Uid: uid db error!"),
|
mockFindStore: &mockFindResponse{nil, nil},
|
||||||
StoreRespErr: errors.New("db error!"),
|
mockDeleteStore: &mockDeleteResponse{0, nil},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Public dashboard UID does not belong to the dashboard",
|
||||||
|
ExpectedErrResp: ErrInvalidUid.Errorf("Delete: the public dashboard does not belong to the dashboard"),
|
||||||
|
mockFindStore: &mockFindResponse{&PublicDashboard{Uid: "2", OrgId: 1, DashboardUid: "wrong"}, nil},
|
||||||
|
mockDeleteStore: &mockDeleteResponse{0, nil},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
Name: "Failed to delete - Database error",
|
||||||
|
ExpectedErrResp: ErrInternalServerError.Errorf("Delete: failed to delete a public dashboard by Uid: pubdashUID db error!"),
|
||||||
|
mockFindStore: &mockFindResponse{pubdash, nil},
|
||||||
|
mockDeleteStore: &mockDeleteResponse{1, errors.New("db error!")},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
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).Return(tt.AffectedRowsResp, tt.StoreRespErr)
|
store.On("Find", mock.Anything, mock.Anything).Return(tt.mockFindStore.PublicDashboard, tt.mockFindStore.Err)
|
||||||
|
if tt.ExpectedErrResp == nil || tt.mockDeleteStore.StoreRespErr != nil {
|
||||||
|
store.On("Delete", mock.Anything, mock.Anything).Return(tt.mockDeleteStore.AffectedRowsResp, tt.mockDeleteStore.StoreRespErr)
|
||||||
|
}
|
||||||
serviceWrapper := &PublicDashboardServiceWrapperImpl{
|
serviceWrapper := &PublicDashboardServiceWrapperImpl{
|
||||||
log: log.New("test.logger"),
|
log: log.New("test.logger"),
|
||||||
store: store,
|
store: store,
|
||||||
@ -1335,10 +1363,9 @@ func TestDeletePublicDashboard(t *testing.T) {
|
|||||||
serviceWrapper: serviceWrapper,
|
serviceWrapper: serviceWrapper,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.Delete(context.Background(), "uid")
|
err := service.Delete(context.Background(), "pubdashUID", "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())
|
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user