dashboards.go 8.9 KB

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