folder.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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, id int64, uid string) (*m.Dashboard, Response) {
  13. query := m.GetDashboardQuery{OrgId: orgId, Id: id, Uid: uid}
  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 GetFolder(c *middleware.Context) Response {
  45. folder, rsp := getFolderHelper(c.OrgId, c.ParamsInt64(":id"), c.Params(":uid"))
  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 := cmd.GetDashboardModel()
  60. guardian := guardian.NewDashboardGuardian(0, c.OrgId, c.SignedInUser)
  61. if canSave, err := guardian.CanSave(); err != nil || !canSave {
  62. return folderGuardianResponse(err)
  63. }
  64. if dashFolder.Title == "" {
  65. return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
  66. }
  67. limitReached, err := middleware.QuotaReached(c, "folder")
  68. if err != nil {
  69. return ApiError(500, "failed to get quota", err)
  70. }
  71. if limitReached {
  72. return ApiError(403, "Quota reached", nil)
  73. }
  74. dashItem := &dashboards.SaveDashboardItem{
  75. Dashboard: dashFolder,
  76. OrgId: c.OrgId,
  77. UserId: c.UserId,
  78. }
  79. folder, err := dashboards.GetRepository().SaveDashboard(dashItem)
  80. if err != nil {
  81. return toFolderError(err)
  82. }
  83. return Json(200, toDto(guardian, folder))
  84. }
  85. func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
  86. cmd.OrgId = c.OrgId
  87. cmd.UserId = c.UserId
  88. uid := c.Params(":uid")
  89. dashFolder, rsp := getFolderHelper(c.OrgId, 0, uid)
  90. if rsp != nil {
  91. return rsp
  92. }
  93. guardian := guardian.NewDashboardGuardian(dashFolder.Id, c.OrgId, c.SignedInUser)
  94. if canSave, err := guardian.CanSave(); err != nil || !canSave {
  95. return folderGuardianResponse(err)
  96. }
  97. cmd.UpdateDashboardModel(dashFolder)
  98. if dashFolder.Title == "" {
  99. return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
  100. }
  101. dashItem := &dashboards.SaveDashboardItem{
  102. Dashboard: dashFolder,
  103. OrgId: c.OrgId,
  104. UserId: c.UserId,
  105. Overwrite: cmd.Overwrite,
  106. }
  107. folder, err := dashboards.GetRepository().SaveDashboard(dashItem)
  108. if err != nil {
  109. return toFolderError(err)
  110. }
  111. return Json(200, toDto(guardian, folder))
  112. }
  113. func DeleteFolder(c *middleware.Context) Response {
  114. dashFolder, rsp := getFolderHelper(c.OrgId, 0, c.Params(":uid"))
  115. if rsp != nil {
  116. return rsp
  117. }
  118. guardian := guardian.NewDashboardGuardian(dashFolder.Id, c.OrgId, c.SignedInUser)
  119. if canSave, err := guardian.CanSave(); err != nil || !canSave {
  120. return folderGuardianResponse(err)
  121. }
  122. deleteCmd := m.DeleteDashboardCommand{OrgId: c.OrgId, Id: dashFolder.Id}
  123. if err := bus.Dispatch(&deleteCmd); err != nil {
  124. return ApiError(500, "Failed to delete folder", err)
  125. }
  126. var resp = map[string]interface{}{"title": dashFolder.Title}
  127. return Json(200, resp)
  128. }
  129. func toDto(guardian *guardian.DashboardGuardian, folder *m.Dashboard) dtos.Folder {
  130. canEdit, _ := guardian.CanEdit()
  131. canSave, _ := guardian.CanSave()
  132. canAdmin, _ := guardian.CanAdmin()
  133. // Finding creator and last updater of the folder
  134. updater, creator := "Anonymous", "Anonymous"
  135. if folder.CreatedBy > 0 {
  136. creator = getUserLogin(folder.CreatedBy)
  137. }
  138. if folder.UpdatedBy > 0 {
  139. updater = getUserLogin(folder.UpdatedBy)
  140. }
  141. return dtos.Folder{
  142. Id: folder.Id,
  143. Uid: folder.Uid,
  144. Title: folder.Title,
  145. Url: folder.GetUrl(),
  146. HasAcl: folder.HasAcl,
  147. CanSave: canSave,
  148. CanEdit: canEdit,
  149. CanAdmin: canAdmin,
  150. CreatedBy: creator,
  151. Created: folder.Created,
  152. UpdatedBy: updater,
  153. Updated: folder.Updated,
  154. Version: folder.Version,
  155. }
  156. }
  157. func toFolderError(err error) Response {
  158. if err == m.ErrDashboardTitleEmpty {
  159. return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
  160. }
  161. if err == m.ErrDashboardWithSameNameInFolderExists {
  162. return Json(412, util.DynMap{"status": "name-exists", "message": m.ErrFolderSameNameExists.Error()})
  163. }
  164. if err == m.ErrDashboardWithSameUIDExists {
  165. return Json(412, util.DynMap{"status": "uid-exists", "message": m.ErrFolderWithSameUIDExists.Error()})
  166. }
  167. if err == m.ErrDashboardVersionMismatch {
  168. return Json(412, util.DynMap{"status": "version-mismatch", "message": m.ErrFolderVersionMismatch.Error()})
  169. }
  170. if err == m.ErrDashboardNotFound {
  171. return Json(404, util.DynMap{"status": "not-found", "message": m.ErrFolderNotFound.Error()})
  172. }
  173. if err == m.ErrDashboardFailedGenerateUniqueUid {
  174. err = m.ErrFolderFailedGenerateUniqueUid
  175. }
  176. return ApiError(500, "Failed to create folder", err)
  177. }