dashboards.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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. ErrDashboardsWithSameSlugExists = errors.New("Multiple dashboards with the same slug exists")
  22. ErrDashboardFailedGenerateUniqueUid = errors.New("Failed to generate unique dashboard id")
  23. ErrDashboardTypeMismatch = errors.New("Dashboard cannot be changed to a folder")
  24. ErrDashboardFolderWithSameNameAsDashboard = errors.New("Folder name cannot be the same as one of its dashboards")
  25. ErrDashboardWithSameNameAsFolder = errors.New("Dashboard name cannot be the same as folder")
  26. ErrDashboardFolderNameExists = errors.New("A folder with that name already exists")
  27. ErrDashboardUpdateAccessDenied = errors.New("Access denied to save dashboard")
  28. ErrDashboardInvalidUid = errors.New("uid contains illegal characters")
  29. ErrDashboardUidToLong = errors.New("uid to long. max 40 characters")
  30. ErrDashboardCannotSaveProvisionedDashboard = errors.New("Cannot save provisioned dashboard")
  31. ErrDashboardCannotDeleteProvisionedDashboard = errors.New("provisioned dashboard cannot be deleted")
  32. RootFolderName = "General"
  33. )
  34. type UpdatePluginDashboardError struct {
  35. PluginId string
  36. }
  37. func (d UpdatePluginDashboardError) Error() string {
  38. return "Dashboard belong to plugin"
  39. }
  40. var (
  41. DashTypeJson = "file"
  42. DashTypeDB = "db"
  43. DashTypeScript = "script"
  44. DashTypeSnapshot = "snapshot"
  45. )
  46. // Dashboard model
  47. type Dashboard struct {
  48. Id int64
  49. Uid string
  50. Slug string
  51. OrgId int64
  52. GnetId int64
  53. Version int
  54. PluginId string
  55. Created time.Time
  56. Updated time.Time
  57. UpdatedBy int64
  58. CreatedBy int64
  59. FolderId int64
  60. IsFolder bool
  61. HasAcl bool
  62. Title string
  63. Data *simplejson.Json
  64. }
  65. func (d *Dashboard) SetId(id int64) {
  66. d.Id = id
  67. d.Data.Set("id", id)
  68. }
  69. func (d *Dashboard) SetUid(uid string) {
  70. d.Uid = uid
  71. d.Data.Set("uid", uid)
  72. }
  73. func (d *Dashboard) SetVersion(version int) {
  74. d.Version = version
  75. d.Data.Set("version", version)
  76. }
  77. // GetDashboardIdForSavePermissionCheck return the dashboard id to be used for checking permission of dashboard
  78. func (d *Dashboard) GetDashboardIdForSavePermissionCheck() int64 {
  79. if d.Id == 0 {
  80. return d.FolderId
  81. }
  82. return d.Id
  83. }
  84. // NewDashboard creates a new dashboard
  85. func NewDashboard(title string) *Dashboard {
  86. dash := &Dashboard{}
  87. dash.Data = simplejson.New()
  88. dash.Data.Set("title", title)
  89. dash.Title = title
  90. dash.Created = time.Now()
  91. dash.Updated = time.Now()
  92. dash.UpdateSlug()
  93. return dash
  94. }
  95. // NewDashboardFolder creates a new dashboard folder
  96. func NewDashboardFolder(title string) *Dashboard {
  97. folder := NewDashboard(title)
  98. folder.IsFolder = true
  99. folder.Data.Set("schemaVersion", 17)
  100. folder.Data.Set("version", 0)
  101. folder.IsFolder = true
  102. return folder
  103. }
  104. // GetTags turns the tags in data json into go string array
  105. func (dash *Dashboard) GetTags() []string {
  106. return dash.Data.Get("tags").MustStringArray()
  107. }
  108. func NewDashboardFromJson(data *simplejson.Json) *Dashboard {
  109. dash := &Dashboard{}
  110. dash.Data = data
  111. dash.Title = dash.Data.Get("title").MustString()
  112. dash.UpdateSlug()
  113. update := false
  114. if id, err := dash.Data.Get("id").Float64(); err == nil {
  115. dash.Id = int64(id)
  116. update = true
  117. }
  118. if uid, err := dash.Data.Get("uid").String(); err == nil {
  119. dash.Uid = uid
  120. update = true
  121. }
  122. if version, err := dash.Data.Get("version").Float64(); err == nil && update {
  123. dash.Version = int(version)
  124. dash.Updated = time.Now()
  125. } else {
  126. dash.Data.Set("version", 0)
  127. dash.Created = time.Now()
  128. dash.Updated = time.Now()
  129. }
  130. if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil {
  131. dash.GnetId = int64(gnetId)
  132. }
  133. return dash
  134. }
  135. // GetDashboardModel turns the command into the saveable model
  136. func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard {
  137. dash := NewDashboardFromJson(cmd.Dashboard)
  138. userId := cmd.UserId
  139. if userId == 0 {
  140. userId = -1
  141. }
  142. dash.UpdatedBy = userId
  143. dash.OrgId = cmd.OrgId
  144. dash.PluginId = cmd.PluginId
  145. dash.IsFolder = cmd.IsFolder
  146. dash.FolderId = cmd.FolderId
  147. dash.UpdateSlug()
  148. return dash
  149. }
  150. // GetString a
  151. func (dash *Dashboard) GetString(prop string, defaultValue string) string {
  152. return dash.Data.Get(prop).MustString(defaultValue)
  153. }
  154. // UpdateSlug updates the slug
  155. func (dash *Dashboard) UpdateSlug() {
  156. title := dash.Data.Get("title").MustString()
  157. dash.Slug = SlugifyTitle(title)
  158. }
  159. func SlugifyTitle(title string) string {
  160. return slug.Make(strings.ToLower(title))
  161. }
  162. // GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
  163. func (dash *Dashboard) GetUrl() string {
  164. return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
  165. }
  166. // Return the html url for a dashboard
  167. func (dash *Dashboard) GenerateUrl() string {
  168. return GetDashboardUrl(dash.Uid, dash.Slug)
  169. }
  170. // GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
  171. func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
  172. if isFolder {
  173. return GetFolderUrl(uid, slug)
  174. }
  175. return GetDashboardUrl(uid, slug)
  176. }
  177. // GetDashboardUrl return the html url for a dashboard
  178. func GetDashboardUrl(uid string, slug string) string {
  179. return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
  180. }
  181. // GetFullDashboardUrl return the full url for a dashboard
  182. func GetFullDashboardUrl(uid string, slug string) string {
  183. return fmt.Sprintf("%sd/%s/%s", setting.AppUrl, uid, slug)
  184. }
  185. // GetFolderUrl return the html url for a folder
  186. func GetFolderUrl(folderUid string, slug string) string {
  187. return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
  188. }
  189. type ValidateDashboardBeforeSaveResult struct {
  190. IsParentFolderChanged bool
  191. }
  192. //
  193. // COMMANDS
  194. //
  195. type SaveDashboardCommand struct {
  196. Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
  197. UserId int64 `json:"userId"`
  198. Overwrite bool `json:"overwrite"`
  199. Message string `json:"message"`
  200. OrgId int64 `json:"-"`
  201. RestoredFrom int `json:"-"`
  202. PluginId string `json:"-"`
  203. FolderId int64 `json:"folderId"`
  204. IsFolder bool `json:"isFolder"`
  205. UpdatedAt time.Time
  206. Result *Dashboard
  207. }
  208. type DashboardProvisioning struct {
  209. Id int64
  210. DashboardId int64
  211. Name string
  212. ExternalId string
  213. CheckSum 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. }
  295. type UnprovisionDashboardCommand struct {
  296. Id int64
  297. }