This PR moves public dashboards into its own self contained service including API, Service, Database, and Models. Routes are mounted on the Grafana HTTPServer by the API service at injection time with wire.go. The main route that loads the frontend for public dashboards is still handled by the API package. Co-authored-by: Jesse Weaver <jesse.weaver@grafana.com> Co-authored-by: Owen Smallwood <owen.smallwood@grafana.com>
174 lines
4.4 KiB
Go
174 lines
4.4 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
|
|
"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/publicdashboards"
|
|
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
// Define the storage implementation. We're generating the mock implementation
|
|
// automatically
|
|
type PublicDashboardStoreImpl struct {
|
|
sqlStore *sqlstore.SQLStore
|
|
log log.Logger
|
|
dialect migrator.Dialect
|
|
}
|
|
|
|
// Gives us a compile time error if our database does not adhere to contract of
|
|
// the interface
|
|
var _ publicdashboards.Store = (*PublicDashboardStoreImpl)(nil)
|
|
|
|
// Factory used by wire to dependency injection
|
|
func ProvideStore(sqlStore *sqlstore.SQLStore) *PublicDashboardStoreImpl {
|
|
return &PublicDashboardStoreImpl{
|
|
sqlStore: sqlStore,
|
|
log: log.New("publicdashboards.store"),
|
|
dialect: sqlStore.Dialect,
|
|
}
|
|
}
|
|
|
|
// Retrieves public dashboard configuration
|
|
func (d *PublicDashboardStoreImpl) GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error) {
|
|
if accessToken == "" {
|
|
return nil, nil, ErrPublicDashboardIdentifierNotSet
|
|
}
|
|
|
|
// get public dashboard
|
|
pdRes := &PublicDashboard{AccessToken: accessToken}
|
|
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
|
has, err := sess.Get(pdRes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !has {
|
|
return ErrPublicDashboardNotFound
|
|
}
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// 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
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return pdRes, dashRes, err
|
|
}
|
|
|
|
// Generates a new unique uid to retrieve a public dashboard
|
|
func (d *PublicDashboardStoreImpl) GenerateNewPublicDashboardUid(ctx context.Context) (string, error) {
|
|
var uid string
|
|
|
|
err := d.sqlStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
|
for i := 0; i < 3; i++ {
|
|
uid = util.GenerateShortUID()
|
|
|
|
exists, err := sess.Get(&PublicDashboard{Uid: uid})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return ErrPublicDashboardFailedGenerateUniqueUid
|
|
})
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return uid, nil
|
|
}
|
|
|
|
// Retrieves public dashboard configuration
|
|
func (d *PublicDashboardStoreImpl) GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error) {
|
|
if dashboardUid == "" {
|
|
return nil, dashboards.ErrDashboardIdentifierNotSet
|
|
}
|
|
|
|
pdRes := &PublicDashboard{OrgId: orgId, DashboardUid: dashboardUid}
|
|
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
|
// publicDashboard
|
|
_, err := sess.Get(pdRes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return pdRes, err
|
|
}
|
|
|
|
// Persists public dashboard configuration
|
|
func (d *PublicDashboardStoreImpl) SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) (*PublicDashboard, error) {
|
|
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
|
_, err := sess.UseBool("is_enabled").Insert(&cmd.PublicDashboard)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &cmd.PublicDashboard, nil
|
|
}
|
|
|
|
// updates existing public dashboard configuration
|
|
func (d *PublicDashboardStoreImpl) UpdatePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error {
|
|
err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
|
timeSettingsJSON, err := cmd.PublicDashboard.TimeSettings.MarshalJSON()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = sess.Exec("UPDATE dashboard_public SET is_enabled = ?, time_settings = ?, updated_by = ?, updated_at = ? WHERE uid = ?",
|
|
cmd.PublicDashboard.IsEnabled,
|
|
string(timeSettingsJSON),
|
|
cmd.PublicDashboard.UpdatedBy,
|
|
cmd.PublicDashboard.UpdatedAt.UTC().Format("2006-01-02 15:04:05"),
|
|
cmd.PublicDashboard.Uid)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return err
|
|
}
|