dashboards.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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. 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", 16)
  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 savable 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. //
  190. // COMMANDS
  191. //
  192. type SaveDashboardCommand struct {
  193. Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
  194. UserId int64 `json:"userId"`
  195. Overwrite bool `json:"overwrite"`
  196. Message string `json:"message"`
  197. OrgId int64 `json:"-"`
  198. RestoredFrom int `json:"-"`
  199. PluginId string `json:"-"`
  200. FolderId int64 `json:"folderId"`
  201. IsFolder bool `json:"isFolder"`
  202. UpdatedAt time.Time
  203. Result *Dashboard
  204. }
  205. type DashboardProvisioning struct {
  206. Id int64
  207. DashboardId int64
  208. Name string
  209. ExternalId string
  210. Updated int64
  211. }
  212. type SaveProvisionedDashboardCommand struct {
  213. DashboardCmd *SaveDashboardCommand
  214. DashboardProvisioning *DashboardProvisioning
  215. Result *Dashboard
  216. }
  217. type DeleteDashboardCommand struct {
  218. Id int64
  219. OrgId int64
  220. }
  221. type ValidateDashboardBeforeSaveCommand struct {
  222. OrgId int64
  223. Dashboard *Dashboard
  224. Overwrite bool
  225. }
  226. //
  227. // QUERIES
  228. //
  229. type GetDashboardQuery struct {
  230. Slug string // required if no Id or Uid is specified
  231. Id int64 // optional if slug is set
  232. Uid string // optional if slug is set
  233. OrgId int64
  234. Result *Dashboard
  235. }
  236. type DashboardTagCloudItem struct {
  237. Term string `json:"term"`
  238. Count int `json:"count"`
  239. }
  240. type GetDashboardTagsQuery struct {
  241. OrgId int64
  242. Result []*DashboardTagCloudItem
  243. }
  244. type GetDashboardsQuery struct {
  245. DashboardIds []int64
  246. Result []*Dashboard
  247. }
  248. type GetDashboardPermissionsForUserQuery struct {
  249. DashboardIds []int64
  250. OrgId int64
  251. UserId int64
  252. OrgRole RoleType
  253. Result []*DashboardPermissionForUser
  254. }
  255. type GetDashboardsByPluginIdQuery struct {
  256. OrgId int64
  257. PluginId string
  258. Result []*Dashboard
  259. }
  260. type GetDashboardSlugByIdQuery struct {
  261. Id int64
  262. Result string
  263. }
  264. type GetProvisionedDashboardDataQuery struct {
  265. Name string
  266. Result []*DashboardProvisioning
  267. }
  268. type GetDashboardsBySlugQuery struct {
  269. OrgId int64
  270. Slug string
  271. Result []*Dashboard
  272. }
  273. type DashboardPermissionForUser struct {
  274. DashboardId int64 `json:"dashboardId"`
  275. Permission PermissionType `json:"permission"`
  276. PermissionName string `json:"permissionName"`
  277. }
  278. type DashboardRef struct {
  279. Uid string
  280. Slug string
  281. }
  282. type GetDashboardRefByIdQuery struct {
  283. Id int64
  284. Result *DashboardRef
  285. }