folders.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package api
  2. import (
  3. "fmt"
  4. "github.com/grafana/grafana/pkg/api/dtos"
  5. "github.com/grafana/grafana/pkg/bus"
  6. "github.com/grafana/grafana/pkg/middleware"
  7. m "github.com/grafana/grafana/pkg/models"
  8. "github.com/grafana/grafana/pkg/services/dashboards"
  9. "github.com/grafana/grafana/pkg/services/guardian"
  10. "github.com/grafana/grafana/pkg/util"
  11. )
  12. func getFolderHelper(orgId int64, slug string, id int64) (*m.Dashboard, Response) {
  13. query := m.GetDashboardQuery{Slug: slug, Id: id, OrgId: orgId}
  14. if err := bus.Dispatch(&query); err != nil {
  15. if err == m.ErrDashboardNotFound {
  16. err = m.ErrFolderNotFound
  17. }
  18. return nil, ApiError(404, "Folder not found", err)
  19. }
  20. if !query.Result.IsFolder {
  21. return nil, ApiError(404, "Folder not found", m.ErrFolderNotFound)
  22. }
  23. return query.Result, nil
  24. }
  25. func folderGuardianResponse(err error) Response {
  26. if err != nil {
  27. return ApiError(500, "Error while checking folder permissions", err)
  28. }
  29. return ApiError(403, "Access denied to this folder", nil)
  30. }
  31. func GetFoldersForSignedInUser(c *middleware.Context) Response {
  32. title := c.Query("query")
  33. query := m.GetFoldersForSignedInUserQuery{
  34. OrgId: c.OrgId,
  35. SignedInUser: c.SignedInUser,
  36. Title: title,
  37. }
  38. err := bus.Dispatch(&query)
  39. if err != nil {
  40. return ApiError(500, "Failed to retrieve folders", err)
  41. }
  42. return Json(200, query.Result)
  43. }
  44. func GetFolderById(c *middleware.Context) Response {
  45. folder, rsp := getFolderHelper(c.OrgId, "", c.ParamsInt64(":id"))
  46. if rsp != nil {
  47. return rsp
  48. }
  49. guardian := guardian.NewDashboardGuardian(folder.Id, c.OrgId, c.SignedInUser)
  50. if canView, err := guardian.CanView(); err != nil || !canView {
  51. fmt.Printf("%v", err)
  52. return folderGuardianResponse(err)
  53. }
  54. return Json(200, toDto(guardian, folder))
  55. }
  56. func CreateFolder(c *middleware.Context, cmd m.CreateFolderCommand) Response {
  57. cmd.OrgId = c.OrgId
  58. cmd.UserId = c.UserId
  59. dashFolder := m.NewDashboardFolder(cmd.Title)
  60. guardian := guardian.NewDashboardGuardian(0, c.OrgId, c.SignedInUser)
  61. if canSave, err := guardian.CanSave(); err != nil || !canSave {
  62. return folderGuardianResponse(err)
  63. }
  64. // Check if Title is empty
  65. if dashFolder.Title == "" {
  66. return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
  67. }
  68. limitReached, err := middleware.QuotaReached(c, "folder")
  69. if err != nil {
  70. return ApiError(500, "failed to get quota", err)
  71. }
  72. if limitReached {
  73. return ApiError(403, "Quota reached", nil)
  74. }
  75. dashFolder.CreatedBy = c.UserId
  76. dashFolder.UpdatedBy = c.UserId
  77. dashItem := &dashboards.SaveDashboardItem{
  78. Dashboard: dashFolder,
  79. OrgId: c.OrgId,
  80. UserId: c.UserId,
  81. }
  82. folder, err := dashboards.GetRepository().SaveDashboard(dashItem)
  83. if err != nil {
  84. return toFolderError(err)
  85. }
  86. return Json(200, toDto(guardian, folder))
  87. }
  88. func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
  89. cmd.OrgId = c.OrgId
  90. cmd.UserId = c.UserId
  91. dashFolder, rsp := getFolderHelper(c.OrgId, "", c.ParamsInt64(":id"))
  92. if rsp != nil {
  93. return rsp
  94. }
  95. guardian := guardian.NewDashboardGuardian(dashFolder.Id, c.OrgId, c.SignedInUser)
  96. if canSave, err := guardian.CanSave(); err != nil || !canSave {
  97. return folderGuardianResponse(err)
  98. }
  99. dashFolder.Data.Set("title", cmd.Title)
  100. dashFolder.Title = cmd.Title
  101. dashFolder.Data.Set("version", cmd.Version)
  102. dashFolder.Version = cmd.Version
  103. dashFolder.UpdatedBy = c.UserId
  104. // Check if Title is empty
  105. if dashFolder.Title == "" {
  106. return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
  107. }
  108. dashItem := &dashboards.SaveDashboardItem{
  109. Dashboard: dashFolder,
  110. OrgId: c.OrgId,
  111. UserId: c.UserId,
  112. }
  113. folder, err := dashboards.GetRepository().SaveDashboard(dashItem)
  114. if err != nil {
  115. return toFolderError(err)
  116. }
  117. return Json(200, toDto(guardian, folder))
  118. }
  119. func DeleteFolder(c *middleware.Context) Response {
  120. dashFolder, rsp := getFolderHelper(c.OrgId, "", c.ParamsInt64(":id"))
  121. if rsp != nil {
  122. return rsp
  123. }
  124. guardian := guardian.NewDashboardGuardian(dashFolder.Id, c.OrgId, c.SignedInUser)
  125. if canSave, err := guardian.CanSave(); err != nil || !canSave {
  126. return folderGuardianResponse(err)
  127. }
  128. deleteCmd := m.DeleteDashboardCommand{OrgId: c.OrgId, Id: dashFolder.Id}
  129. if err := bus.Dispatch(&deleteCmd); err != nil {
  130. return ApiError(500, "Failed to delete folder", err)
  131. }
  132. var resp = map[string]interface{}{"title": dashFolder.Title}
  133. return Json(200, resp)
  134. }
  135. func toDto(guardian *guardian.DashboardGuardian, folder *m.Dashboard) dtos.Folder {
  136. canEdit, _ := guardian.CanEdit()
  137. canSave, _ := guardian.CanSave()
  138. canAdmin, _ := guardian.CanAdmin()
  139. // Finding creator and last updater of the folder
  140. updater, creator := "Anonymous", "Anonymous"
  141. if folder.UpdatedBy > 0 {
  142. updater = getUserLogin(folder.UpdatedBy)
  143. }
  144. if folder.CreatedBy > 0 {
  145. creator = getUserLogin(folder.CreatedBy)
  146. }
  147. return dtos.Folder{
  148. Id: folder.Id,
  149. Title: folder.Title,
  150. Slug: folder.Slug,
  151. HasAcl: folder.HasAcl,
  152. CanSave: canSave,
  153. CanEdit: canEdit,
  154. CanAdmin: canAdmin,
  155. CreatedBy: creator,
  156. Created: folder.Created,
  157. UpdatedBy: updater,
  158. Updated: folder.Updated,
  159. Version: folder.Version,
  160. }
  161. }
  162. func toFolderError(err error) Response {
  163. if err == m.ErrDashboardTitleEmpty {
  164. return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
  165. }
  166. if err == m.ErrDashboardWithSameUIDExists {
  167. return Json(412, util.DynMap{"status": "uid-exists", "message": m.ErrFolderWithSameUIDExists.Error()})
  168. }
  169. if err == m.ErrDashboardVersionMismatch {
  170. return Json(412, util.DynMap{"status": "version-mismatch", "message": m.ErrFolderVersionMismatch.Error()})
  171. }
  172. if err == m.ErrDashboardNotFound {
  173. return Json(404, util.DynMap{"status": "not-found", "message": m.ErrFolderNotFound.Error()})
  174. }
  175. if err == m.ErrDashboardFailedGenerateUniqueUid {
  176. err = m.ErrFolderFailedGenerateUniqueUid
  177. }
  178. return ApiError(500, "Failed to create folder", err)
  179. }