dashboards.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. package models
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "github.com/gosimple/slug"
  8. "github.com/grafana/grafana/pkg/components/simplejson"
  9. "github.com/grafana/grafana/pkg/setting"
  10. )
  11. // Typed errors
  12. var (
  13. ErrDashboardNotFound = errors.New("Dashboard not found")
  14. ErrDashboardFolderNotFound = errors.New("Folder not found")
  15. ErrDashboardSnapshotNotFound = errors.New("Dashboard snapshot not found")
  16. ErrDashboardWithSameUIDExists = errors.New("A dashboard with the same uid already exists")
  17. ErrDashboardWithSameNameInFolderExists = errors.New("A dashboard with the same name in the folder already exists")
  18. ErrDashboardVersionMismatch = errors.New("The dashboard has been changed by someone else")
  19. ErrDashboardTitleEmpty = errors.New("Dashboard title cannot be empty")
  20. ErrDashboardFolderCannotHaveParent = errors.New("A Dashboard Folder cannot be added to another folder")
  21. ErrDashboardContainsInvalidAlertData = errors.New("Invalid alert data. Cannot save dashboard")
  22. ErrDashboardFailedToUpdateAlertData = errors.New("Failed to save alert data")
  23. ErrDashboardsWithSameSlugExists = errors.New("Multiple dashboards with the same slug exists")
  24. ErrDashboardFailedGenerateUniqueUid = errors.New("Failed to generate unique dashboard id")
  25. ErrDashboardTypeMismatch = errors.New("Dashboard cannot be changed to a folder")
  26. ErrDashboardFolderWithSameNameAsDashboard = errors.New("Folder name cannot be the same as one of its dashboards")
  27. ErrDashboardWithSameNameAsFolder = errors.New("Dashboard name cannot be the same as folder")
  28. ErrDashboardFolderNameExists = errors.New("A folder with that name already exists")
  29. ErrDashboardUpdateAccessDenied = errors.New("Access denied to save dashboard")
  30. ErrDashboardInvalidUid = errors.New("uid contains illegal characters")
  31. ErrDashboardUidToLong = errors.New("uid to long. max 40 characters")
  32. ErrDashboardCannotSaveProvisionedDashboard = errors.New("Cannot save provisioned dashboard")
  33. //ErrDashboardProvisioningDoesNotExist = errors.New("Dashboard provisioning does not exist")
  34. RootFolderName = "General"
  35. )
  36. type UpdatePluginDashboardError struct {
  37. PluginId string
  38. }
  39. func (d UpdatePluginDashboardError) Error() string {
  40. return "Dashboard belong to plugin"
  41. }
  42. var (
  43. DashTypeJson = "file"
  44. DashTypeDB = "db"
  45. DashTypeScript = "script"
  46. DashTypeSnapshot = "snapshot"
  47. )
  48. // Dashboard model
  49. type Dashboard struct {
  50. Id int64
  51. Uid string
  52. Slug string
  53. OrgId int64
  54. GnetId int64
  55. Version int
  56. PluginId string
  57. Created time.Time
  58. Updated time.Time
  59. UpdatedBy int64
  60. CreatedBy int64
  61. FolderId int64
  62. IsFolder bool
  63. HasAcl bool
  64. Title string
  65. Data *simplejson.Json
  66. }
  67. func (d *Dashboard) SetId(id int64) {
  68. d.Id = id
  69. d.Data.Set("id", id)
  70. }
  71. func (d *Dashboard) SetUid(uid string) {
  72. d.Uid = uid
  73. d.Data.Set("uid", uid)
  74. }
  75. func (d *Dashboard) SetVersion(version int) {
  76. d.Version = version
  77. d.Data.Set("version", version)
  78. }
  79. // GetDashboardIdForSavePermissionCheck return the dashboard id to be used for checking permission of dashboard
  80. func (d *Dashboard) GetDashboardIdForSavePermissionCheck() int64 {
  81. if d.Id == 0 {
  82. return d.FolderId
  83. }
  84. return d.Id
  85. }
  86. // NewDashboard creates a new dashboard
  87. func NewDashboard(title string) *Dashboard {
  88. dash := &Dashboard{}
  89. dash.Data = simplejson.New()
  90. dash.Data.Set("title", title)
  91. dash.Title = title
  92. dash.Created = time.Now()
  93. dash.Updated = time.Now()
  94. dash.UpdateSlug()
  95. return dash
  96. }
  97. // NewDashboardFolder creates a new dashboard folder
  98. func NewDashboardFolder(title string) *Dashboard {
  99. folder := NewDashboard(title)
  100. folder.IsFolder = true
  101. folder.Data.Set("schemaVersion", 16)
  102. folder.Data.Set("version", 0)
  103. folder.IsFolder = true
  104. return folder
  105. }
  106. // GetTags turns the tags in data json into go string array
  107. func (dash *Dashboard) GetTags() []string {
  108. return dash.Data.Get("tags").MustStringArray()
  109. }
  110. func NewDashboardFromJson(data *simplejson.Json) *Dashboard {
  111. dash := &Dashboard{}
  112. dash.Data = data
  113. dash.Title = dash.Data.Get("title").MustString()
  114. dash.UpdateSlug()
  115. update := false
  116. if id, err := dash.Data.Get("id").Float64(); err == nil {
  117. dash.Id = int64(id)
  118. update = true
  119. }
  120. if uid, err := dash.Data.Get("uid").String(); err == nil {
  121. dash.Uid = uid
  122. update = true
  123. }
  124. if version, err := dash.Data.Get("version").Float64(); err == nil && update {
  125. dash.Version = int(version)
  126. dash.Updated = time.Now()
  127. } else {
  128. dash.Data.Set("version", 0)
  129. dash.Created = time.Now()
  130. dash.Updated = time.Now()
  131. }
  132. if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil {
  133. dash.GnetId = int64(gnetId)
  134. }
  135. return dash
  136. }
  137. // GetDashboardModel turns the command into the savable model
  138. func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard {
  139. dash := NewDashboardFromJson(cmd.Dashboard)
  140. userId := cmd.UserId
  141. if userId == 0 {
  142. userId = -1
  143. }
  144. dash.UpdatedBy = userId
  145. dash.OrgId = cmd.OrgId
  146. dash.PluginId = cmd.PluginId
  147. dash.IsFolder = cmd.IsFolder
  148. dash.FolderId = cmd.FolderId
  149. dash.UpdateSlug()
  150. return dash
  151. }
  152. // GetString a
  153. func (dash *Dashboard) GetString(prop string, defaultValue string) string {
  154. return dash.Data.Get(prop).MustString(defaultValue)
  155. }
  156. // UpdateSlug updates the slug
  157. func (dash *Dashboard) UpdateSlug() {
  158. title := dash.Data.Get("title").MustString()
  159. dash.Slug = SlugifyTitle(title)
  160. }
  161. func SlugifyTitle(title string) string {
  162. return slug.Make(strings.ToLower(title))
  163. }
  164. // GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
  165. func (dash *Dashboard) GetUrl() string {
  166. return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
  167. }
  168. // Return the html url for a dashboard
  169. func (dash *Dashboard) GenerateUrl() string {
  170. return GetDashboardUrl(dash.Uid, dash.Slug)
  171. }
  172. // GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
  173. func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
  174. if isFolder {
  175. return GetFolderUrl(uid, slug)
  176. }
  177. return GetDashboardUrl(uid, slug)
  178. }
  179. // GetDashboardUrl return the html url for a dashboard
  180. func GetDashboardUrl(uid string, slug string) string {
  181. return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
  182. }
  183. // GetFullDashboardUrl return the full url for a dashboard
  184. func GetFullDashboardUrl(uid string, slug string) string {
  185. return fmt.Sprintf("%sd/%s/%s", setting.AppUrl, uid, slug)
  186. }
  187. // GetFolderUrl return the html url for a folder
  188. func GetFolderUrl(folderUid string, slug string) string {
  189. return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
  190. }
  191. //
  192. // COMMANDS
  193. //
  194. type SaveDashboardCommand struct {
  195. Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
  196. UserId int64 `json:"userId"`
  197. Overwrite bool `json:"overwrite"`
  198. Message string `json:"message"`
  199. OrgId int64 `json:"-"`
  200. RestoredFrom int `json:"-"`
  201. PluginId string `json:"-"`
  202. FolderId int64 `json:"folderId"`
  203. IsFolder bool `json:"isFolder"`
  204. UpdatedAt time.Time
  205. Result *Dashboard
  206. }
  207. type DashboardProvisioning struct {
  208. Id int64
  209. DashboardId int64
  210. Name string
  211. ExternalId string
  212. Updated int64
  213. }
  214. type SaveProvisionedDashboardCommand struct {
  215. DashboardCmd *SaveDashboardCommand
  216. DashboardProvisioning *DashboardProvisioning
  217. Result *Dashboard
  218. }
  219. type DeleteDashboardCommand struct {
  220. Id int64
  221. OrgId int64
  222. }
  223. type ValidateDashboardBeforeSaveCommand struct {
  224. OrgId int64
  225. Dashboard *Dashboard
  226. Overwrite bool
  227. }
  228. //
  229. // QUERIES
  230. //
  231. type GetDashboardQuery struct {
  232. Slug string // required if no Id or Uid is specified
  233. Id int64 // optional if slug is set
  234. Uid string // optional if slug is set
  235. OrgId int64
  236. Result *Dashboard
  237. }
  238. type DashboardTagCloudItem struct {
  239. Term string `json:"term"`
  240. Count int `json:"count"`
  241. }
  242. type GetDashboardTagsQuery struct {
  243. OrgId int64
  244. Result []*DashboardTagCloudItem
  245. }
  246. type GetDashboardsQuery struct {
  247. DashboardIds []int64
  248. Result []*Dashboard
  249. }
  250. type GetDashboardPermissionsForUserQuery struct {
  251. DashboardIds []int64
  252. OrgId int64
  253. UserId int64
  254. OrgRole RoleType
  255. Result []*DashboardPermissionForUser
  256. }
  257. type GetDashboardsByPluginIdQuery struct {
  258. OrgId int64
  259. PluginId string
  260. Result []*Dashboard
  261. }
  262. type GetDashboardSlugByIdQuery struct {
  263. Id int64
  264. Result string
  265. }
  266. type IsDashboardProvisionedQuery struct {
  267. DashboardId int64
  268. Result bool
  269. }
  270. type GetProvisionedDashboardDataQuery struct {
  271. Name string
  272. Result []*DashboardProvisioning
  273. }
  274. type GetDashboardsBySlugQuery struct {
  275. OrgId int64
  276. Slug string
  277. Result []*Dashboard
  278. }
  279. type DashboardPermissionForUser struct {
  280. DashboardId int64 `json:"dashboardId"`
  281. Permission PermissionType `json:"permission"`
  282. PermissionName string `json:"permissionName"`
  283. }
  284. type DashboardRef struct {
  285. Uid string
  286. Slug string
  287. }
  288. type GetDashboardRefByIdQuery struct {
  289. Id int64
  290. Result *DashboardRef
  291. }