mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Public Dashboards: Adds template variable validation for pubdash on the backend (#52566)
Validates template variables for pubdash on the backend when saving a public dashboard
This commit is contained in:
parent
9ef29bb5c3
commit
cf86c696e0
@ -126,6 +126,7 @@ func (api *Api) SavePublicDashboardConfig(c *models.ReqContext) response.Respons
|
||||
PublicDashboard: pubdash,
|
||||
}
|
||||
|
||||
// Save the public dashboard
|
||||
pubdash, err := api.PublicDashboardService.SavePublicDashboardConfig(c.Req.Context(), &dto)
|
||||
if err != nil {
|
||||
return handleDashboardErr(http.StatusInternalServerError, "Failed to save public dashboard configuration", err)
|
||||
|
@ -34,6 +34,22 @@ func ProvideStore(sqlStore *sqlstore.SQLStore) *PublicDashboardStoreImpl {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *PublicDashboardStoreImpl) GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error) {
|
||||
dashboard := &models.Dashboard{Uid: dashboardUid}
|
||||
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
has, err := sess.Get(dashboard)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return ErrPublicDashboardNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return dashboard, err
|
||||
}
|
||||
|
||||
// Retrieves public dashboard configuration
|
||||
func (d *PublicDashboardStoreImpl) GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error) {
|
||||
if accessToken == "" {
|
||||
@ -58,17 +74,7 @@ func (d *PublicDashboardStoreImpl) GetPublicDashboard(ctx context.Context, acces
|
||||
}
|
||||
|
||||
// find dashboard
|
||||
dashRes := &models.Dashboard{OrgId: pdRes.OrgId, Uid: pdRes.DashboardUid}
|
||||
err = d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
has, err := sess.Get(dashRes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return ErrPublicDashboardNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
dashRes, err := d.GetDashboard(ctx, pdRes.DashboardUid)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -24,6 +24,29 @@ var DefaultTimeSettings, _ = simplejson.NewJson([]byte(`{}`))
|
||||
// Default time to pass in with seconds rounded
|
||||
var DefaultTime = time.Now().UTC().Round(time.Second)
|
||||
|
||||
func TestIntegrationGetDashboard(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
var dashboardStore *dashboardsDB.DashboardStore
|
||||
var publicdashboardStore *PublicDashboardStoreImpl
|
||||
var savedDashboard *models.Dashboard
|
||||
|
||||
setup := func() {
|
||||
sqlStore = sqlstore.InitTestDB(t)
|
||||
dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore = ProvideStore(sqlStore)
|
||||
savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
}
|
||||
|
||||
t.Run("GetDashboard can get original dashboard by uid", func(t *testing.T) {
|
||||
setup()
|
||||
|
||||
dashboard, err := publicdashboardStore.GetDashboard(context.Background(), savedDashboard.Uid)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, savedDashboard.Uid, dashboard.Uid)
|
||||
})
|
||||
}
|
||||
|
||||
// GetPublicDashboard
|
||||
func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
|
@ -45,6 +45,10 @@ var (
|
||||
Reason: "No Uid for public dashboard specified",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrPublicDashboardHasTemplateVariables = PublicDashboardErr{
|
||||
Reason: "Public dashboard has template variables",
|
||||
StatusCode: 422,
|
||||
}
|
||||
)
|
||||
|
||||
type PublicDashboard struct {
|
||||
|
@ -64,6 +64,29 @@ func (_m *FakePublicDashboardService) BuildPublicDashboardMetricRequest(ctx cont
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetDashboard provides a mock function with given fields: ctx, dashboardUid
|
||||
func (_m *FakePublicDashboardService) GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, dashboardUid)
|
||||
|
||||
var r0 *models.Dashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Dashboard); ok {
|
||||
r0 = rf(ctx, dashboardUid)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Dashboard)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, dashboardUid)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPublicDashboard provides a mock function with given fields: ctx, accessToken
|
||||
func (_m *FakePublicDashboardService) GetPublicDashboard(ctx context.Context, accessToken string) (*models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, accessToken)
|
||||
|
@ -5,10 +5,10 @@ package publicdashboards
|
||||
import (
|
||||
context "context"
|
||||
|
||||
models "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
models "github.com/grafana/grafana/pkg/models"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
pkgmodels "github.com/grafana/grafana/pkg/models"
|
||||
publicdashboardsmodels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
|
||||
testing "testing"
|
||||
)
|
||||
@ -39,25 +39,48 @@ func (_m *FakePublicDashboardStore) GenerateNewPublicDashboardUid(ctx context.Co
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPublicDashboard provides a mock function with given fields: ctx, accessToken
|
||||
func (_m *FakePublicDashboardStore) GetPublicDashboard(ctx context.Context, accessToken string) (*models.PublicDashboard, *pkgmodels.Dashboard, error) {
|
||||
ret := _m.Called(ctx, accessToken)
|
||||
// GetDashboard provides a mock function with given fields: ctx, dashboardUid
|
||||
func (_m *FakePublicDashboardStore) GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, dashboardUid)
|
||||
|
||||
var r0 *models.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.PublicDashboard); ok {
|
||||
r0 = rf(ctx, accessToken)
|
||||
var r0 *models.Dashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *models.Dashboard); ok {
|
||||
r0 = rf(ctx, dashboardUid)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.PublicDashboard)
|
||||
r0 = ret.Get(0).(*models.Dashboard)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *pkgmodels.Dashboard
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) *pkgmodels.Dashboard); ok {
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, dashboardUid)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPublicDashboard provides a mock function with given fields: ctx, accessToken
|
||||
func (_m *FakePublicDashboardStore) GetPublicDashboard(ctx context.Context, accessToken string) (*publicdashboardsmodels.PublicDashboard, *models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, accessToken)
|
||||
|
||||
var r0 *publicdashboardsmodels.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
r0 = rf(ctx, accessToken)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*publicdashboardsmodels.PublicDashboard)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *models.Dashboard
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) *models.Dashboard); ok {
|
||||
r1 = rf(ctx, accessToken)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*pkgmodels.Dashboard)
|
||||
r1 = ret.Get(1).(*models.Dashboard)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,15 +95,15 @@ func (_m *FakePublicDashboardStore) GetPublicDashboard(ctx context.Context, acce
|
||||
}
|
||||
|
||||
// GetPublicDashboardConfig provides a mock function with given fields: ctx, orgId, dashboardUid
|
||||
func (_m *FakePublicDashboardStore) GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
|
||||
func (_m *FakePublicDashboardStore) GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
ret := _m.Called(ctx, orgId, dashboardUid)
|
||||
|
||||
var r0 *models.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *models.PublicDashboard); ok {
|
||||
var r0 *publicdashboardsmodels.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
r0 = rf(ctx, orgId, dashboardUid)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.PublicDashboard)
|
||||
r0 = ret.Get(0).(*publicdashboardsmodels.PublicDashboard)
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,20 +139,20 @@ func (_m *FakePublicDashboardStore) PublicDashboardEnabled(ctx context.Context,
|
||||
}
|
||||
|
||||
// SavePublicDashboardConfig provides a mock function with given fields: ctx, cmd
|
||||
func (_m *FakePublicDashboardStore) SavePublicDashboardConfig(ctx context.Context, cmd models.SavePublicDashboardConfigCommand) (*models.PublicDashboard, error) {
|
||||
func (_m *FakePublicDashboardStore) SavePublicDashboardConfig(ctx context.Context, cmd publicdashboardsmodels.SavePublicDashboardConfigCommand) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
ret := _m.Called(ctx, cmd)
|
||||
|
||||
var r0 *models.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.SavePublicDashboardConfigCommand) *models.PublicDashboard); ok {
|
||||
var r0 *publicdashboardsmodels.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, publicdashboardsmodels.SavePublicDashboardConfigCommand) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
r0 = rf(ctx, cmd)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.PublicDashboard)
|
||||
r0 = ret.Get(0).(*publicdashboardsmodels.PublicDashboard)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.SavePublicDashboardConfigCommand) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, publicdashboardsmodels.SavePublicDashboardConfigCommand) error); ok {
|
||||
r1 = rf(ctx, cmd)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@ -139,11 +162,11 @@ func (_m *FakePublicDashboardStore) SavePublicDashboardConfig(ctx context.Contex
|
||||
}
|
||||
|
||||
// UpdatePublicDashboardConfig provides a mock function with given fields: ctx, cmd
|
||||
func (_m *FakePublicDashboardStore) UpdatePublicDashboardConfig(ctx context.Context, cmd models.SavePublicDashboardConfigCommand) error {
|
||||
func (_m *FakePublicDashboardStore) UpdatePublicDashboardConfig(ctx context.Context, cmd publicdashboardsmodels.SavePublicDashboardConfigCommand) error {
|
||||
ret := _m.Called(ctx, cmd)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.SavePublicDashboardConfigCommand) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, publicdashboardsmodels.SavePublicDashboardConfigCommand) error); ok {
|
||||
r0 = rf(ctx, cmd)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
type Service interface {
|
||||
BuildAnonymousUser(ctx context.Context, dashboard *models.Dashboard) (*models.SignedInUser, error)
|
||||
GetPublicDashboard(ctx context.Context, accessToken string) (*models.Dashboard, error)
|
||||
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
|
||||
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
|
||||
BuildPublicDashboardMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64) (dtos.MetricRequest, error)
|
||||
@ -23,6 +24,7 @@ type Service interface {
|
||||
//go:generate mockery --name Store --structname FakePublicDashboardStore --inpackage --filename public_dashboard_store_mock.go
|
||||
type Store interface {
|
||||
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
|
||||
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
|
||||
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
||||
GenerateNewPublicDashboardUid(ctx context.Context) (string, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) (*PublicDashboard, error)
|
||||
|
@ -10,10 +10,10 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards/validation"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@ -42,6 +42,16 @@ func ProvideService(
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *PublicDashboardServiceImpl) GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error) {
|
||||
dashboard, err := pd.store.GetDashboard(ctx, dashboardUid)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dashboard, err
|
||||
}
|
||||
|
||||
// Gets public dashboard via access token
|
||||
func (pd *PublicDashboardServiceImpl) GetPublicDashboard(ctx context.Context, accessToken string) (*models.Dashboard, error) {
|
||||
pubdash, d, err := pd.store.GetPublicDashboard(ctx, accessToken)
|
||||
@ -78,8 +88,13 @@ func (pd *PublicDashboardServiceImpl) GetPublicDashboardConfig(ctx context.Conte
|
||||
// SavePublicDashboardConfig is a helper method to persist the sharing config
|
||||
// to the database. It handles validations for sharing config and persistence
|
||||
func (pd *PublicDashboardServiceImpl) SavePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error) {
|
||||
if len(dto.DashboardUid) == 0 {
|
||||
return nil, dashboards.ErrDashboardIdentifierNotSet
|
||||
dashboard, err := pd.GetDashboard(ctx, dto.DashboardUid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = validation.ValidateSavePublicDashboard(dto, dashboard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// set default value for time settings
|
||||
|
@ -120,7 +120,7 @@ func TestSavePublicDashboard(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -164,7 +164,7 @@ func TestSavePublicDashboard(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -190,7 +190,32 @@ func TestSavePublicDashboard(t *testing.T) {
|
||||
assert.Equal(t, defaultPubdashTimeSettings, pubdash.TimeSettings)
|
||||
})
|
||||
|
||||
t.Run("PLACEHOLDER - dashboard with template variables cannot be saved", func(t *testing.T) {})
|
||||
t.Run("Validate pubdash whose dashboard has template variables returns error", func(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
templateVars := make([]map[string]interface{}, 1)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, templateVars)
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
store: publicdashboardStore,
|
||||
}
|
||||
|
||||
dto := &SavePublicDashboardConfigDTO{
|
||||
DashboardUid: dashboard.Uid,
|
||||
OrgId: dashboard.OrgId,
|
||||
UserId: 7,
|
||||
PublicDashboard: &PublicDashboard{
|
||||
IsEnabled: true,
|
||||
DashboardUid: "NOTTHESAME",
|
||||
OrgId: 9999999,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdatePublicDashboard(t *testing.T) {
|
||||
@ -198,7 +223,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -265,7 +290,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -323,7 +348,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
func TestBuildAnonymousUser(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -346,8 +371,8 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
|
||||
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true)
|
||||
nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true)
|
||||
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true, []map[string]interface{}{})
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -441,7 +466,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardStore, title string, orgId int64,
|
||||
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
||||
folderId int64, isFolder bool, templateVars []map[string]interface{}, tags ...interface{}) *models.Dashboard {
|
||||
t.Helper()
|
||||
cmd := models.SaveDashboardCommand{
|
||||
OrgId: orgId,
|
||||
@ -490,6 +515,9 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto
|
||||
},
|
||||
},
|
||||
},
|
||||
"templating": map[string]interface{}{
|
||||
"list": templateVars,
|
||||
},
|
||||
}),
|
||||
}
|
||||
dash, err := dashboardStore.SaveDashboard(cmd)
|
||||
|
60
pkg/services/publicdashboards/validation/validation_test.go
Normal file
60
pkg/services/publicdashboards/validation/validation_test.go
Normal file
@ -0,0 +1,60 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
publicdashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidateSavePublicDashboard(t *testing.T) {
|
||||
t.Run("Returns validation error when dto has no dashboard uid", func(t *testing.T) {
|
||||
dashboard := models.NewDashboard("dashboardTitle")
|
||||
dto := &publicdashboardModels.SavePublicDashboardConfigDTO{DashboardUid: "", OrgId: 1, UserId: 1, PublicDashboard: nil}
|
||||
|
||||
err := ValidateSavePublicDashboard(dto, dashboard)
|
||||
require.ErrorContains(t, err, "Unique identifier needed to be able to get a dashboard")
|
||||
})
|
||||
|
||||
t.Run("Returns no validation error when dto has dashboard uid", func(t *testing.T) {
|
||||
dashboard := models.NewDashboard("dashboardTitle")
|
||||
dto := &publicdashboardModels.SavePublicDashboardConfigDTO{DashboardUid: "abc123", OrgId: 1, UserId: 1, PublicDashboard: nil}
|
||||
|
||||
err := ValidateSavePublicDashboard(dto, dashboard)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Returns validation error when dashboard has template variables", func(t *testing.T) {
|
||||
templateVars := []byte(`{
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"name": "templateVariableName"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
dashboardData, _ := simplejson.NewJson(templateVars)
|
||||
dashboard := models.NewDashboardFromJson(dashboardData)
|
||||
dto := &publicdashboardModels.SavePublicDashboardConfigDTO{DashboardUid: "abc123", OrgId: 1, UserId: 1, PublicDashboard: nil}
|
||||
|
||||
err := ValidateSavePublicDashboard(dto, dashboard)
|
||||
require.ErrorContains(t, err, "Public dashboard has template variables")
|
||||
})
|
||||
|
||||
t.Run("Returns no validation error when dashboard has no template variables", func(t *testing.T) {
|
||||
templateVars := []byte(`{
|
||||
"templating": {
|
||||
"list": []
|
||||
}
|
||||
}`)
|
||||
dashboardData, _ := simplejson.NewJson(templateVars)
|
||||
dashboard := models.NewDashboardFromJson(dashboardData)
|
||||
dto := &publicdashboardModels.SavePublicDashboardConfigDTO{DashboardUid: "abc123", OrgId: 1, UserId: 1, PublicDashboard: nil}
|
||||
|
||||
err := ValidateSavePublicDashboard(dto, dashboard)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
27
pkg/services/publicdashboards/validation/validator.go
Normal file
27
pkg/services/publicdashboards/validation/validator.go
Normal file
@ -0,0 +1,27 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
publicDashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
)
|
||||
|
||||
func ValidateSavePublicDashboard(dto *publicDashboardModels.SavePublicDashboardConfigDTO, dashboard *models.Dashboard) error {
|
||||
var err error
|
||||
|
||||
if len(dto.DashboardUid) == 0 {
|
||||
return dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
if hasTemplateVariables(dashboard) {
|
||||
return publicDashboardModels.ErrPublicDashboardHasTemplateVariables
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func hasTemplateVariables(dashboard *models.Dashboard) bool {
|
||||
templateVariables := dashboard.Data.Get("templating").Get("list").MustArray()
|
||||
|
||||
return len(templateVariables) > 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user