2022-06-02 18:27:23 -08:00
package database
import (
"context"
2022-09-13 13:33:41 -03:00
"encoding/json"
2022-06-02 18:27:23 -08:00
2022-10-19 09:02:15 -04:00
"github.com/grafana/grafana/pkg/infra/db"
2022-07-06 15:51:44 -08:00
"github.com/grafana/grafana/pkg/infra/log"
2022-06-30 09:31:54 -04:00
"github.com/grafana/grafana/pkg/services/dashboards"
2022-07-06 15:51:44 -08:00
"github.com/grafana/grafana/pkg/services/publicdashboards"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
2023-03-08 14:54:35 -06:00
"github.com/grafana/grafana/pkg/services/sqlstore"
2022-06-02 18:27:23 -08:00
)
2022-07-06 15:51:44 -08:00
// Define the storage implementation. We're generating the mock implementation
// automatically
type PublicDashboardStoreImpl struct {
2022-10-14 15:33:06 -04:00
sqlStore db . DB
2022-07-06 15:51:44 -08:00
log log . Logger
}
2022-08-01 14:46:48 -08:00
var LogPrefix = "publicdashboards.store"
2022-07-06 15:51:44 -08:00
// 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
2022-10-14 15:33:06 -04:00
func ProvideStore ( sqlStore db . DB ) * PublicDashboardStoreImpl {
2022-07-06 15:51:44 -08:00
return & PublicDashboardStoreImpl {
sqlStore : sqlStore ,
2022-08-01 14:46:48 -08:00
log : log . New ( LogPrefix ) ,
2022-07-06 15:51:44 -08:00
}
}
2022-10-26 14:49:43 -03:00
// FindAll Returns a list of public dashboards by orgId
2022-10-25 21:40:42 -03:00
func ( d * PublicDashboardStoreImpl ) FindAll ( ctx context . Context , orgId int64 ) ( [ ] PublicDashboardListResponse , error ) {
2022-10-12 21:36:05 -08:00
resp := make ( [ ] PublicDashboardListResponse , 0 )
2022-10-31 18:16:07 -03:00
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
2022-11-01 16:56:19 -03:00
sess . Table ( "dashboard_public" ) . Select (
"dashboard_public.uid, dashboard_public.access_token, dashboard.uid as dashboard_uid, dashboard_public.is_enabled, dashboard.title" ) .
2022-10-12 21:36:05 -08:00
Join ( "LEFT" , "dashboard" , "dashboard.uid = dashboard_public.dashboard_uid AND dashboard.org_id = dashboard_public.org_id" ) .
Where ( "dashboard_public.org_id = ?" , orgId ) .
2022-10-19 17:24:00 -03:00
OrderBy ( " is_enabled DESC, dashboard.title IS NULL, dashboard.title ASC" )
2022-10-12 21:36:05 -08:00
err := sess . Find ( & resp )
return err
} )
if err != nil {
return nil , err
}
return resp , nil
}
2022-10-31 11:22:27 -03:00
// FindDashboard returns a dashboard by orgId and dashboardUid
2023-01-16 16:33:55 +01:00
func ( d * PublicDashboardStoreImpl ) FindDashboard ( ctx context . Context , orgId int64 , dashboardUid string ) ( * dashboards . Dashboard , error ) {
dashboard := & dashboards . Dashboard { OrgID : orgId , UID : dashboardUid }
2022-10-31 11:22:27 -03:00
var found bool
2022-10-31 18:16:07 -03:00
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
2022-10-31 11:22:27 -03:00
var err error
found , err = sess . Get ( dashboard )
return err
2022-07-21 13:56:20 -06:00
} )
2022-11-03 11:30:12 -08:00
if err != nil {
return nil , err
}
2022-10-31 11:22:27 -03:00
if ! found {
return nil , nil
}
2022-11-03 11:30:12 -08:00
return dashboard , nil
2022-07-21 13:56:20 -06:00
}
2022-10-27 17:08:11 -08:00
// Find Returns public dashboard by Uid or nil if not found
2022-10-25 21:40:42 -03:00
func ( d * PublicDashboardStoreImpl ) Find ( ctx context . Context , uid string ) ( * PublicDashboard , error ) {
2022-10-25 16:29:18 -03:00
if uid == "" {
return nil , nil
}
2022-06-22 13:58:52 -08:00
2022-10-25 16:29:18 -03:00
var found bool
2022-11-03 11:30:12 -08:00
publicDashboard := & PublicDashboard { Uid : uid }
2022-10-31 18:16:07 -03:00
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
2022-10-25 16:29:18 -03:00
var err error
2022-11-03 11:30:12 -08:00
found , err = sess . Get ( publicDashboard )
2022-10-25 16:29:18 -03:00
return err
2022-06-22 13:58:52 -08:00
} )
if err != nil {
2022-10-25 16:29:18 -03:00
return nil , err
2022-06-02 18:27:23 -08:00
}
2022-10-25 16:29:18 -03:00
if ! found {
return nil , nil
2022-10-13 11:32:32 -03:00
}
2022-11-03 11:30:12 -08:00
return publicDashboard , nil
2022-10-13 11:32:32 -03:00
}
2022-10-26 12:53:33 -03:00
// FindByAccessToken Returns public dashboard by access token or nil if not found
2022-10-25 21:40:42 -03:00
func ( d * PublicDashboardStoreImpl ) FindByAccessToken ( ctx context . Context , accessToken string ) ( * PublicDashboard , error ) {
2022-10-25 16:29:18 -03:00
if accessToken == "" {
2022-10-31 11:22:27 -03:00
return nil , nil
2022-08-26 11:28:54 -08:00
}
var found bool
2022-11-03 11:30:12 -08:00
publicDashboard := & PublicDashboard { AccessToken : accessToken }
2022-10-31 18:16:07 -03:00
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
2022-08-26 11:28:54 -08:00
var err error
2022-11-03 11:30:12 -08:00
found , err = sess . Get ( publicDashboard )
2022-08-26 11:28:54 -08:00
return err
} )
if err != nil {
return nil , err
}
if ! found {
return nil , nil
}
2022-11-03 11:30:12 -08:00
return publicDashboard , nil
2022-08-26 11:28:54 -08:00
}
2022-10-31 11:22:27 -03:00
// FindByDashboardUid Retrieves public dashboard by dashboard uid or nil if not found
2022-10-25 21:40:42 -03:00
func ( d * PublicDashboardStoreImpl ) FindByDashboardUid ( ctx context . Context , orgId int64 , dashboardUid string ) ( * PublicDashboard , error ) {
2022-10-31 11:22:27 -03:00
if dashboardUid == "" || orgId == 0 {
return nil , nil
2022-06-02 18:27:23 -08:00
}
2022-10-31 11:22:27 -03:00
var found bool
2022-10-31 18:16:07 -03:00
publicDashboard := & PublicDashboard { OrgId : orgId , DashboardUid : dashboardUid }
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
2022-10-31 11:22:27 -03:00
var err error
2022-10-31 18:16:07 -03:00
found , err = sess . Get ( publicDashboard )
2022-06-02 18:27:23 -08:00
if err != nil {
return err
}
return nil
} )
if err != nil {
return nil , err
}
2022-10-31 11:22:27 -03:00
if ! found {
return nil , nil
}
2022-11-03 11:30:12 -08:00
return publicDashboard , nil
2022-10-31 18:16:07 -03:00
}
2022-10-25 21:40:42 -03:00
// ExistsEnabledByDashboardUid Responds true if there is an enabled public dashboard for a dashboard uid
func ( d * PublicDashboardStoreImpl ) ExistsEnabledByDashboardUid ( ctx context . Context , dashboardUid string ) ( bool , error ) {
2022-07-19 17:44:41 -06:00
hasPublicDashboard := false
2022-10-19 09:02:15 -04:00
err := d . sqlStore . WithDbSession ( ctx , func ( dbSession * db . Session ) error {
2022-07-19 17:44:41 -06:00
sql := "SELECT COUNT(*) FROM dashboard_public WHERE dashboard_uid=? AND is_enabled=true"
result , err := dbSession . SQL ( sql , dashboardUid ) . Count ( )
if err != nil {
return err
}
hasPublicDashboard = result > 0
return err
} )
return hasPublicDashboard , err
}
2022-08-10 11:14:48 -06:00
2022-10-25 21:40:42 -03:00
// ExistsEnabledByAccessToken Responds true if the accessToken exists and the public dashboard is enabled
func ( d * PublicDashboardStoreImpl ) ExistsEnabledByAccessToken ( ctx context . Context , accessToken string ) ( bool , error ) {
2022-08-10 11:14:48 -06:00
hasPublicDashboard := false
2022-10-19 09:02:15 -04:00
err := d . sqlStore . WithDbSession ( ctx , func ( dbSession * db . Session ) error {
2022-08-10 11:14:48 -06:00
sql := "SELECT COUNT(*) FROM dashboard_public WHERE access_token=? AND is_enabled=true"
result , err := dbSession . SQL ( sql , accessToken ) . Count ( )
if err != nil {
return err
}
hasPublicDashboard = result > 0
return err
} )
return hasPublicDashboard , err
}
2022-10-06 12:35:19 -08:00
2023-03-03 10:12:29 -03:00
// GetOrgIdByAccessToken Returns the public dashboard OrgId if exists.
2022-10-25 21:40:42 -03:00
func ( d * PublicDashboardStoreImpl ) GetOrgIdByAccessToken ( ctx context . Context , accessToken string ) ( int64 , error ) {
2022-10-06 12:35:19 -08:00
var orgId int64
2022-10-19 09:02:15 -04:00
err := d . sqlStore . WithDbSession ( ctx , func ( dbSession * db . Session ) error {
2023-03-03 10:12:29 -03:00
sql := "SELECT org_id FROM dashboard_public WHERE access_token=?"
2022-10-06 12:35:19 -08:00
_ , err := dbSession . SQL ( sql , accessToken ) . Get ( & orgId )
if err != nil {
return err
}
return err
} )
return orgId , err
}
2022-11-03 11:30:12 -08:00
// Creates a public dashboard
func ( d * PublicDashboardStoreImpl ) Create ( ctx context . Context , cmd SavePublicDashboardCommand ) ( int64 , error ) {
if cmd . PublicDashboard . DashboardUid == "" {
return 0 , dashboards . ErrDashboardIdentifierNotSet
}
var affectedRows int64
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
var err error
affectedRows , err = sess . UseBool ( "is_enabled" ) . Insert ( & cmd . PublicDashboard )
return err
} )
return affectedRows , err
}
// Updates existing public dashboard
func ( d * PublicDashboardStoreImpl ) Update ( ctx context . Context , cmd SavePublicDashboardCommand ) ( int64 , error ) {
var affectedRows int64
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
timeSettingsJSON , err := json . Marshal ( cmd . PublicDashboard . TimeSettings )
if err != nil {
return err
}
2023-02-09 15:44:09 -03:00
sqlResult , err := sess . Exec ( "UPDATE dashboard_public SET is_enabled = ?, annotations_enabled = ?, time_selection_enabled = ?, share = ?, time_settings = ?, updated_by = ?, updated_at = ? WHERE uid = ?" ,
2022-11-03 11:30:12 -08:00
cmd . PublicDashboard . IsEnabled ,
cmd . PublicDashboard . AnnotationsEnabled ,
2022-12-01 11:37:08 -03:00
cmd . PublicDashboard . TimeSelectionEnabled ,
2023-02-09 15:44:09 -03:00
cmd . PublicDashboard . Share ,
2022-11-03 11:30:12 -08:00
string ( timeSettingsJSON ) ,
cmd . PublicDashboard . UpdatedBy ,
cmd . PublicDashboard . UpdatedAt . UTC ( ) . Format ( "2006-01-02 15:04:05" ) ,
cmd . PublicDashboard . Uid )
if err != nil {
return err
}
affectedRows , err = sqlResult . RowsAffected ( )
return err
} )
return affectedRows , err
}
// Deletes a public dashboard
2023-03-08 14:54:35 -06:00
func ( d * PublicDashboardStoreImpl ) Delete ( ctx context . Context , uid string ) ( int64 , error ) {
dashboard := & PublicDashboard { Uid : uid }
2022-11-03 11:30:12 -08:00
var affectedRows int64
err := d . sqlStore . WithDbSession ( ctx , func ( sess * db . Session ) error {
var err error
affectedRows , err = sess . Delete ( dashboard )
return err
} )
return affectedRows , err
}
2023-03-08 14:54:35 -06:00
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
}