2014-08-08 18:35:15 +08:00
|
|
|
package models
|
|
|
|
|
|
|
|
import (
|
2014-11-20 19:11:07 +08:00
|
|
|
"errors"
|
2018-01-30 22:24:14 +08:00
|
|
|
"fmt"
|
2014-08-22 21:32:42 +08:00
|
|
|
"strings"
|
2014-08-22 04:09:48 +08:00
|
|
|
"time"
|
2015-04-15 18:36:02 +08:00
|
|
|
|
2015-06-12 14:53:20 +08:00
|
|
|
"github.com/gosimple/slug"
|
2016-03-12 07:13:06 +08:00
|
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
2018-01-30 22:24:14 +08:00
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
2014-08-08 18:35:15 +08:00
|
|
|
)
|
|
|
|
|
2014-11-20 19:11:07 +08:00
|
|
|
// Typed errors
|
|
|
|
var (
|
2018-03-27 21:12:47 +08:00
|
|
|
ErrDashboardNotFound = errors.New("Dashboard not found")
|
|
|
|
ErrDashboardFolderNotFound = errors.New("Folder not found")
|
|
|
|
ErrDashboardSnapshotNotFound = errors.New("Dashboard snapshot not found")
|
|
|
|
ErrDashboardWithSameUIDExists = errors.New("A dashboard with the same uid already exists")
|
|
|
|
ErrDashboardWithSameNameInFolderExists = errors.New("A dashboard with the same name in the folder already exists")
|
|
|
|
ErrDashboardVersionMismatch = errors.New("The dashboard has been changed by someone else")
|
|
|
|
ErrDashboardTitleEmpty = errors.New("Dashboard title cannot be empty")
|
|
|
|
ErrDashboardFolderCannotHaveParent = errors.New("A Dashboard Folder cannot be added to another folder")
|
|
|
|
ErrDashboardContainsInvalidAlertData = errors.New("Invalid alert data. Cannot save dashboard")
|
|
|
|
ErrDashboardFailedToUpdateAlertData = errors.New("Failed to save alert data")
|
|
|
|
ErrDashboardsWithSameSlugExists = errors.New("Multiple dashboards with the same slug exists")
|
|
|
|
ErrDashboardFailedGenerateUniqueUid = errors.New("Failed to generate unique dashboard id")
|
|
|
|
ErrDashboardTypeMismatch = errors.New("Dashboard cannot be changed to a folder")
|
|
|
|
ErrDashboardFolderWithSameNameAsDashboard = errors.New("Folder name cannot be the same as one of its dashboards")
|
|
|
|
ErrDashboardWithSameNameAsFolder = errors.New("Dashboard name cannot be the same as folder")
|
|
|
|
ErrDashboardFolderNameExists = errors.New("A folder with that name already exists")
|
|
|
|
ErrDashboardUpdateAccessDenied = errors.New("Access denied to save dashboard")
|
|
|
|
ErrDashboardInvalidUid = errors.New("uid contains illegal characters")
|
|
|
|
ErrDashboardUidToLong = errors.New("uid to long. max 40 characters")
|
2018-04-10 15:32:05 +08:00
|
|
|
ErrDashboardCannotSaveProvisionedDashboard = errors.New("Cannot save provisioned dashboard")
|
2018-04-13 23:11:52 +08:00
|
|
|
RootFolderName = "General"
|
2014-10-07 03:31:54 +08:00
|
|
|
)
|
|
|
|
|
2016-07-08 19:41:46 +08:00
|
|
|
type UpdatePluginDashboardError struct {
|
|
|
|
PluginId string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d UpdatePluginDashboardError) Error() string {
|
|
|
|
return "Dashboard belong to plugin"
|
|
|
|
}
|
|
|
|
|
2015-05-12 20:11:30 +08:00
|
|
|
var (
|
2015-05-13 15:58:45 +08:00
|
|
|
DashTypeJson = "file"
|
|
|
|
DashTypeDB = "db"
|
|
|
|
DashTypeScript = "script"
|
|
|
|
DashTypeSnapshot = "snapshot"
|
2015-05-12 20:11:30 +08:00
|
|
|
)
|
|
|
|
|
2015-03-19 22:32:47 +08:00
|
|
|
// Dashboard model
|
2014-08-08 18:35:15 +08:00
|
|
|
type Dashboard struct {
|
2016-07-08 15:35:06 +08:00
|
|
|
Id int64
|
2018-01-30 00:20:18 +08:00
|
|
|
Uid string
|
2016-07-08 15:35:06 +08:00
|
|
|
Slug string
|
|
|
|
OrgId int64
|
|
|
|
GnetId int64
|
|
|
|
Version int
|
|
|
|
PluginId string
|
2014-11-20 19:11:07 +08:00
|
|
|
|
2015-01-07 19:37:24 +08:00
|
|
|
Created time.Time
|
|
|
|
Updated time.Time
|
2014-08-22 04:09:48 +08:00
|
|
|
|
2015-12-18 17:52:05 +08:00
|
|
|
UpdatedBy int64
|
2016-01-28 14:00:24 +08:00
|
|
|
CreatedBy int64
|
2017-06-24 04:00:26 +08:00
|
|
|
FolderId int64
|
2017-03-27 20:36:28 +08:00
|
|
|
IsFolder bool
|
2017-04-29 03:22:53 +08:00
|
|
|
HasAcl bool
|
2015-12-18 16:20:23 +08:00
|
|
|
|
2014-08-22 04:09:48 +08:00
|
|
|
Title string
|
2016-03-12 07:13:06 +08:00
|
|
|
Data *simplejson.Json
|
2014-08-22 04:09:48 +08:00
|
|
|
}
|
|
|
|
|
2018-01-25 22:25:07 +08:00
|
|
|
func (d *Dashboard) SetId(id int64) {
|
|
|
|
d.Id = id
|
|
|
|
d.Data.Set("id", id)
|
|
|
|
}
|
|
|
|
|
2018-02-19 18:12:56 +08:00
|
|
|
func (d *Dashboard) SetUid(uid string) {
|
|
|
|
d.Uid = uid
|
|
|
|
d.Data.Set("uid", uid)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Dashboard) SetVersion(version int) {
|
|
|
|
d.Version = version
|
|
|
|
d.Data.Set("version", version)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetDashboardIdForSavePermissionCheck return the dashboard id to be used for checking permission of dashboard
|
|
|
|
func (d *Dashboard) GetDashboardIdForSavePermissionCheck() int64 {
|
|
|
|
if d.Id == 0 {
|
|
|
|
return d.FolderId
|
|
|
|
}
|
|
|
|
|
|
|
|
return d.Id
|
|
|
|
}
|
|
|
|
|
2015-03-19 22:32:47 +08:00
|
|
|
// NewDashboard creates a new dashboard
|
2014-08-08 18:35:15 +08:00
|
|
|
func NewDashboard(title string) *Dashboard {
|
|
|
|
dash := &Dashboard{}
|
2016-03-12 07:13:06 +08:00
|
|
|
dash.Data = simplejson.New()
|
|
|
|
dash.Data.Set("title", title)
|
2014-08-22 21:32:42 +08:00
|
|
|
dash.Title = title
|
2015-11-20 20:37:24 +08:00
|
|
|
dash.Created = time.Now()
|
2015-11-20 20:52:50 +08:00
|
|
|
dash.Updated = time.Now()
|
|
|
|
dash.UpdateSlug()
|
2014-08-08 18:35:15 +08:00
|
|
|
return dash
|
|
|
|
}
|
|
|
|
|
2017-11-28 19:49:37 +08:00
|
|
|
// NewDashboardFolder creates a new dashboard folder
|
|
|
|
func NewDashboardFolder(title string) *Dashboard {
|
|
|
|
folder := NewDashboard(title)
|
2018-01-29 20:51:01 +08:00
|
|
|
folder.IsFolder = true
|
2017-11-28 19:49:37 +08:00
|
|
|
folder.Data.Set("schemaVersion", 16)
|
2018-01-29 20:51:01 +08:00
|
|
|
folder.Data.Set("version", 0)
|
2018-02-19 18:12:56 +08:00
|
|
|
folder.IsFolder = true
|
2017-11-28 19:49:37 +08:00
|
|
|
return folder
|
|
|
|
}
|
|
|
|
|
2015-03-19 22:32:47 +08:00
|
|
|
// GetTags turns the tags in data json into go string array
|
2015-01-07 19:37:24 +08:00
|
|
|
func (dash *Dashboard) GetTags() []string {
|
2016-03-12 07:13:06 +08:00
|
|
|
return dash.Data.Get("tags").MustStringArray()
|
2015-01-07 19:37:24 +08:00
|
|
|
}
|
|
|
|
|
2016-03-12 07:13:06 +08:00
|
|
|
func NewDashboardFromJson(data *simplejson.Json) *Dashboard {
|
2014-12-22 19:25:08 +08:00
|
|
|
dash := &Dashboard{}
|
2015-05-12 18:20:03 +08:00
|
|
|
dash.Data = data
|
2016-03-12 07:13:06 +08:00
|
|
|
dash.Title = dash.Data.Get("title").MustString()
|
2015-11-20 20:52:50 +08:00
|
|
|
dash.UpdateSlug()
|
2018-02-08 19:48:38 +08:00
|
|
|
update := false
|
2014-08-08 18:35:15 +08:00
|
|
|
|
2016-03-12 07:13:06 +08:00
|
|
|
if id, err := dash.Data.Get("id").Float64(); err == nil {
|
|
|
|
dash.Id = int64(id)
|
2018-02-08 19:48:38 +08:00
|
|
|
update = true
|
|
|
|
}
|
2015-03-03 05:24:01 +08:00
|
|
|
|
2018-02-08 19:48:38 +08:00
|
|
|
if uid, err := dash.Data.Get("uid").String(); err == nil {
|
|
|
|
dash.Uid = uid
|
|
|
|
update = true
|
|
|
|
}
|
2015-03-03 05:24:01 +08:00
|
|
|
|
2018-02-08 19:48:38 +08:00
|
|
|
if version, err := dash.Data.Get("version").Float64(); err == nil && update {
|
|
|
|
dash.Version = int(version)
|
|
|
|
dash.Updated = time.Now()
|
2015-03-19 22:32:47 +08:00
|
|
|
} else {
|
2016-03-12 07:13:06 +08:00
|
|
|
dash.Data.Set("version", 0)
|
2015-11-20 20:52:50 +08:00
|
|
|
dash.Created = time.Now()
|
|
|
|
dash.Updated = time.Now()
|
2014-08-08 18:35:15 +08:00
|
|
|
}
|
|
|
|
|
2016-05-27 22:42:32 +08:00
|
|
|
if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil {
|
|
|
|
dash.GnetId = int64(gnetId)
|
|
|
|
}
|
|
|
|
|
2014-12-22 19:25:08 +08:00
|
|
|
return dash
|
2014-08-08 18:35:15 +08:00
|
|
|
}
|
|
|
|
|
2018-04-14 00:40:14 +08:00
|
|
|
// GetDashboardModel turns the command into the saveable model
|
2015-05-12 18:20:03 +08:00
|
|
|
func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard {
|
|
|
|
dash := NewDashboardFromJson(cmd.Dashboard)
|
2017-06-05 22:34:32 +08:00
|
|
|
userId := cmd.UserId
|
|
|
|
|
|
|
|
if userId == 0 {
|
|
|
|
userId = -1
|
|
|
|
}
|
2016-03-12 07:13:06 +08:00
|
|
|
|
2017-06-05 22:34:32 +08:00
|
|
|
dash.UpdatedBy = userId
|
2016-01-28 14:00:24 +08:00
|
|
|
dash.OrgId = cmd.OrgId
|
2016-07-08 18:26:51 +08:00
|
|
|
dash.PluginId = cmd.PluginId
|
2017-03-27 20:36:28 +08:00
|
|
|
dash.IsFolder = cmd.IsFolder
|
2017-06-24 04:00:26 +08:00
|
|
|
dash.FolderId = cmd.FolderId
|
2015-05-12 18:20:03 +08:00
|
|
|
dash.UpdateSlug()
|
|
|
|
return dash
|
|
|
|
}
|
|
|
|
|
2015-03-19 22:32:47 +08:00
|
|
|
// GetString a
|
2016-03-11 02:57:48 +08:00
|
|
|
func (dash *Dashboard) GetString(prop string, defaultValue string) string {
|
2016-03-12 07:13:06 +08:00
|
|
|
return dash.Data.Get(prop).MustString(defaultValue)
|
2014-08-08 18:35:15 +08:00
|
|
|
}
|
2014-08-22 21:32:42 +08:00
|
|
|
|
2015-03-19 22:32:47 +08:00
|
|
|
// UpdateSlug updates the slug
|
2014-08-22 21:32:42 +08:00
|
|
|
func (dash *Dashboard) UpdateSlug() {
|
2017-12-27 23:32:39 +08:00
|
|
|
title := dash.Data.Get("title").MustString()
|
|
|
|
dash.Slug = SlugifyTitle(title)
|
|
|
|
}
|
|
|
|
|
|
|
|
func SlugifyTitle(title string) string {
|
|
|
|
return slug.Make(strings.ToLower(title))
|
2014-08-22 21:32:42 +08:00
|
|
|
}
|
2015-01-09 18:01:37 +08:00
|
|
|
|
2018-02-01 06:14:48 +08:00
|
|
|
// GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
|
|
|
|
func (dash *Dashboard) GetUrl() string {
|
|
|
|
return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
|
|
|
|
}
|
|
|
|
|
2018-02-01 20:49:34 +08:00
|
|
|
// Return the html url for a dashboard
|
|
|
|
func (dash *Dashboard) GenerateUrl() string {
|
|
|
|
return GetDashboardUrl(dash.Uid, dash.Slug)
|
|
|
|
}
|
|
|
|
|
2018-02-01 06:14:48 +08:00
|
|
|
// GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
|
|
|
|
func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
|
|
|
|
if isFolder {
|
|
|
|
return GetFolderUrl(uid, slug)
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetDashboardUrl(uid, slug)
|
|
|
|
}
|
|
|
|
|
2018-03-28 02:24:11 +08:00
|
|
|
// GetDashboardUrl return the html url for a dashboard
|
2018-01-30 22:24:14 +08:00
|
|
|
func GetDashboardUrl(uid string, slug string) string {
|
|
|
|
return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
|
|
|
|
}
|
|
|
|
|
2018-03-28 02:24:11 +08:00
|
|
|
// GetFullDashboardUrl return the full url for a dashboard
|
2018-02-01 20:32:00 +08:00
|
|
|
func GetFullDashboardUrl(uid string, slug string) string {
|
2018-03-28 02:24:11 +08:00
|
|
|
return fmt.Sprintf("%sd/%s/%s", setting.AppUrl, uid, slug)
|
2018-02-01 20:32:00 +08:00
|
|
|
}
|
|
|
|
|
2018-01-30 22:24:14 +08:00
|
|
|
// GetFolderUrl return the html url for a folder
|
|
|
|
func GetFolderUrl(folderUid string, slug string) string {
|
2018-01-31 23:51:06 +08:00
|
|
|
return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
|
2018-01-30 22:24:14 +08:00
|
|
|
}
|
|
|
|
|
2018-04-11 06:23:50 +08:00
|
|
|
type ValidateDashboardBeforeSaveResult struct {
|
|
|
|
IsParentFolderChanged bool
|
|
|
|
}
|
|
|
|
|
2015-01-09 18:01:37 +08:00
|
|
|
//
|
|
|
|
// COMMANDS
|
|
|
|
//
|
|
|
|
|
|
|
|
type SaveDashboardCommand struct {
|
2017-06-06 04:59:04 +08:00
|
|
|
Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
|
|
|
|
UserId int64 `json:"userId"`
|
|
|
|
Overwrite bool `json:"overwrite"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
OrgId int64 `json:"-"`
|
|
|
|
RestoredFrom int `json:"-"`
|
|
|
|
PluginId string `json:"-"`
|
2017-06-24 04:00:26 +08:00
|
|
|
FolderId int64 `json:"folderId"`
|
2017-06-10 05:19:58 +08:00
|
|
|
IsFolder bool `json:"isFolder"`
|
2015-01-09 18:01:37 +08:00
|
|
|
|
2017-11-23 18:29:06 +08:00
|
|
|
UpdatedAt time.Time
|
|
|
|
|
2015-01-09 18:01:37 +08:00
|
|
|
Result *Dashboard
|
|
|
|
}
|
|
|
|
|
2018-01-23 19:28:56 +08:00
|
|
|
type DashboardProvisioning struct {
|
|
|
|
Id int64
|
|
|
|
DashboardId int64
|
|
|
|
Name string
|
|
|
|
ExternalId string
|
2018-05-31 20:13:34 +08:00
|
|
|
CheckSum string
|
2018-02-14 22:28:30 +08:00
|
|
|
Updated int64
|
2018-01-23 19:28:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type SaveProvisionedDashboardCommand struct {
|
|
|
|
DashboardCmd *SaveDashboardCommand
|
|
|
|
DashboardProvisioning *DashboardProvisioning
|
|
|
|
|
|
|
|
Result *Dashboard
|
|
|
|
}
|
|
|
|
|
2015-01-09 18:01:37 +08:00
|
|
|
type DeleteDashboardCommand struct {
|
2017-06-18 06:24:38 +08:00
|
|
|
Id int64
|
2015-02-24 03:07:49 +08:00
|
|
|
OrgId int64
|
2015-01-09 18:01:37 +08:00
|
|
|
}
|
|
|
|
|
2018-02-19 18:12:56 +08:00
|
|
|
type ValidateDashboardBeforeSaveCommand struct {
|
|
|
|
OrgId int64
|
|
|
|
Dashboard *Dashboard
|
|
|
|
Overwrite bool
|
2018-04-11 06:23:50 +08:00
|
|
|
Result *ValidateDashboardBeforeSaveResult
|
2018-02-19 18:12:56 +08:00
|
|
|
}
|
|
|
|
|
2015-01-09 18:01:37 +08:00
|
|
|
//
|
|
|
|
// QUERIES
|
|
|
|
//
|
|
|
|
|
|
|
|
type GetDashboardQuery struct {
|
2018-01-30 04:23:07 +08:00
|
|
|
Slug string // required if no Id or Uid is specified
|
2017-06-05 23:45:27 +08:00
|
|
|
Id int64 // optional if slug is set
|
2018-01-30 04:23:07 +08:00
|
|
|
Uid string // optional if slug is set
|
2015-02-24 03:07:49 +08:00
|
|
|
OrgId int64
|
2015-01-09 18:01:37 +08:00
|
|
|
|
|
|
|
Result *Dashboard
|
|
|
|
}
|
2015-05-13 19:36:13 +08:00
|
|
|
|
|
|
|
type DashboardTagCloudItem struct {
|
|
|
|
Term string `json:"term"`
|
|
|
|
Count int `json:"count"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type GetDashboardTagsQuery struct {
|
|
|
|
OrgId int64
|
|
|
|
Result []*DashboardTagCloudItem
|
|
|
|
}
|
2016-01-29 08:41:23 +08:00
|
|
|
|
|
|
|
type GetDashboardsQuery struct {
|
|
|
|
DashboardIds []int64
|
2016-07-08 15:35:06 +08:00
|
|
|
Result []*Dashboard
|
|
|
|
}
|
|
|
|
|
2018-01-31 06:31:02 +08:00
|
|
|
type GetDashboardPermissionsForUserQuery struct {
|
|
|
|
DashboardIds []int64
|
|
|
|
OrgId int64
|
|
|
|
UserId int64
|
|
|
|
OrgRole RoleType
|
|
|
|
Result []*DashboardPermissionForUser
|
|
|
|
}
|
|
|
|
|
2016-07-08 15:35:06 +08:00
|
|
|
type GetDashboardsByPluginIdQuery struct {
|
|
|
|
OrgId int64
|
|
|
|
PluginId string
|
|
|
|
Result []*Dashboard
|
2016-01-29 08:41:23 +08:00
|
|
|
}
|
2016-03-17 16:01:58 +08:00
|
|
|
|
|
|
|
type GetDashboardSlugByIdQuery struct {
|
|
|
|
Id int64
|
|
|
|
Result string
|
|
|
|
}
|
2018-01-31 23:51:06 +08:00
|
|
|
|
2018-04-10 18:30:37 +08:00
|
|
|
type IsDashboardProvisionedQuery struct {
|
2018-02-28 01:51:04 +08:00
|
|
|
DashboardId int64
|
|
|
|
|
2018-04-10 18:30:37 +08:00
|
|
|
Result bool
|
2018-02-28 01:51:04 +08:00
|
|
|
}
|
|
|
|
|
2018-01-23 19:28:56 +08:00
|
|
|
type GetProvisionedDashboardDataQuery struct {
|
|
|
|
Name string
|
|
|
|
|
|
|
|
Result []*DashboardProvisioning
|
|
|
|
}
|
2018-02-08 18:01:09 +08:00
|
|
|
|
2018-01-31 23:51:06 +08:00
|
|
|
type GetDashboardsBySlugQuery struct {
|
|
|
|
OrgId int64
|
|
|
|
Slug string
|
|
|
|
|
|
|
|
Result []*Dashboard
|
|
|
|
}
|
2018-02-01 18:08:39 +08:00
|
|
|
|
2018-01-31 06:31:02 +08:00
|
|
|
type DashboardPermissionForUser struct {
|
|
|
|
DashboardId int64 `json:"dashboardId"`
|
|
|
|
Permission PermissionType `json:"permission"`
|
|
|
|
PermissionName string `json:"permissionName"`
|
|
|
|
}
|
2018-02-01 20:32:00 +08:00
|
|
|
|
|
|
|
type DashboardRef struct {
|
|
|
|
Uid string
|
|
|
|
Slug string
|
|
|
|
}
|
|
|
|
|
2018-02-05 17:24:48 +08:00
|
|
|
type GetDashboardRefByIdQuery struct {
|
2018-02-01 20:32:00 +08:00
|
|
|
Id int64
|
|
|
|
Result *DashboardRef
|
|
|
|
}
|