dashboards.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. if dash.Data.Get("version").MustInt(0) == 0 {
  143. dash.CreatedBy = userId
  144. }
  145. dash.UpdatedBy = userId
  146. dash.OrgId = cmd.OrgId
  147. dash.PluginId = cmd.PluginId
  148. dash.IsFolder = cmd.IsFolder
  149. dash.FolderId = cmd.FolderId
  150. dash.UpdateSlug()
  151. return dash
  152. }
  153. // GetString a
  154. func (dash *Dashboard) GetString(prop string, defaultValue string) string {
  155. return dash.Data.Get(prop).MustString(defaultValue)
  156. }
  157. // UpdateSlug updates the slug
  158. func (dash *Dashboard) UpdateSlug() {
  159. title := dash.Data.Get("title").MustString()
  160. dash.Slug = SlugifyTitle(title)
  161. }
  162. func SlugifyTitle(title string) string {
  163. return slug.Make(strings.ToLower(title))
  164. }
  165. // GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
  166. func (dash *Dashboard) GetUrl() string {
  167. return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
  168. }
  169. // Return the html url for a dashboard
  170. func (dash *Dashboard) GenerateUrl() string {
  171. return GetDashboardUrl(dash.Uid, dash.Slug)
  172. }
  173. // GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
  174. func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
  175. if isFolder {
  176. return GetFolderUrl(uid, slug)
  177. }
  178. return GetDashboardUrl(uid, slug)
  179. }
  180. // Return the html url for a dashboard
  181. func GetDashboardUrl(uid string, slug string) string {
  182. return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
  183. }
  184. // Return the full url for a dashboard
  185. func GetFullDashboardUrl(uid string, slug string) string {
  186. return fmt.Sprintf("%s%s", setting.AppUrl, GetDashboardUrl(uid, slug))
  187. }
  188. // GetFolderUrl return the html url for a folder
  189. func GetFolderUrl(folderUid string, slug string) string {
  190. return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
  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. 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. }
  229. //
  230. // QUERIES
  231. //
  232. type GetDashboardQuery struct {
  233. Slug string // required if no Id or Uid is specified
  234. Id int64 // optional if slug is set
  235. Uid string // optional if slug is set
  236. OrgId int64
  237. Result *Dashboard
  238. }
  239. type DashboardTagCloudItem struct {
  240. Term string `json:"term"`
  241. Count int `json:"count"`
  242. }
  243. type GetDashboardTagsQuery struct {
  244. OrgId int64
  245. Result []*DashboardTagCloudItem
  246. }
  247. type GetDashboardsQuery struct {
  248. DashboardIds []int64
  249. Result []*Dashboard
  250. }
  251. type GetDashboardPermissionsForUserQuery struct {
  252. DashboardIds []int64
  253. OrgId int64
  254. UserId int64
  255. OrgRole RoleType
  256. Result []*DashboardPermissionForUser
  257. }
  258. type GetDashboardsByPluginIdQuery struct {
  259. OrgId int64
  260. PluginId string
  261. Result []*Dashboard
  262. }
  263. type GetDashboardSlugByIdQuery struct {
  264. Id int64
  265. Result string
  266. }
  267. type GetProvisionedDashboardDataQuery struct {
  268. Name string
  269. Result []*DashboardProvisioning
  270. }
  271. type GetDashboardsBySlugQuery struct {
  272. OrgId int64
  273. Slug string
  274. Result []*Dashboard
  275. }
  276. type DashboardPermissionForUser struct {
  277. DashboardId int64 `json:"dashboardId"`
  278. Permission PermissionType `json:"permission"`
  279. PermissionName string `json:"permissionName"`
  280. }
  281. type DashboardRef struct {
  282. Uid string
  283. Slug string
  284. }
  285. type GetDashboardRefByIdQuery struct {
  286. Id int64
  287. Result *DashboardRef
  288. }