mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
public-dashboards: Add log statement when public dashboard enabled or disabled (#54133)
* refactor apis for consistent outputs * add dashboardUid validation at API layer * add check for empty dashboardUid on SavePublicDashboard * remove public dashboard errors from models package. Co-authored-by: Ezequiel Victorero <evictorero@gmail.com>
This commit is contained in:
parent
b9be2815d3
commit
5cb9fca990
@ -125,28 +125,6 @@ var (
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardFailedGenerateUniqueUid = DashboardErr{
|
||||
Reason: "Failed to generate unique public dashboard id",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrPublicDashboardFailedGenerateAccesstoken = DashboardErr{
|
||||
Reason: "Failed to public dashboard access token",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrPublicDashboardNotFound = DashboardErr{
|
||||
Reason: "Public dashboard not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardPanelNotFound = DashboardErr{
|
||||
Reason: "Panel not found in dashboard",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardIdentifierNotSet = DashboardErr{
|
||||
Reason: "No Uid for public dashboard specified",
|
||||
StatusCode: 400,
|
||||
}
|
||||
|
||||
ErrFolderNotFound = errors.New("folder not found")
|
||||
ErrFolderVersionMismatch = errors.New("the folder has been changed by someone else")
|
||||
|
@ -120,23 +120,28 @@ func (api *Api) GetPublicDashboardConfig(c *models.ReqContext) response.Response
|
||||
// Sets public dashboard configuration for dashboard
|
||||
// POST /api/dashboards/uid/:uid/public-config
|
||||
func (api *Api) SavePublicDashboardConfig(c *models.ReqContext) response.Response {
|
||||
// exit if we don't have a valid dashboardUid
|
||||
dashboardUid := web.Params(c.Req)[":uid"]
|
||||
if dashboardUid == "" || !util.IsValidShortUID(dashboardUid) {
|
||||
handleDashboardErr(http.StatusBadRequest, "no dashboardUid", dashboards.ErrDashboardIdentifierNotSet)
|
||||
}
|
||||
|
||||
pubdash := &PublicDashboard{}
|
||||
if err := web.Bind(c.Req, pubdash); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
// Always set the org id to the current auth session orgId
|
||||
// Always set the orgID and userID from the session
|
||||
pubdash.OrgId = c.OrgID
|
||||
|
||||
dto := SavePublicDashboardConfigDTO{
|
||||
OrgId: c.OrgID,
|
||||
DashboardUid: web.Params(c.Req)[":uid"],
|
||||
UserId: c.UserID,
|
||||
OrgId: c.OrgID,
|
||||
DashboardUid: dashboardUid,
|
||||
PublicDashboard: pubdash,
|
||||
}
|
||||
|
||||
// Save the public dashboard
|
||||
pubdash, err := api.PublicDashboardService.SavePublicDashboardConfig(c.Req.Context(), &dto)
|
||||
pubdash, err := api.PublicDashboardService.SavePublicDashboardConfig(c.Req.Context(), c.SignedInUser, &dto)
|
||||
if err != nil {
|
||||
return handleDashboardErr(http.StatusInternalServerError, "Failed to save public dashboard configuration", err)
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func TestApiSavePublicDashboardConfig(t *testing.T) {
|
||||
for _, test := range testCases {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
service := publicdashboards.NewFakePublicDashboardService(t)
|
||||
service.On("SavePublicDashboardConfig", mock.Anything, mock.AnythingOfType("*models.SavePublicDashboardConfigDTO")).
|
||||
service.On("SavePublicDashboardConfig", mock.Anything, mock.Anything, mock.AnythingOfType("*models.SavePublicDashboardConfigDTO")).
|
||||
Return(&PublicDashboard{IsEnabled: true}, test.SaveDashboardErr)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
@ -558,7 +558,7 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
|
||||
cfg := setting.NewCfg()
|
||||
cfg.RBACEnabled = false
|
||||
service := publicdashboardsService.ProvideService(cfg, store)
|
||||
pubdash, err := service.SavePublicDashboardConfig(context.Background(), savePubDashboardCmd)
|
||||
pubdash, err := service.SavePublicDashboardConfig(context.Background(), &user.SignedInUser{}, savePubDashboardCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
// setup test server
|
||||
|
@ -113,6 +113,31 @@ func (d *PublicDashboardStoreImpl) GenerateNewPublicDashboardUid(ctx context.Con
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
// Retrieves public dashboard configuration by Uid
|
||||
func (d *PublicDashboardStoreImpl) GetPublicDashboardByUid(ctx context.Context, uid string) (*PublicDashboard, error) {
|
||||
if uid == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var found bool
|
||||
pdRes := &PublicDashboard{Uid: uid}
|
||||
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
var err error
|
||||
found, err = sess.Get(pdRes)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return pdRes, err
|
||||
}
|
||||
|
||||
// Retrieves public dashboard configuration
|
||||
func (d *PublicDashboardStoreImpl) GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error) {
|
||||
if dashboardUid == "" {
|
||||
@ -138,7 +163,11 @@ func (d *PublicDashboardStoreImpl) GetPublicDashboardConfig(ctx context.Context,
|
||||
}
|
||||
|
||||
// Persists public dashboard configuration
|
||||
func (d *PublicDashboardStoreImpl) SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) (*PublicDashboard, error) {
|
||||
func (d *PublicDashboardStoreImpl) SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error {
|
||||
if cmd.PublicDashboard.DashboardUid == "" {
|
||||
return dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
_, err := sess.UseBool("is_enabled").Insert(&cmd.PublicDashboard)
|
||||
if err != nil {
|
||||
@ -148,11 +177,7 @@ func (d *PublicDashboardStoreImpl) SavePublicDashboardConfig(ctx context.Context
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cmd.PublicDashboard, nil
|
||||
return err
|
||||
}
|
||||
|
||||
// updates existing public dashboard configuration
|
||||
|
@ -67,7 +67,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
t.Run("AccessTokenExists will return true when at least one public dashboard has a matching access token", func(t *testing.T) {
|
||||
setup()
|
||||
|
||||
_, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "abc123",
|
||||
@ -98,7 +98,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
t.Run("PublicDashboardEnabled Will return true when dashboard has at least one enabled public dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
|
||||
_, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "abc123",
|
||||
@ -120,7 +120,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
t.Run("PublicDashboardEnabled will return false when dashboard has public dashboards but they are not enabled", func(t *testing.T) {
|
||||
setup()
|
||||
|
||||
_, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: false,
|
||||
Uid: "abc123",
|
||||
@ -141,7 +141,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
|
||||
t.Run("returns PublicDashboard and Dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
pubdash, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
cmd := SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "abc1234",
|
||||
@ -152,14 +152,16 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
CreatedBy: 7,
|
||||
AccessToken: "NOTAREALUUID",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
pd, d, err := publicdashboardStore.GetPublicDashboard(context.Background(), "NOTAREALUUID")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, pd, pubdash)
|
||||
assert.Equal(t, d.Uid, pubdash.DashboardUid)
|
||||
assert.Equal(t, pd, &cmd.PublicDashboard)
|
||||
assert.Equal(t, d.Uid, cmd.PublicDashboard.DashboardUid)
|
||||
})
|
||||
|
||||
t.Run("returns ErrPublicDashboardNotFound with empty uid", func(t *testing.T) {
|
||||
@ -176,7 +178,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
|
||||
t.Run("returns ErrDashboardNotFound when Dashboard not found", func(t *testing.T) {
|
||||
setup()
|
||||
_, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "abc1234",
|
||||
@ -219,10 +221,9 @@ func TestIntegrationGetPublicDashboardConfig(t *testing.T) {
|
||||
require.Error(t, dashboards.ErrDashboardIdentifierNotSet, err)
|
||||
})
|
||||
|
||||
t.Run("returns isPublic along with public dashboard when exists", func(t *testing.T) {
|
||||
t.Run("returns along with public dashboard when exists", func(t *testing.T) {
|
||||
setup()
|
||||
// insert test public dashboard
|
||||
resp, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
cmd := SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "pubdash-uid",
|
||||
@ -232,14 +233,17 @@ func TestIntegrationGetPublicDashboardConfig(t *testing.T) {
|
||||
CreatedAt: DefaultTime,
|
||||
CreatedBy: 7,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// insert test public dashboard
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
// retrieve from db
|
||||
pubdash, err := publicdashboardStore.GetPublicDashboardConfig(context.Background(), savedDashboard.OrgId, savedDashboard.Uid)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, assert.ObjectsAreEqualValues(resp, pubdash))
|
||||
assert.True(t, assert.ObjectsAreEqual(resp, pubdash))
|
||||
assert.True(t, assert.ObjectsAreEqualValues(&cmd.PublicDashboard, pubdash))
|
||||
})
|
||||
}
|
||||
|
||||
@ -261,7 +265,7 @@ func TestIntegrationSavePublicDashboardConfig(t *testing.T) {
|
||||
|
||||
t.Run("saves new public dashboard", func(t *testing.T) {
|
||||
setup()
|
||||
resp, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "pubdash-uid",
|
||||
@ -278,9 +282,6 @@ func TestIntegrationSavePublicDashboardConfig(t *testing.T) {
|
||||
pubdash, err := publicdashboardStore.GetPublicDashboardConfig(context.Background(), savedDashboard.OrgId, savedDashboard.Uid)
|
||||
require.NoError(t, err)
|
||||
|
||||
//verify saved response and queried response are the same
|
||||
assert.Equal(t, resp, pubdash)
|
||||
|
||||
// verify we have a valid uid
|
||||
assert.True(t, util.IsValidShortUID(pubdash.Uid))
|
||||
|
||||
@ -289,6 +290,23 @@ func TestIntegrationSavePublicDashboardConfig(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.False(t, pubdash2.IsEnabled)
|
||||
})
|
||||
|
||||
t.Run("guards from saving without dashboardUid", func(t *testing.T) {
|
||||
setup()
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
IsEnabled: true,
|
||||
Uid: "pubdash-uid",
|
||||
DashboardUid: "",
|
||||
OrgId: savedDashboard.OrgId,
|
||||
TimeSettings: DefaultTimeSettings,
|
||||
CreatedAt: DefaultTime,
|
||||
CreatedBy: 7,
|
||||
AccessToken: "NOTAREALUUID",
|
||||
},
|
||||
})
|
||||
assert.Error(t, err, dashboards.ErrDashboardIdentifierNotSet)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationUpdatePublicDashboard(t *testing.T) {
|
||||
@ -310,7 +328,7 @@ func TestIntegrationUpdatePublicDashboard(t *testing.T) {
|
||||
setup()
|
||||
|
||||
pdUid := "asdf1234"
|
||||
_, err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err := publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
Uid: pdUid,
|
||||
DashboardUid: savedDashboard.Uid,
|
||||
@ -325,7 +343,7 @@ func TestIntegrationUpdatePublicDashboard(t *testing.T) {
|
||||
|
||||
// inserting two different public dashboards to test update works and only affect the desired pd by uid
|
||||
anotherPdUid := "anotherUid"
|
||||
_, err = publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
err = publicdashboardStore.SavePublicDashboardConfig(context.Background(), SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
Uid: anotherPdUid,
|
||||
DashboardUid: anotherSavedDashboard.Uid,
|
||||
@ -365,11 +383,11 @@ func TestIntegrationUpdatePublicDashboard(t *testing.T) {
|
||||
// not updated dashboard shouldn't have changed
|
||||
pdNotUpdatedRetrieved, err := publicdashboardStore.GetPublicDashboardConfig(context.Background(), anotherSavedDashboard.OrgId, anotherSavedDashboard.Uid)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NotEqual(t, updatedPublicDashboard.UpdatedAt, pdNotUpdatedRetrieved.UpdatedAt)
|
||||
assert.NotEqual(t, updatedPublicDashboard.IsEnabled, pdNotUpdatedRetrieved.IsEnabled)
|
||||
})
|
||||
}
|
||||
|
||||
func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardStore, title string, orgId int64,
|
||||
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
||||
t.Helper()
|
||||
|
@ -186,13 +186,13 @@ func (_m *FakePublicDashboardService) PublicDashboardEnabled(ctx context.Context
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SavePublicDashboardConfig provides a mock function with given fields: ctx, dto
|
||||
func (_m *FakePublicDashboardService) SavePublicDashboardConfig(ctx context.Context, dto *publicdashboardsmodels.SavePublicDashboardConfigDTO) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
ret := _m.Called(ctx, dto)
|
||||
// SavePublicDashboardConfig provides a mock function with given fields: ctx, u, dto
|
||||
func (_m *FakePublicDashboardService) SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *publicdashboardsmodels.SavePublicDashboardConfigDTO) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
ret := _m.Called(ctx, u, dto)
|
||||
|
||||
var r0 *publicdashboardsmodels.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *publicdashboardsmodels.SavePublicDashboardConfigDTO) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
r0 = rf(ctx, dto)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *user.SignedInUser, *publicdashboardsmodels.SavePublicDashboardConfigDTO) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
r0 = rf(ctx, u, dto)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*publicdashboardsmodels.PublicDashboard)
|
||||
@ -200,8 +200,8 @@ func (_m *FakePublicDashboardService) SavePublicDashboardConfig(ctx context.Cont
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *publicdashboardsmodels.SavePublicDashboardConfigDTO) error); ok {
|
||||
r1 = rf(ctx, dto)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *user.SignedInUser, *publicdashboardsmodels.SavePublicDashboardConfigDTO) error); ok {
|
||||
r1 = rf(ctx, u, dto)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
@ -115,6 +115,29 @@ func (_m *FakePublicDashboardStore) GetPublicDashboard(ctx context.Context, acce
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GetPublicDashboardByUid provides a mock function with given fields: ctx, uid
|
||||
func (_m *FakePublicDashboardStore) GetPublicDashboardByUid(ctx context.Context, uid string) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
ret := _m.Called(ctx, uid)
|
||||
|
||||
var r0 *publicdashboardsmodels.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
r0 = rf(ctx, uid)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*publicdashboardsmodels.PublicDashboard)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, uid)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPublicDashboardConfig provides a mock function with given fields: ctx, orgId, dashboardUid
|
||||
func (_m *FakePublicDashboardStore) GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
ret := _m.Called(ctx, orgId, dashboardUid)
|
||||
@ -160,26 +183,17 @@ 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 publicdashboardsmodels.SavePublicDashboardConfigCommand) (*publicdashboardsmodels.PublicDashboard, error) {
|
||||
func (_m *FakePublicDashboardStore) SavePublicDashboardConfig(ctx context.Context, cmd publicdashboardsmodels.SavePublicDashboardConfigCommand) error {
|
||||
ret := _m.Called(ctx, cmd)
|
||||
|
||||
var r0 *publicdashboardsmodels.PublicDashboard
|
||||
if rf, ok := ret.Get(0).(func(context.Context, publicdashboardsmodels.SavePublicDashboardConfigCommand) *publicdashboardsmodels.PublicDashboard); ok {
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, publicdashboardsmodels.SavePublicDashboardConfigCommand) error); ok {
|
||||
r0 = rf(ctx, cmd)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*publicdashboardsmodels.PublicDashboard)
|
||||
}
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, publicdashboardsmodels.SavePublicDashboardConfigCommand) error); ok {
|
||||
r1 = rf(ctx, cmd)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdatePublicDashboardConfig provides a mock function with given fields: ctx, cmd
|
||||
|
@ -17,7 +17,7 @@ type Service 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)
|
||||
SavePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
|
||||
BuildPublicDashboardMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64) (dtos.MetricRequest, error)
|
||||
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
|
||||
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
|
||||
@ -28,8 +28,9 @@ 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)
|
||||
GetPublicDashboardByUid(ctx context.Context, uid string) (*PublicDashboard, error)
|
||||
GenerateNewPublicDashboardUid(ctx context.Context) (string, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) (*PublicDashboard, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error
|
||||
UpdatePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error
|
||||
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
|
||||
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
|
||||
|
@ -86,11 +86,12 @@ 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) {
|
||||
func (pd *PublicDashboardServiceImpl) SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error) {
|
||||
dashboard, err := pd.GetDashboard(ctx, dto.DashboardUid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = validation.ValidateSavePublicDashboard(dto, dashboard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -101,22 +102,45 @@ func (pd *PublicDashboardServiceImpl) SavePublicDashboardConfig(ctx context.Cont
|
||||
dto.PublicDashboard.TimeSettings = simplejson.New()
|
||||
}
|
||||
|
||||
if dto.PublicDashboard.Uid == "" {
|
||||
return pd.savePublicDashboardConfig(ctx, dto)
|
||||
}
|
||||
|
||||
return pd.updatePublicDashboardConfig(ctx, dto)
|
||||
}
|
||||
|
||||
func (pd *PublicDashboardServiceImpl) savePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error) {
|
||||
uid, err := pd.store.GenerateNewPublicDashboardUid(ctx)
|
||||
// get existing public dashboard if exists
|
||||
existingPubdash, err := pd.store.GetPublicDashboardByUid(ctx, dto.PublicDashboard.Uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// save changes
|
||||
var pubdashUid string
|
||||
if existingPubdash == nil {
|
||||
pubdashUid, err = pd.savePublicDashboardConfig(ctx, dto)
|
||||
} else {
|
||||
pubdashUid, err = pd.updatePublicDashboardConfig(ctx, dto)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Get latest public dashboard to return
|
||||
newPubdash, err := pd.store.GetPublicDashboardByUid(ctx, pubdashUid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pd.logIsEnabledChanged(existingPubdash, newPubdash, u)
|
||||
|
||||
return newPubdash, err
|
||||
}
|
||||
|
||||
// Called by SavePublicDashboardConfig this handles business logic
|
||||
// to generate token and calls create at the database layer
|
||||
func (pd *PublicDashboardServiceImpl) savePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (string, error) {
|
||||
uid, err := pd.store.GenerateNewPublicDashboardUid(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
accessToken, err := GenerateAccessToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd := SavePublicDashboardConfigCommand{
|
||||
@ -132,10 +156,17 @@ func (pd *PublicDashboardServiceImpl) savePublicDashboardConfig(ctx context.Cont
|
||||
},
|
||||
}
|
||||
|
||||
return pd.store.SavePublicDashboardConfig(ctx, cmd)
|
||||
err = pd.store.SavePublicDashboardConfig(ctx, cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
func (pd *PublicDashboardServiceImpl) updatePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error) {
|
||||
// Called by SavePublicDashboard this handles business logic for updating a
|
||||
// dashboard and calls update at the database layer
|
||||
func (pd *PublicDashboardServiceImpl) updatePublicDashboardConfig(ctx context.Context, dto *SavePublicDashboardConfigDTO) (string, error) {
|
||||
cmd := SavePublicDashboardConfigCommand{
|
||||
PublicDashboard: PublicDashboard{
|
||||
Uid: dto.PublicDashboard.Uid,
|
||||
@ -146,17 +177,7 @@ func (pd *PublicDashboardServiceImpl) updatePublicDashboardConfig(ctx context.Co
|
||||
},
|
||||
}
|
||||
|
||||
err := pd.store.UpdatePublicDashboardConfig(ctx, cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publicDashboard, err := pd.store.GetPublicDashboardConfig(ctx, dto.OrgId, dto.DashboardUid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return publicDashboard, nil
|
||||
return dto.PublicDashboard.Uid, pd.store.UpdatePublicDashboardConfig(ctx, cmd)
|
||||
}
|
||||
|
||||
// BuildPublicDashboardMetricRequest merges public dashboard parameters with
|
||||
@ -218,3 +239,23 @@ func GenerateAccessToken() (string, error) {
|
||||
|
||||
return fmt.Sprintf("%x", token[:]), nil
|
||||
}
|
||||
|
||||
// Log when PublicDashboard.IsEnabled changed
|
||||
func (pd *PublicDashboardServiceImpl) logIsEnabledChanged(existingPubdash *PublicDashboard, newPubdash *PublicDashboard, u *user.SignedInUser) {
|
||||
if publicDashboardIsEnabledChanged(existingPubdash, newPubdash) {
|
||||
verb := "disabled"
|
||||
if newPubdash.IsEnabled {
|
||||
verb = "enabled"
|
||||
}
|
||||
pd.log.Info(fmt.Sprintf("Public dashboard %v: dashboardUid: %v, user:%v", verb, newPubdash.Uid, u.Login))
|
||||
}
|
||||
}
|
||||
|
||||
// Checks to see if PublicDashboard.Isenabled is true on create or changed on update
|
||||
func publicDashboardIsEnabledChanged(existingPubdash *PublicDashboard, newPubdash *PublicDashboard) bool {
|
||||
// creating dashboard, enabled true
|
||||
newDashCreated := existingPubdash == nil && newPubdash.IsEnabled
|
||||
// updating dashboard, enabled changed
|
||||
isEnabledChanged := existingPubdash != nil && newPubdash.IsEnabled != existingPubdash.IsEnabled
|
||||
return newDashCreated || isEnabledChanged
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -25,6 +26,7 @@ import (
|
||||
var timeSettings, _ = simplejson.NewJson([]byte(`{"from": "now-12", "to": "now"}`))
|
||||
var defaultPubdashTimeSettings, _ = simplejson.NewJson([]byte(`{}`))
|
||||
var dashboardData = simplejson.NewFromAny(map[string]interface{}{"time": map[string]interface{}{"from": "now-8", "to": "now"}})
|
||||
var SignedInUser = &user.SignedInUser{UserID: 1234, Login: "user@login.com"}
|
||||
|
||||
func TestLogPrefix(t *testing.T) {
|
||||
assert.Equal(t, LogPrefix, "publicdashboards.service")
|
||||
@ -134,7 +136,7 @@ func TestSavePublicDashboard(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
pubdash, err := service.GetPublicDashboardConfig(context.Background(), dashboard.OrgId, dashboard.Uid)
|
||||
@ -177,7 +179,7 @@ func TestSavePublicDashboard(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
pubdash, err := service.GetPublicDashboardConfig(context.Background(), dashboard.OrgId, dashboard.Uid)
|
||||
@ -208,7 +210,7 @@ func TestSavePublicDashboard(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
@ -235,10 +237,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
savedPubdash, err := service.GetPublicDashboardConfig(context.Background(), dashboard.OrgId, dashboard.Uid)
|
||||
savedPubdash, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
// attempt to overwrite settings
|
||||
@ -261,10 +260,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
|
||||
// Since the dto.PublicDashboard has a uid, this will call
|
||||
// service.updatePublicDashboardConfig
|
||||
_, err = service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedPubdash, err := service.GetPublicDashboardConfig(context.Background(), dashboard.OrgId, dashboard.Uid)
|
||||
updatedPubdash, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
// don't get updated
|
||||
@ -304,10 +300,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
|
||||
// Since the dto.PublicDashboard has a uid, this will call
|
||||
// service.updatePublicDashboardConfig
|
||||
_, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
savedPubdash, err := service.GetPublicDashboardConfig(context.Background(), dashboard.OrgId, dashboard.Uid)
|
||||
savedPubdash, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
// attempt to overwrite settings
|
||||
@ -327,10 +320,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
_, err = service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedPubdash, err := service.GetPublicDashboardConfig(context.Background(), dashboard.OrgId, dashboard.Uid)
|
||||
updatedPubdash, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
timeSettings, err := simplejson.NewJson([]byte("{}"))
|
||||
@ -385,7 +375,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
publicDashboardPD, err := service.SavePublicDashboardConfig(context.Background(), dto)
|
||||
publicDashboardPD, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
nonPublicDto := &SavePublicDashboardConfigDTO{
|
||||
@ -399,7 +389,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
nonPublicDashboardPD, err := service.SavePublicDashboardConfig(context.Background(), nonPublicDto)
|
||||
nonPublicDashboardPD, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, nonPublicDto)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("extracts queries from provided dashboard", func(t *testing.T) {
|
||||
@ -522,3 +512,21 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto
|
||||
dash.Data.Set("uid", dash.Uid)
|
||||
return dash
|
||||
}
|
||||
|
||||
func TestDashboardEnabledChanged(t *testing.T) {
|
||||
t.Run("created isEnabled: false", func(t *testing.T) {
|
||||
assert.False(t, publicDashboardIsEnabledChanged(nil, &PublicDashboard{IsEnabled: false}))
|
||||
})
|
||||
|
||||
t.Run("created isEnabled: true", func(t *testing.T) {
|
||||
assert.True(t, publicDashboardIsEnabledChanged(nil, &PublicDashboard{IsEnabled: true}))
|
||||
})
|
||||
|
||||
t.Run("updated isEnabled same", func(t *testing.T) {
|
||||
assert.False(t, publicDashboardIsEnabledChanged(&PublicDashboard{IsEnabled: true}, &PublicDashboard{IsEnabled: true}))
|
||||
})
|
||||
|
||||
t.Run("updated isEnabled changed", func(t *testing.T) {
|
||||
assert.True(t, publicDashboardIsEnabledChanged(&PublicDashboard{IsEnabled: false}, &PublicDashboard{IsEnabled: true}))
|
||||
})
|
||||
}
|
||||
|
@ -10,22 +10,6 @@ import (
|
||||
)
|
||||
|
||||
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": {
|
||||
|
@ -2,22 +2,15 @@ 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
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasTemplateVariables(dashboard *models.Dashboard) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user