dashboard.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package api
  2. import (
  3. "encoding/json"
  4. "os"
  5. "path"
  6. "strings"
  7. "github.com/grafana/grafana/pkg/api/dtos"
  8. "github.com/grafana/grafana/pkg/bus"
  9. "github.com/grafana/grafana/pkg/log"
  10. "github.com/grafana/grafana/pkg/metrics"
  11. "github.com/grafana/grafana/pkg/middleware"
  12. m "github.com/grafana/grafana/pkg/models"
  13. "github.com/grafana/grafana/pkg/plugins"
  14. "github.com/grafana/grafana/pkg/services/alerting"
  15. "github.com/grafana/grafana/pkg/services/search"
  16. "github.com/grafana/grafana/pkg/setting"
  17. "github.com/grafana/grafana/pkg/util"
  18. )
  19. func isDashboardStarredByUser(c *middleware.Context, dashId int64) (bool, error) {
  20. if !c.IsSignedIn {
  21. return false, nil
  22. }
  23. query := m.IsStarredByUserQuery{UserId: c.UserId, DashboardId: dashId}
  24. if err := bus.Dispatch(&query); err != nil {
  25. return false, err
  26. }
  27. return query.Result, nil
  28. }
  29. func GetDashboard(c *middleware.Context) {
  30. slug := strings.ToLower(c.Params(":slug"))
  31. query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId}
  32. err := bus.Dispatch(&query)
  33. if err != nil {
  34. c.JsonApiErr(404, "Dashboard not found", nil)
  35. return
  36. }
  37. isStarred, err := isDashboardStarredByUser(c, query.Result.Id)
  38. if err != nil {
  39. c.JsonApiErr(500, "Error while checking if dashboard was starred by user", err)
  40. return
  41. }
  42. dash := query.Result
  43. // Finding creator and last updater of the dashboard
  44. updater, creator := "Anonymous", "Anonymous"
  45. if dash.UpdatedBy > 0 {
  46. updater = getUserLogin(dash.UpdatedBy)
  47. }
  48. if dash.CreatedBy > 0 {
  49. creator = getUserLogin(dash.CreatedBy)
  50. }
  51. dto := dtos.DashboardFullWithMeta{
  52. Dashboard: dash.Data,
  53. Meta: dtos.DashboardMeta{
  54. IsStarred: isStarred,
  55. Slug: slug,
  56. Type: m.DashTypeDB,
  57. CanStar: c.IsSignedIn,
  58. CanSave: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
  59. CanEdit: canEditDashboard(c.OrgRole),
  60. Created: dash.Created,
  61. Updated: dash.Updated,
  62. UpdatedBy: updater,
  63. CreatedBy: creator,
  64. Version: dash.Version,
  65. },
  66. }
  67. c.TimeRequest(metrics.M_Api_Dashboard_Get)
  68. c.JSON(200, dto)
  69. }
  70. func getUserLogin(userId int64) string {
  71. query := m.GetUserByIdQuery{Id: userId}
  72. err := bus.Dispatch(&query)
  73. if err != nil {
  74. return "Anonymous"
  75. } else {
  76. user := query.Result
  77. return user.Login
  78. }
  79. }
  80. func DeleteDashboard(c *middleware.Context) {
  81. slug := c.Params(":slug")
  82. query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId}
  83. if err := bus.Dispatch(&query); err != nil {
  84. c.JsonApiErr(404, "Dashboard not found", nil)
  85. return
  86. }
  87. cmd := m.DeleteDashboardCommand{Slug: slug, OrgId: c.OrgId}
  88. if err := bus.Dispatch(&cmd); err != nil {
  89. c.JsonApiErr(500, "Failed to delete dashboard", err)
  90. return
  91. }
  92. var resp = map[string]interface{}{"title": query.Result.Title}
  93. c.JSON(200, resp)
  94. }
  95. func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) Response {
  96. cmd.OrgId = c.OrgId
  97. if !c.IsSignedIn {
  98. cmd.UserId = -1
  99. } else {
  100. cmd.UserId = c.UserId
  101. }
  102. dash := cmd.GetDashboardModel()
  103. if dash.Id == 0 {
  104. limitReached, err := middleware.QuotaReached(c, "dashboard")
  105. if err != nil {
  106. return ApiError(500, "failed to get quota", err)
  107. }
  108. if limitReached {
  109. return ApiError(403, "Quota reached", nil)
  110. }
  111. }
  112. err := bus.Dispatch(&cmd)
  113. if err != nil {
  114. if err == m.ErrDashboardWithSameNameExists {
  115. return Json(412, util.DynMap{"status": "name-exists", "message": err.Error()})
  116. }
  117. if err == m.ErrDashboardVersionMismatch {
  118. return Json(412, util.DynMap{"status": "version-mismatch", "message": err.Error()})
  119. }
  120. if pluginErr, ok := err.(m.UpdatePluginDashboardError); ok {
  121. message := "Dashboard is belongs to plugin " + pluginErr.PluginId + "."
  122. // look up plugin name
  123. if pluginDef, exist := plugins.Plugins[pluginErr.PluginId]; exist {
  124. message = "Dashboard is belongs to plugin " + pluginDef.Name + "."
  125. }
  126. return Json(412, util.DynMap{"status": "plugin-dashboard", "message": message})
  127. }
  128. if err == m.ErrDashboardNotFound {
  129. return Json(404, util.DynMap{"status": "not-found", "message": err.Error()})
  130. }
  131. return ApiError(500, "Failed to save dashboard", err)
  132. }
  133. if setting.AlertingEnabled {
  134. alertCmd := alerting.UpdateDashboardAlertsCommand{
  135. OrgId: c.OrgId,
  136. UserId: c.UserId,
  137. Dashboard: cmd.Result,
  138. }
  139. if err := bus.Dispatch(&alertCmd); err != nil {
  140. return ApiError(500, "Failed to save alerts", err)
  141. }
  142. }
  143. c.TimeRequest(metrics.M_Api_Dashboard_Save)
  144. return Json(200, util.DynMap{"status": "success", "slug": cmd.Result.Slug, "version": cmd.Result.Version})
  145. }
  146. func canEditDashboard(role m.RoleType) bool {
  147. return role == m.ROLE_ADMIN || role == m.ROLE_EDITOR || role == m.ROLE_READ_ONLY_EDITOR
  148. }
  149. func GetHomeDashboard(c *middleware.Context) Response {
  150. prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId}
  151. if err := bus.Dispatch(&prefsQuery); err != nil {
  152. return ApiError(500, "Failed to get preferences", err)
  153. }
  154. if prefsQuery.Result.HomeDashboardId != 0 {
  155. slugQuery := m.GetDashboardSlugByIdQuery{Id: prefsQuery.Result.HomeDashboardId}
  156. err := bus.Dispatch(&slugQuery)
  157. if err == nil {
  158. dashRedirect := dtos.DashboardRedirect{RedirectUri: "db/" + slugQuery.Result}
  159. return Json(200, &dashRedirect)
  160. } else {
  161. log.Warn("Failed to get slug from database, %s", err.Error())
  162. }
  163. }
  164. filePath := path.Join(setting.StaticRootPath, "dashboards/home.json")
  165. file, err := os.Open(filePath)
  166. if err != nil {
  167. return ApiError(500, "Failed to load home dashboard", err)
  168. }
  169. dash := dtos.DashboardFullWithMeta{}
  170. dash.Meta.IsHome = true
  171. dash.Meta.CanEdit = canEditDashboard(c.OrgRole)
  172. jsonParser := json.NewDecoder(file)
  173. if err := jsonParser.Decode(&dash.Dashboard); err != nil {
  174. return ApiError(500, "Failed to load home dashboard", err)
  175. }
  176. return Json(200, &dash)
  177. }
  178. func GetDashboardFromJsonFile(c *middleware.Context) {
  179. file := c.Params(":file")
  180. dashboard := search.GetDashboardFromJsonIndex(file)
  181. if dashboard == nil {
  182. c.JsonApiErr(404, "Dashboard not found", nil)
  183. return
  184. }
  185. dash := dtos.DashboardFullWithMeta{Dashboard: dashboard.Data}
  186. dash.Meta.Type = m.DashTypeJson
  187. dash.Meta.CanEdit = canEditDashboard(c.OrgRole)
  188. c.JSON(200, &dash)
  189. }
  190. func GetDashboardTags(c *middleware.Context) {
  191. query := m.GetDashboardTagsQuery{OrgId: c.OrgId}
  192. err := bus.Dispatch(&query)
  193. if err != nil {
  194. c.JsonApiErr(500, "Failed to get tags from database", err)
  195. return
  196. }
  197. c.JSON(200, query.Result)
  198. }