dashboards.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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. RootFolderName = "General"
  34. )
  35. type UpdatePluginDashboardError struct {
  36. PluginId string
  37. }
  38. func (d UpdatePluginDashboardError) Error() string {
  39. return "Dashboard belong to plugin"
  40. }
  41. var (
  42. DashTypeJson = "file"
  43. DashTypeDB = "db"
  44. DashTypeScript = "script"
  45. DashTypeSnapshot = "snapshot"
  46. )
  47. // Dashboard model
  48. type Dashboard struct {
  49. Id int64
  50. Uid string
  51. Slug string
  52. OrgId int64
  53. GnetId int64
  54. Version int
  55. PluginId string
  56. Created time.Time
  57. Updated time.Time
  58. UpdatedBy int64
  59. CreatedBy int64
  60. FolderId int64
  61. IsFolder bool
  62. HasAcl bool
  63. Title string
  64. Data *simplejson.Json
  65. }
  66. func (d *Dashboard) SetId(id int64) {
  67. d.Id = id
  68. d.Data.Set("id", id)
  69. }
  70. func (d *Dashboard) SetUid(uid string) {
  71. d.Uid = uid
  72. d.Data.Set("uid", uid)
  73. }
  74. func (d *Dashboard) SetVersion(version int) {
  75. d.Version = version
  76. d.Data.Set("version", version)
  77. }
  78. // GetDashboardIdForSavePermissionCheck return the dashboard id to be used for checking permission of dashboard
  79. func (d *Dashboard) GetDashboardIdForSavePermissionCheck() int64 {
  80. if d.Id == 0 {
  81. return d.FolderId
  82. }
  83. return d.Id
  84. }
  85. // NewDashboard creates a new dashboard
  86. func NewDashboard(title string) *Dashboard {
  87. dash := &Dashboard{}
  88. dash.Data = simplejson.New()
  89. dash.Data.Set("title", title)
  90. dash.Title = title
  91. dash.Created = time.Now()
  92. dash.Updated = time.Now()
  93. dash.UpdateSlug()
  94. return dash
  95. }
  96. // NewDashboardFolder creates a new dashboard folder
  97. func NewDashboardFolder(title string) *Dashboard {
  98. folder := NewDashboard(title)
  99. folder.IsFolder = true
  100. folder.Data.Set("schemaVersion", 16)
  101. folder.Data.Set("version", 0)
  102. folder.IsFolder = true
  103. return folder
  104. }
  105. // GetTags turns the tags in data json into go string array
  106. func (dash *Dashboard) GetTags() []string {
  107. return dash.Data.Get("tags").MustStringArray()
  108. }
  109. func NewDashboardFromJson(data *simplejson.Json) *Dashboard {
  110. dash := &Dashboard{}
  111. dash.Data = data
  112. dash.Title = dash.Data.Get("title").MustString()
  113. dash.UpdateSlug()
  114. update := false
  115. if id, err := dash.Data.Get("id").Float64(); err == nil {
  116. dash.Id = int64(id)
  117. update = true
  118. }
  119. if uid, err := dash.Data.Get("uid").String(); err == nil {
  120. dash.Uid = uid
  121. update = true
  122. }
  123. if version, err := dash.Data.Get("version").Float64(); err == nil && update {
  124. dash.Version = int(version)
  125. dash.Updated = time.Now()
  126. } else {
  127. dash.Data.Set("version", 0)
  128. dash.Created = time.Now()
  129. dash.Updated = time.Now()
  130. }
  131. if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil {
  132. dash.GnetId = int64(gnetId)
  133. }
  134. return dash
  135. }
  136. // GetDashboardModel turns the command into the saveable model
  137. func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard {
  138. dash := NewDashboardFromJson(cmd.Dashboard)
  139. userId := cmd.UserId
  140. if userId == 0 {
  141. userId = -1
  142. }
  143. dash.UpdatedBy = userId
  144. dash.OrgId = cmd.OrgId
  145. dash.PluginId = cmd.PluginId
  146. dash.IsFolder = cmd.IsFolder
  147. dash.FolderId = cmd.FolderId
  148. dash.UpdateSlug()
  149. return dash
  150. }
  151. // GetString a
  152. func (dash *Dashboard) GetString(prop string, defaultValue string) string {
  153. return dash.Data.Get(prop).MustString(defaultValue)
  154. }
  155. // UpdateSlug updates the slug
  156. func (dash *Dashboard) UpdateSlug() {
  157. title := dash.Data.Get("title").MustString()
  158. dash.Slug = SlugifyTitle(title)
  159. }
  160. func SlugifyTitle(title string) string {
  161. return slug.Make(strings.ToLower(title))
  162. }
  163. // GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
  164. func (dash *Dashboard) GetUrl() string {
  165. return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
  166. }
  167. // Return the html url for a dashboard
  168. func (dash *Dashboard) GenerateUrl() string {
  169. return GetDashboardUrl(dash.Uid, dash.Slug)
  170. }
  171. // GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
  172. func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
  173. if isFolder {
  174. return GetFolderUrl(uid, slug)
  175. }
  176. return GetDashboardUrl(uid, slug)
  177. }
  178. // GetDashboardUrl return the html url for a dashboard
  179. func GetDashboardUrl(uid string, slug string) string {
  180. return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
  181. }
  182. // GetFullDashboardUrl return the full url for a dashboard
  183. func GetFullDashboardUrl(uid string, slug string) string {
  184. return fmt.Sprintf("%sd/%s/%s", setting.AppUrl, uid, slug)
  185. }
  186. // GetFolderUrl return the html url for a folder
  187. func GetFolderUrl(folderUid string, slug string) string {
  188. return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
  189. }
  190. type ValidateDashboardBeforeSaveResult struct {
  191. IsParentFolderChanged bool
  192. }
  193. //
  194. // COMMANDS
  195. //
  196. type SaveDashboardCommand struct {
  197. Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
  198. UserId int64 `json:"userId"`
  199. Overwrite bool `json:"overwrite"`
  200. Message string `json:"message"`
  201. OrgId int64 `json:"-"`
  202. RestoredFrom int `json:"-"`
  203. PluginId string `json:"-"`
  204. FolderId int64 `json:"folderId"`
  205. IsFolder bool `json:"isFolder"`
  206. UpdatedAt time.Time
  207. Result *Dashboard
  208. }
  209. type DashboardProvisioning struct {
  210. Id int64
  211. DashboardId int64
  212. Name string
  213. ExternalId string
  214. Updated int64
  215. }
  216. type SaveProvisionedDashboardCommand struct {
  217. DashboardCmd *SaveDashboardCommand
  218. DashboardProvisioning *DashboardProvisioning
  219. Result *Dashboard
  220. }
  221. type DeleteDashboardCommand struct {
  222. Id int64
  223. OrgId int64
  224. }
  225. type ValidateDashboardBeforeSaveCommand struct {
  226. OrgId int64
  227. Dashboard *Dashboard
  228. Overwrite bool
  229. Result *ValidateDashboardBeforeSaveResult
  230. }
  231. //
  232. // QUERIES
  233. //
  234. type GetDashboardQuery struct {
  235. Slug string // required if no Id or Uid is specified
  236. Id int64 // optional if slug is set
  237. Uid string // optional if slug is set
  238. OrgId int64
  239. Result *Dashboard
  240. }
  241. type DashboardTagCloudItem struct {
  242. Term string `json:"term"`
  243. Count int `json:"count"`
  244. }
  245. type GetDashboardTagsQuery struct {
  246. OrgId int64
  247. Result []*DashboardTagCloudItem
  248. }
  249. type GetDashboardsQuery struct {
  250. DashboardIds []int64
  251. Result []*Dashboard
  252. }
  253. type GetDashboardPermissionsForUserQuery struct {
  254. DashboardIds []int64
  255. OrgId int64
  256. UserId int64
  257. OrgRole RoleType
  258. Result []*DashboardPermissionForUser
  259. }
  260. type GetDashboardsByPluginIdQuery struct {
  261. OrgId int64
  262. PluginId string
  263. Result []*Dashboard
  264. }
  265. type GetDashboardSlugByIdQuery struct {
  266. Id int64
  267. Result string
  268. }
  269. type IsDashboardProvisionedQuery struct {
  270. DashboardId int64
  271. Result bool
  272. }
  273. type GetProvisionedDashboardDataQuery struct {
  274. Name string
  275. Result []*DashboardProvisioning
  276. }
  277. type GetDashboardsBySlugQuery struct {
  278. OrgId int64
  279. Slug string
  280. Result []*Dashboard
  281. }
  282. type DashboardPermissionForUser struct {
  283. DashboardId int64 `json:"dashboardId"`
  284. Permission PermissionType `json:"permission"`
  285. PermissionName string `json:"permissionName"`
  286. }
  287. type DashboardRef struct {
  288. Uid string
  289. Slug string
  290. }
  291. type GetDashboardRefByIdQuery struct {
  292. Id int64
  293. Result *DashboardRef
  294. }