mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
folders: changes and updated tests after merging permissions and new url structure
This commit is contained in:
parent
5912cf4dc2
commit
04a9a650e7
@ -248,10 +248,11 @@ func (hs *HttpServer) registerRoutes() {
|
|||||||
|
|
||||||
// Folders
|
// Folders
|
||||||
apiRoute.Group("/folders", func(folderRoute RouteRegister) {
|
apiRoute.Group("/folders", func(folderRoute RouteRegister) {
|
||||||
folderRoute.Get("/:id", wrap(GetFolderById))
|
folderRoute.Get("/:uid", wrap(GetFolder))
|
||||||
|
folderRoute.Get("/id/:id", wrap(GetFolder))
|
||||||
folderRoute.Post("/", bind(m.CreateFolderCommand{}), wrap(CreateFolder))
|
folderRoute.Post("/", bind(m.CreateFolderCommand{}), wrap(CreateFolder))
|
||||||
folderRoute.Put("/:id", bind(m.UpdateFolderCommand{}), wrap(UpdateFolder))
|
folderRoute.Put("/:uid", bind(m.UpdateFolderCommand{}), wrap(UpdateFolder))
|
||||||
folderRoute.Delete("/:id", wrap(DeleteFolder))
|
folderRoute.Delete("/:uid", wrap(DeleteFolder))
|
||||||
})
|
})
|
||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
|
@ -4,8 +4,9 @@ import "time"
|
|||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
|
Uid string `json:"uid"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Slug string `json:"slug"`
|
Url string `json:"url"`
|
||||||
HasAcl bool `json:"hasAcl"`
|
HasAcl bool `json:"hasAcl"`
|
||||||
CanSave bool `json:"canSave"`
|
CanSave bool `json:"canSave"`
|
||||||
CanEdit bool `json:"canEdit"`
|
CanEdit bool `json:"canEdit"`
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getFolderHelper(orgId int64, slug string, id int64) (*m.Dashboard, Response) {
|
func getFolderHelper(orgId int64, id int64, uid string) (*m.Dashboard, Response) {
|
||||||
query := m.GetDashboardQuery{Slug: slug, Id: id, OrgId: orgId}
|
query := m.GetDashboardQuery{OrgId: orgId, Id: id, Uid: uid}
|
||||||
if err := bus.Dispatch(&query); err != nil {
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
if err == m.ErrDashboardNotFound {
|
if err == m.ErrDashboardNotFound {
|
||||||
err = m.ErrFolderNotFound
|
err = m.ErrFolderNotFound
|
||||||
@ -53,8 +53,8 @@ func GetFoldersForSignedInUser(c *middleware.Context) Response {
|
|||||||
return Json(200, query.Result)
|
return Json(200, query.Result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFolderById(c *middleware.Context) Response {
|
func GetFolder(c *middleware.Context) Response {
|
||||||
folder, rsp := getFolderHelper(c.OrgId, "", c.ParamsInt64(":id"))
|
folder, rsp := getFolderHelper(c.OrgId, c.ParamsInt64(":id"), c.Params(":uid"))
|
||||||
if rsp != nil {
|
if rsp != nil {
|
||||||
return rsp
|
return rsp
|
||||||
}
|
}
|
||||||
@ -72,14 +72,13 @@ func CreateFolder(c *middleware.Context, cmd m.CreateFolderCommand) Response {
|
|||||||
cmd.OrgId = c.OrgId
|
cmd.OrgId = c.OrgId
|
||||||
cmd.UserId = c.UserId
|
cmd.UserId = c.UserId
|
||||||
|
|
||||||
dashFolder := m.NewDashboardFolder(cmd.Title)
|
dashFolder := cmd.GetDashboardModel()
|
||||||
|
|
||||||
guardian := guardian.NewDashboardGuardian(0, c.OrgId, c.SignedInUser)
|
guardian := guardian.NewDashboardGuardian(0, c.OrgId, c.SignedInUser)
|
||||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||||
return folderGuardianResponse(err)
|
return folderGuardianResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if Title is empty
|
|
||||||
if dashFolder.Title == "" {
|
if dashFolder.Title == "" {
|
||||||
return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
|
return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
|
||||||
}
|
}
|
||||||
@ -92,9 +91,6 @@ func CreateFolder(c *middleware.Context, cmd m.CreateFolderCommand) Response {
|
|||||||
return ApiError(403, "Quota reached", nil)
|
return ApiError(403, "Quota reached", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
dashFolder.CreatedBy = c.UserId
|
|
||||||
dashFolder.UpdatedBy = c.UserId
|
|
||||||
|
|
||||||
dashItem := &dashboards.SaveDashboardItem{
|
dashItem := &dashboards.SaveDashboardItem{
|
||||||
Dashboard: dashFolder,
|
Dashboard: dashFolder,
|
||||||
OrgId: c.OrgId,
|
OrgId: c.OrgId,
|
||||||
@ -113,8 +109,9 @@ func CreateFolder(c *middleware.Context, cmd m.CreateFolderCommand) Response {
|
|||||||
func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
|
func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
|
||||||
cmd.OrgId = c.OrgId
|
cmd.OrgId = c.OrgId
|
||||||
cmd.UserId = c.UserId
|
cmd.UserId = c.UserId
|
||||||
|
uid := c.Params(":uid")
|
||||||
|
|
||||||
dashFolder, rsp := getFolderHelper(c.OrgId, "", c.ParamsInt64(":id"))
|
dashFolder, rsp := getFolderHelper(c.OrgId, 0, uid)
|
||||||
if rsp != nil {
|
if rsp != nil {
|
||||||
return rsp
|
return rsp
|
||||||
}
|
}
|
||||||
@ -124,13 +121,8 @@ func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
|
|||||||
return folderGuardianResponse(err)
|
return folderGuardianResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dashFolder.Data.Set("title", cmd.Title)
|
cmd.UpdateDashboardModel(dashFolder)
|
||||||
dashFolder.Title = cmd.Title
|
|
||||||
dashFolder.Data.Set("version", cmd.Version)
|
|
||||||
dashFolder.Version = cmd.Version
|
|
||||||
dashFolder.UpdatedBy = c.UserId
|
|
||||||
|
|
||||||
// Check if Title is empty
|
|
||||||
if dashFolder.Title == "" {
|
if dashFolder.Title == "" {
|
||||||
return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
|
return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
|
||||||
}
|
}
|
||||||
@ -139,6 +131,7 @@ func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
|
|||||||
Dashboard: dashFolder,
|
Dashboard: dashFolder,
|
||||||
OrgId: c.OrgId,
|
OrgId: c.OrgId,
|
||||||
UserId: c.UserId,
|
UserId: c.UserId,
|
||||||
|
Overwrite: cmd.Overwrite,
|
||||||
}
|
}
|
||||||
|
|
||||||
folder, err := dashboards.GetRepository().SaveDashboard(dashItem)
|
folder, err := dashboards.GetRepository().SaveDashboard(dashItem)
|
||||||
@ -151,7 +144,7 @@ func UpdateFolder(c *middleware.Context, cmd m.UpdateFolderCommand) Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteFolder(c *middleware.Context) Response {
|
func DeleteFolder(c *middleware.Context) Response {
|
||||||
dashFolder, rsp := getFolderHelper(c.OrgId, "", c.ParamsInt64(":id"))
|
dashFolder, rsp := getFolderHelper(c.OrgId, 0, c.Params(":uid"))
|
||||||
if rsp != nil {
|
if rsp != nil {
|
||||||
return rsp
|
return rsp
|
||||||
}
|
}
|
||||||
@ -177,17 +170,18 @@ func toDto(guardian *guardian.DashboardGuardian, folder *m.Dashboard) dtos.Folde
|
|||||||
|
|
||||||
// Finding creator and last updater of the folder
|
// Finding creator and last updater of the folder
|
||||||
updater, creator := "Anonymous", "Anonymous"
|
updater, creator := "Anonymous", "Anonymous"
|
||||||
if folder.UpdatedBy > 0 {
|
|
||||||
updater = getUserLogin(folder.UpdatedBy)
|
|
||||||
}
|
|
||||||
if folder.CreatedBy > 0 {
|
if folder.CreatedBy > 0 {
|
||||||
creator = getUserLogin(folder.CreatedBy)
|
creator = getUserLogin(folder.CreatedBy)
|
||||||
}
|
}
|
||||||
|
if folder.UpdatedBy > 0 {
|
||||||
|
updater = getUserLogin(folder.UpdatedBy)
|
||||||
|
}
|
||||||
|
|
||||||
return dtos.Folder{
|
return dtos.Folder{
|
||||||
Id: folder.Id,
|
Id: folder.Id,
|
||||||
|
Uid: folder.Uid,
|
||||||
Title: folder.Title,
|
Title: folder.Title,
|
||||||
Slug: folder.Slug,
|
Url: folder.GetUrl(),
|
||||||
HasAcl: folder.HasAcl,
|
HasAcl: folder.HasAcl,
|
||||||
CanSave: canSave,
|
CanSave: canSave,
|
||||||
CanEdit: canEdit,
|
CanEdit: canEdit,
|
||||||
@ -205,6 +199,10 @@ func toFolderError(err error) Response {
|
|||||||
return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
|
return ApiError(400, m.ErrFolderTitleEmpty.Error(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err == m.ErrDashboardWithSameNameInFolderExists {
|
||||||
|
return Json(412, util.DynMap{"status": "name-exists", "message": m.ErrFolderSameNameExists.Error()})
|
||||||
|
}
|
||||||
|
|
||||||
if err == m.ErrDashboardWithSameUIDExists {
|
if err == m.ErrDashboardWithSameUIDExists {
|
||||||
return Json(412, util.DynMap{"status": "uid-exists", "message": m.ErrFolderWithSameUIDExists.Error()})
|
return Json(412, util.DynMap{"status": "uid-exists", "message": m.ErrFolderWithSameUIDExists.Error()})
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,11 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
fakeDash.FolderId = 1
|
fakeDash.FolderId = 1
|
||||||
fakeDash.HasAcl = false
|
fakeDash.HasAcl = false
|
||||||
|
|
||||||
|
var getDashboardQueries []*m.GetDashboardQuery
|
||||||
|
|
||||||
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
||||||
query.Result = fakeDash
|
query.Result = fakeDash
|
||||||
|
getDashboardQueries = append(getDashboardQueries, query)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -33,19 +36,40 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
Convey("When user is an Org Editor", func() {
|
Convey("When user is an Org Editor", func() {
|
||||||
role := m.ROLE_EDITOR
|
role := m.ROLE_EDITOR
|
||||||
|
|
||||||
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
|
callGetFolder(sc)
|
||||||
|
So(sc.resp.Code, ShouldEqual, 404)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
||||||
callGetFolder(sc)
|
callGetFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 404)
|
So(sc.resp.Code, ShouldEqual, 404)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by id", func() {
|
||||||
|
So(getDashboardQueries[0].Id, ShouldEqual, 1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
updateFolderScenario("When calling PUT on", "/api/folders/1", "/api/folders/:id", role, updateFolderCmd, func(sc *scenarioContext) {
|
updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
|
||||||
callUpdateFolder(sc)
|
callUpdateFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 404)
|
So(sc.resp.Code, ShouldEqual, 404)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
callDeleteFolder(sc)
|
callDeleteFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 404)
|
So(sc.resp.Code, ShouldEqual, 404)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -55,8 +79,11 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
fakeFolder.Id = 1
|
fakeFolder.Id = 1
|
||||||
fakeFolder.HasAcl = false
|
fakeFolder.HasAcl = false
|
||||||
|
|
||||||
|
var getDashboardQueries []*m.GetDashboardQuery
|
||||||
|
|
||||||
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
||||||
query.Result = fakeFolder
|
query.Result = fakeFolder
|
||||||
|
getDashboardQueries = append(getDashboardQueries, query)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -82,12 +109,20 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
Title: fakeFolder.Title,
|
Title: fakeFolder.Title,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateFolderCmd := m.UpdateFolderCommand{
|
||||||
|
Title: fakeFolder.Title,
|
||||||
|
}
|
||||||
|
|
||||||
Convey("When user is an Org Viewer", func() {
|
Convey("When user is an Org Viewer", func() {
|
||||||
role := m.ROLE_VIEWER
|
role := m.ROLE_VIEWER
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
folder := getFolderShouldReturn200(sc)
|
folder := getFolderShouldReturn200(sc)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
|
||||||
Convey("Should not be able to edit or save folder", func() {
|
Convey("Should not be able to edit or save folder", func() {
|
||||||
So(folder.CanEdit, ShouldBeFalse)
|
So(folder.CanEdit, ShouldBeFalse)
|
||||||
So(folder.CanSave, ShouldBeFalse)
|
So(folder.CanSave, ShouldBeFalse)
|
||||||
@ -95,23 +130,54 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
||||||
|
folder := getFolderShouldReturn200(sc)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by id", func() {
|
||||||
|
So(getDashboardQueries[0].Id, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Should not be able to edit or save folder", func() {
|
||||||
|
So(folder.CanEdit, ShouldBeFalse)
|
||||||
|
So(folder.CanSave, ShouldBeFalse)
|
||||||
|
So(folder.CanAdmin, ShouldBeFalse)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
callDeleteFolder(sc)
|
callDeleteFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
||||||
callCreateFolder(sc)
|
callCreateFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
|
||||||
|
callUpdateFolder(sc)
|
||||||
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("When user is an Org Editor", func() {
|
Convey("When user is an Org Editor", func() {
|
||||||
role := m.ROLE_EDITOR
|
role := m.ROLE_EDITOR
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
folder := getFolderShouldReturn200(sc)
|
folder := getFolderShouldReturn200(sc)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
|
||||||
Convey("Should be able to edit or save folder", func() {
|
Convey("Should be able to edit or save folder", func() {
|
||||||
So(folder.CanEdit, ShouldBeTrue)
|
So(folder.CanEdit, ShouldBeTrue)
|
||||||
So(folder.CanSave, ShouldBeTrue)
|
So(folder.CanSave, ShouldBeTrue)
|
||||||
@ -119,15 +185,42 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
||||||
|
folder := getFolderShouldReturn200(sc)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by id", func() {
|
||||||
|
So(getDashboardQueries[0].Id, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Should be able to edit or save folder", func() {
|
||||||
|
So(folder.CanEdit, ShouldBeTrue)
|
||||||
|
So(folder.CanSave, ShouldBeTrue)
|
||||||
|
So(folder.CanAdmin, ShouldBeFalse)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
callDeleteFolder(sc)
|
callDeleteFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 200)
|
So(sc.resp.Code, ShouldEqual, 200)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
||||||
callCreateFolder(sc)
|
callCreateFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 200)
|
So(sc.resp.Code, ShouldEqual, 200)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
|
||||||
|
callUpdateFolder(sc)
|
||||||
|
So(sc.resp.Code, ShouldEqual, 200)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -136,8 +229,11 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
fakeFolder.Id = 1
|
fakeFolder.Id = 1
|
||||||
fakeFolder.HasAcl = true
|
fakeFolder.HasAcl = true
|
||||||
|
|
||||||
|
var getDashboardQueries []*m.GetDashboardQuery
|
||||||
|
|
||||||
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
||||||
query.Result = fakeFolder
|
query.Result = fakeFolder
|
||||||
|
getDashboardQueries = append(getDashboardQueries, query)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -163,50 +259,110 @@ func TestFoldersApiEndpoint(t *testing.T) {
|
|||||||
Title: fakeFolder.Title,
|
Title: fakeFolder.Title,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateFolderCmd := m.UpdateFolderCommand{
|
||||||
|
Title: fakeFolder.Title,
|
||||||
|
}
|
||||||
|
|
||||||
Convey("When user is an Org Viewer and has no permissions for this folder", func() {
|
Convey("When user is an Org Viewer and has no permissions for this folder", func() {
|
||||||
role := m.ROLE_VIEWER
|
role := m.ROLE_VIEWER
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
sc.handlerFunc = GetFolderById
|
callGetFolder(sc)
|
||||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
|
||||||
Convey("Should be denied access", func() {
|
Convey("Should be denied access", func() {
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
||||||
|
callGetFolder(sc)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by id", func() {
|
||||||
|
So(getDashboardQueries[0].Id, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Should be denied access", func() {
|
||||||
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
callDeleteFolder(sc)
|
callDeleteFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
||||||
callCreateFolder(sc)
|
callCreateFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
|
||||||
|
callUpdateFolder(sc)
|
||||||
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("When user is an Org Editor and has no permissions for this folder", func() {
|
Convey("When user is an Org Editor and has no permissions for this folder", func() {
|
||||||
role := m.ROLE_EDITOR
|
role := m.ROLE_EDITOR
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
sc.handlerFunc = GetFolderById
|
callGetFolder(sc)
|
||||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
|
||||||
Convey("Should be denied access", func() {
|
Convey("Should be denied access", func() {
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/folders/1", "/api/folders/:id", role, func(sc *scenarioContext) {
|
||||||
|
callGetFolder(sc)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by id", func() {
|
||||||
|
So(getDashboardQueries[0].Id, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Should be denied access", func() {
|
||||||
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/folders/uid", "/api/folders/:uid", role, func(sc *scenarioContext) {
|
||||||
callDeleteFolder(sc)
|
callDeleteFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
createFolderScenario("When calling POST on", "/api/folders", "/api/folders", role, cmd, func(sc *scenarioContext) {
|
||||||
callCreateFolder(sc)
|
callCreateFolder(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 403)
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
updateFolderScenario("When calling PUT on", "/api/folders/uid", "/api/folders/:uid", role, updateFolderCmd, func(sc *scenarioContext) {
|
||||||
|
callUpdateFolder(sc)
|
||||||
|
So(sc.resp.Code, ShouldEqual, 403)
|
||||||
|
|
||||||
|
Convey("Should lookup folder by uid", func() {
|
||||||
|
So(getDashboardQueries[0].Uid, ShouldEqual, "uid")
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -224,7 +380,7 @@ func getFolderShouldReturn200(sc *scenarioContext) dtos.Folder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func callGetFolder(sc *scenarioContext) {
|
func callGetFolder(sc *scenarioContext) {
|
||||||
sc.handlerFunc = GetFolderById
|
sc.handlerFunc = GetFolder
|
||||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,14 +11,16 @@ var (
|
|||||||
ErrFolderNotFound = errors.New("Folder not found")
|
ErrFolderNotFound = errors.New("Folder not found")
|
||||||
ErrFolderVersionMismatch = errors.New("The folder has been changed by someone else")
|
ErrFolderVersionMismatch = errors.New("The folder has been changed by someone else")
|
||||||
ErrFolderTitleEmpty = errors.New("Folder title cannot be empty")
|
ErrFolderTitleEmpty = errors.New("Folder title cannot be empty")
|
||||||
ErrFolderWithSameUIDExists = errors.New("A folder with the same uid already exists")
|
ErrFolderWithSameUIDExists = errors.New("A folder/dashboard with the same uid already exists")
|
||||||
|
ErrFolderSameNameExists = errors.New("A folder or dashboard in the general folder with the same name already exists")
|
||||||
ErrFolderFailedGenerateUniqueUid = errors.New("Failed to generate unique folder id")
|
ErrFolderFailedGenerateUniqueUid = errors.New("Failed to generate unique folder id")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
Id int64
|
Id int64
|
||||||
|
Uid string
|
||||||
Title string
|
Title string
|
||||||
Slug string
|
Url string
|
||||||
OrgId int64
|
OrgId int64
|
||||||
Version int
|
Version int
|
||||||
|
|
||||||
@ -29,6 +32,45 @@ type Folder struct {
|
|||||||
HasAcl bool
|
HasAcl bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDashboardModel turns the command into the savable model
|
||||||
|
func (cmd *CreateFolderCommand) GetDashboardModel() *Dashboard {
|
||||||
|
dashFolder := NewDashboardFolder(strings.TrimSpace(cmd.Title))
|
||||||
|
dashFolder.OrgId = cmd.OrgId
|
||||||
|
dashFolder.Uid = strings.TrimSpace(cmd.Uid)
|
||||||
|
dashFolder.Data.Set("uid", cmd.Uid)
|
||||||
|
|
||||||
|
userId := cmd.UserId
|
||||||
|
|
||||||
|
if userId == 0 {
|
||||||
|
userId = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
dashFolder.CreatedBy = userId
|
||||||
|
dashFolder.UpdatedBy = userId
|
||||||
|
dashFolder.UpdateSlug()
|
||||||
|
|
||||||
|
return dashFolder
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDashboardModel updates an existing model from command into model for update
|
||||||
|
func (cmd *UpdateFolderCommand) UpdateDashboardModel(dashFolder *Dashboard) {
|
||||||
|
dashFolder.Title = strings.TrimSpace(cmd.Title)
|
||||||
|
dashFolder.Data.Set("title", cmd.Title)
|
||||||
|
dashFolder.Uid = dashFolder.Data.MustString("uid")
|
||||||
|
dashFolder.Data.Set("version", cmd.Version)
|
||||||
|
dashFolder.Version = cmd.Version
|
||||||
|
dashFolder.IsFolder = true
|
||||||
|
|
||||||
|
userId := cmd.UserId
|
||||||
|
|
||||||
|
if userId == 0 {
|
||||||
|
userId = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
dashFolder.UpdatedBy = userId
|
||||||
|
dashFolder.UpdateSlug()
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// COMMANDS
|
// COMMANDS
|
||||||
//
|
//
|
||||||
@ -36,16 +78,18 @@ type Folder struct {
|
|||||||
type CreateFolderCommand struct {
|
type CreateFolderCommand struct {
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
UserId int64 `json:"userId"`
|
UserId int64 `json:"userId"`
|
||||||
|
Uid string `json:"uid"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
|
||||||
Result *Folder
|
Result *Folder
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateFolderCommand struct {
|
type UpdateFolderCommand struct {
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
UserId int64 `json:"userId"`
|
UserId int64 `json:"userId"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Version int `json:"version"`
|
Version int `json:"version"`
|
||||||
|
Overwrite bool `json:"overwrite"`
|
||||||
|
|
||||||
Result *Folder
|
Result *Folder
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user