folder_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. package api
  2. import (
  3. "github.com/grafana/grafana/pkg/models"
  4. "github.com/grafana/grafana/pkg/services/dashboards"
  5. )
  6. // import (
  7. // "encoding/json"
  8. // "path/filepath"
  9. // "testing"
  10. // "github.com/go-macaron/session"
  11. // "github.com/grafana/grafana/pkg/api/dtos"
  12. // "github.com/grafana/grafana/pkg/bus"
  13. // "github.com/grafana/grafana/pkg/middleware"
  14. // m "github.com/grafana/grafana/pkg/models"
  15. // "github.com/grafana/grafana/pkg/services/dashboards"
  16. // macaron "gopkg.in/macaron.v1"
  17. // . "github.com/smartystreets/goconvey/convey"
  18. // )
  19. // func TestFoldersApiEndpoint(t *testing.T) {
  20. // Convey("Given a dashboard", t, func() {
  21. // fakeDash := m.NewDashboard("Child dash")
  22. // fakeDash.Id = 1
  23. // fakeDash.FolderId = 1
  24. // fakeDash.HasAcl = false
  25. // var getDashboardQueries []*m.GetDashboardQuery
  26. // bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
  27. // query.Result = fakeDash
  28. // getDashboardQueries = append(getDashboardQueries, query)
  29. // return nil
  30. // })
  31. // updateFolderCmd := m.UpdateFolderCommand{}
  32. // Convey("When user is an Org Editor", func() {
  33. // role := m.ROLE_EDITOR
  34. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  35. // callGetFolder(sc)
  36. // So(sc.resp.Code, ShouldEqual, 404)
  37. // Convey("Should lookup folder by uid", func() {
  38. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  39. // })
  40. // })
  41. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
  42. // callGetFolder(sc)
  43. // So(sc.resp.Code, ShouldEqual, 404)
  44. // Convey("Should lookup folder by id", func() {
  45. // So(getDashboardQueries[0].Id, ShouldEqual, 1)
  46. // })
  47. // })
  48. // updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
  49. // callUpdateFolder(sc)
  50. // So(sc.resp.Code, ShouldEqual, 404)
  51. // Convey("Should lookup folder by uid", func() {
  52. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  53. // })
  54. // })
  55. // loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  56. // callDeleteFolder(sc)
  57. // So(sc.resp.Code, ShouldEqual, 404)
  58. // Convey("Should lookup folder by uid", func() {
  59. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  60. // })
  61. // })
  62. // })
  63. // })
  64. // Convey("Given a folder which does not have an acl", t, func() {
  65. // fakeFolder := m.NewDashboardFolder("Folder")
  66. // fakeFolder.Id = 1
  67. // fakeFolder.HasAcl = false
  68. // var getDashboardQueries []*m.GetDashboardQuery
  69. // bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
  70. // query.Result = fakeFolder
  71. // getDashboardQueries = append(getDashboardQueries, query)
  72. // return nil
  73. // })
  74. // viewerRole := m.ROLE_VIEWER
  75. // editorRole := m.ROLE_EDITOR
  76. // aclMockResp := []*m.DashboardAclInfoDTO{
  77. // {Role: &viewerRole, Permission: m.PERMISSION_VIEW},
  78. // {Role: &editorRole, Permission: m.PERMISSION_EDIT},
  79. // }
  80. // bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
  81. // query.Result = aclMockResp
  82. // return nil
  83. // })
  84. // bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
  85. // query.Result = []*m.Team{}
  86. // return nil
  87. // })
  88. // cmd := m.CreateFolderCommand{
  89. // Title: fakeFolder.Title,
  90. // }
  91. // updateFolderCmd := m.UpdateFolderCommand{
  92. // Title: fakeFolder.Title,
  93. // }
  94. // Convey("When user is an Org Viewer", func() {
  95. // role := m.ROLE_VIEWER
  96. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  97. // folder := getFolderShouldReturn200(sc)
  98. // Convey("Should lookup folder by uid", func() {
  99. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  100. // })
  101. // Convey("Should not be able to edit or save folder", func() {
  102. // So(folder.CanEdit, ShouldBeFalse)
  103. // So(folder.CanSave, ShouldBeFalse)
  104. // So(folder.CanAdmin, ShouldBeFalse)
  105. // })
  106. // })
  107. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
  108. // folder := getFolderShouldReturn200(sc)
  109. // Convey("Should lookup folder by id", func() {
  110. // So(getDashboardQueries[0].Id, ShouldEqual, 1)
  111. // })
  112. // Convey("Should not be able to edit or save folder", func() {
  113. // So(folder.CanEdit, ShouldBeFalse)
  114. // So(folder.CanSave, ShouldBeFalse)
  115. // So(folder.CanAdmin, ShouldBeFalse)
  116. // })
  117. // })
  118. // loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  119. // callDeleteFolder(sc)
  120. // So(sc.resp.Code, ShouldEqual, 403)
  121. // Convey("Should lookup folder by uid", func() {
  122. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  123. // })
  124. // })
  125. // createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
  126. // callCreateFolder(sc)
  127. // So(sc.resp.Code, ShouldEqual, 403)
  128. // })
  129. // updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
  130. // callUpdateFolder(sc)
  131. // So(sc.resp.Code, ShouldEqual, 403)
  132. // Convey("Should lookup folder by uid", func() {
  133. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  134. // })
  135. // })
  136. // })
  137. // Convey("When user is an Org Editor", func() {
  138. // role := m.ROLE_EDITOR
  139. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  140. // folder := getFolderShouldReturn200(sc)
  141. // Convey("Should lookup folder by uid", func() {
  142. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  143. // })
  144. // Convey("Should be able to edit or save folder", func() {
  145. // So(folder.CanEdit, ShouldBeTrue)
  146. // So(folder.CanSave, ShouldBeTrue)
  147. // So(folder.CanAdmin, ShouldBeFalse)
  148. // })
  149. // })
  150. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
  151. // folder := getFolderShouldReturn200(sc)
  152. // Convey("Should lookup folder by id", func() {
  153. // So(getDashboardQueries[0].Id, ShouldEqual, 1)
  154. // })
  155. // Convey("Should be able to edit or save folder", func() {
  156. // So(folder.CanEdit, ShouldBeTrue)
  157. // So(folder.CanSave, ShouldBeTrue)
  158. // So(folder.CanAdmin, ShouldBeFalse)
  159. // })
  160. // })
  161. // loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  162. // callDeleteFolder(sc)
  163. // So(sc.resp.Code, ShouldEqual, 200)
  164. // Convey("Should lookup folder by uid", func() {
  165. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  166. // })
  167. // })
  168. // createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
  169. // callCreateFolder(sc)
  170. // So(sc.resp.Code, ShouldEqual, 200)
  171. // })
  172. // updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
  173. // callUpdateFolder(sc)
  174. // So(sc.resp.Code, ShouldEqual, 200)
  175. // Convey("Should lookup folder by uid", func() {
  176. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  177. // })
  178. // })
  179. // })
  180. // })
  181. // Convey("Given a folder which have an acl", t, func() {
  182. // fakeFolder := m.NewDashboardFolder("Folder")
  183. // fakeFolder.Id = 1
  184. // fakeFolder.HasAcl = true
  185. // var getDashboardQueries []*m.GetDashboardQuery
  186. // bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
  187. // query.Result = fakeFolder
  188. // getDashboardQueries = append(getDashboardQueries, query)
  189. // return nil
  190. // })
  191. // aclMockResp := []*m.DashboardAclInfoDTO{
  192. // {
  193. // DashboardId: 1,
  194. // Permission: m.PERMISSION_EDIT,
  195. // UserId: 200,
  196. // },
  197. // }
  198. // bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
  199. // query.Result = aclMockResp
  200. // return nil
  201. // })
  202. // bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
  203. // query.Result = []*m.Team{}
  204. // return nil
  205. // })
  206. // cmd := m.CreateFolderCommand{
  207. // Title: fakeFolder.Title,
  208. // }
  209. // updateFolderCmd := m.UpdateFolderCommand{
  210. // Title: fakeFolder.Title,
  211. // }
  212. // Convey("When user is an Org Viewer and has no permissions for this folder", func() {
  213. // role := m.ROLE_VIEWER
  214. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  215. // callGetFolder(sc)
  216. // Convey("Should lookup folder by uid", func() {
  217. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  218. // })
  219. // Convey("Should be denied access", func() {
  220. // So(sc.resp.Code, ShouldEqual, 403)
  221. // })
  222. // })
  223. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
  224. // callGetFolder(sc)
  225. // Convey("Should lookup folder by id", func() {
  226. // So(getDashboardQueries[0].Id, ShouldEqual, 1)
  227. // })
  228. // Convey("Should be denied access", func() {
  229. // So(sc.resp.Code, ShouldEqual, 403)
  230. // })
  231. // })
  232. // loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  233. // callDeleteFolder(sc)
  234. // So(sc.resp.Code, ShouldEqual, 403)
  235. // Convey("Should lookup folder by uid", func() {
  236. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  237. // })
  238. // })
  239. // createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
  240. // callCreateFolder(sc)
  241. // So(sc.resp.Code, ShouldEqual, 403)
  242. // })
  243. // updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
  244. // callUpdateFolder(sc)
  245. // So(sc.resp.Code, ShouldEqual, 403)
  246. // Convey("Should lookup folder by uid", func() {
  247. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  248. // })
  249. // })
  250. // })
  251. // Convey("When user is an Org Editor and has no permissions for this folder", func() {
  252. // role := m.ROLE_EDITOR
  253. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  254. // callGetFolder(sc)
  255. // Convey("Should lookup folder by uid", func() {
  256. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  257. // })
  258. // Convey("Should be denied access", func() {
  259. // So(sc.resp.Code, ShouldEqual, 403)
  260. // })
  261. // })
  262. // loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
  263. // callGetFolder(sc)
  264. // Convey("Should lookup folder by id", func() {
  265. // So(getDashboardQueries[0].Id, ShouldEqual, 1)
  266. // })
  267. // Convey("Should be denied access", func() {
  268. // So(sc.resp.Code, ShouldEqual, 403)
  269. // })
  270. // })
  271. // loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
  272. // callDeleteFolder(sc)
  273. // So(sc.resp.Code, ShouldEqual, 403)
  274. // Convey("Should lookup folder by uid", func() {
  275. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  276. // })
  277. // })
  278. // createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
  279. // callCreateFolder(sc)
  280. // So(sc.resp.Code, ShouldEqual, 403)
  281. // })
  282. // updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
  283. // callUpdateFolder(sc)
  284. // So(sc.resp.Code, ShouldEqual, 403)
  285. // Convey("Should lookup folder by uid", func() {
  286. // So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
  287. // })
  288. // })
  289. // })
  290. // })
  291. // }
  292. // func getFolderShouldReturn200(sc *scenarioContext) dtos.Folder {
  293. // callGetFolder(sc)
  294. // So(sc.resp.Code, ShouldEqual, 200)
  295. // folder := dtos.Folder{}
  296. // err := json.NewDecoder(sc.resp.Body).Decode(&folder)
  297. // So(err, ShouldBeNil)
  298. // return folder
  299. // }
  300. // func callGetFolder(sc *scenarioContext) {
  301. // sc.handlerFunc = GetFolder
  302. // sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
  303. // }
  304. // func callDeleteFolder(sc *scenarioContext) {
  305. // bus.AddHandler("test", func(cmd *m.DeleteDashboardCommand) error {
  306. // return nil
  307. // })
  308. // sc.handlerFunc = DeleteFolder
  309. // sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
  310. // }
  311. // func callCreateFolder(sc *scenarioContext) {
  312. // bus.AddHandler("test", func(cmd *m.SaveDashboardCommand) error {
  313. // cmd.Result = &m.Dashboard{Id: 1, Slug: "folder", Version: 2}
  314. // return nil
  315. // })
  316. // sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
  317. // }
  318. // func callUpdateFolder(sc *scenarioContext) {
  319. // bus.AddHandler("test", func(cmd *m.SaveDashboardCommand) error {
  320. // cmd.Result = &m.Dashboard{Id: 1, Slug: "folder", Version: 2}
  321. // return nil
  322. // })
  323. // sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
  324. // }
  325. // func createFolderScenario(desc string, url string, routePattern string, role m.RoleType, cmd m.CreateFolderCommand, fn scenarioFunc) {
  326. // Convey(desc+" "+url, func() {
  327. // defer bus.ClearBusHandlers()
  328. // sc := &scenarioContext{
  329. // url: url,
  330. // }
  331. // viewsPath, _ := filepath.Abs("../../public/views")
  332. // sc.m = macaron.New()
  333. // sc.m.Use(macaron.Renderer(macaron.RenderOptions{
  334. // Directory: viewsPath,
  335. // Delims: macaron.Delims{Left: "[[", Right: "]]"},
  336. // }))
  337. // sc.m.Use(middleware.GetContextHandler())
  338. // sc.m.Use(middleware.Sessioner(&session.Options{}))
  339. // sc.defaultHandler = wrap(func(c *middleware.Context) Response {
  340. // sc.context = c
  341. // sc.context.UserId = TestUserID
  342. // sc.context.OrgId = TestOrgID
  343. // sc.context.OrgRole = role
  344. // return CreateFolder(c, cmd)
  345. // })
  346. // fakeRepo = &fakeDashboardRepo{}
  347. // dashboards.SetRepository(fakeRepo)
  348. // sc.m.Post(routePattern, sc.defaultHandler)
  349. // fn(sc)
  350. // })
  351. // }
  352. // func updateFolderScenario(desc string, url string, routePattern string, role m.RoleType, cmd m.UpdateFolderCommand, fn scenarioFunc) {
  353. // Convey(desc+" "+url, func() {
  354. // defer bus.ClearBusHandlers()
  355. // sc := &scenarioContext{
  356. // url: url,
  357. // }
  358. // viewsPath, _ := filepath.Abs("../../public/views")
  359. // sc.m = macaron.New()
  360. // sc.m.Use(macaron.Renderer(macaron.RenderOptions{
  361. // Directory: viewsPath,
  362. // Delims: macaron.Delims{Left: "[[", Right: "]]"},
  363. // }))
  364. // sc.m.Use(middleware.GetContextHandler())
  365. // sc.m.Use(middleware.Sessioner(&session.Options{}))
  366. // sc.defaultHandler = wrap(func(c *middleware.Context) Response {
  367. // sc.context = c
  368. // sc.context.UserId = TestUserID
  369. // sc.context.OrgId = TestOrgID
  370. // sc.context.OrgRole = role
  371. // return UpdateFolder(c, cmd)
  372. // })
  373. // fakeRepo = &fakeDashboardRepo{}
  374. // dashboards.SetRepository(fakeRepo)
  375. // sc.m.Put(routePattern, sc.defaultHandler)
  376. // fn(sc)
  377. // })
  378. // }
  379. type fakeFolderService struct {
  380. GetFoldersResult []*models.Folder
  381. GetFoldersError error
  382. GetFolderByUidResult *models.Folder
  383. GetFolderByUidError error
  384. GetFolderByIdResult *models.Folder
  385. GetFolderByIdError error
  386. CreateFolderError error
  387. UpdateFolderError error
  388. DeleteFolderResult *models.Folder
  389. DeleteFolderError error
  390. CreatedFolders []*models.CreateFolderCommand
  391. UpdatedFolders []*models.UpdateFolderCommand
  392. DeletedFolderUids []string
  393. }
  394. func (s *fakeFolderService) GetFolders(limit int) ([]*models.Folder, error) {
  395. return s.GetFoldersResult, s.GetFoldersError
  396. }
  397. func (s *fakeFolderService) GetFolderById(id int64) (*models.Folder, error) {
  398. return s.GetFolderByIdResult, s.GetFolderByIdError
  399. }
  400. func (s *fakeFolderService) GetFolderByUid(uid string) (*models.Folder, error) {
  401. return s.GetFolderByUidResult, s.GetFolderByUidError
  402. }
  403. func (s *fakeFolderService) CreateFolder(cmd *models.CreateFolderCommand) error {
  404. return s.CreateFolderError
  405. }
  406. func (s *fakeFolderService) UpdateFolder(existingUid string, cmd *models.UpdateFolderCommand) error {
  407. return s.UpdateFolderError
  408. }
  409. func (s *fakeFolderService) DeleteFolder(uid string) (*models.Folder, error) {
  410. s.DeletedFolderUids = append(s.DeletedFolderUids, uid)
  411. return s.DeleteFolderResult, s.DeleteFolderError
  412. }
  413. func mockFolderService(mock *fakeFolderService) {
  414. dashboards.NewFolderService = func(orgId int64, user *models.SignedInUser) dashboards.FolderService {
  415. return mock
  416. }
  417. }