소스 검색

dashboard and folder search with permissions

Torkel Ödegaard 7 년 전
부모
커밋
8e8f3c4332

+ 0 - 2
pkg/api/api.go

@@ -261,8 +261,6 @@ func (hs *HttpServer) registerRoutes() {
 			dashboardRoute.Get("/tags", GetDashboardTags)
 			dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), wrap(ImportDashboard))
 
-			dashboardRoute.Get("/folders", wrap(GetFoldersForSignedInUser))
-
 			dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute RouteRegister) {
 				dashIdRoute.Get("/versions", wrap(GetDashboardVersions))
 				dashIdRoute.Get("/versions/:id", wrap(GetDashboardVersion))

+ 0 - 16
pkg/api/dashboard.go

@@ -490,19 +490,3 @@ func GetDashboardTags(c *middleware.Context) {
 
 	c.JSON(200, query.Result)
 }
-
-func GetFoldersForSignedInUser(c *middleware.Context) Response {
-	title := c.Query("query")
-	query := m.GetFoldersForSignedInUserQuery{
-		OrgId:        c.OrgId,
-		SignedInUser: c.SignedInUser,
-		Title:        title,
-	}
-
-	err := bus.Dispatch(&query)
-	if err != nil {
-		return ApiError(500, "Failed to get folders from database", err)
-	}
-
-	return Json(200, query.Result)
-}

+ 7 - 0
pkg/api/search.go

@@ -6,6 +6,7 @@ import (
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/middleware"
+	"github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/search"
 )
 
@@ -15,11 +16,16 @@ func Search(c *middleware.Context) {
 	starred := c.Query("starred")
 	limit := c.QueryInt("limit")
 	dashboardType := c.Query("type")
+	permission := models.PERMISSION_VIEW
 
 	if limit == 0 {
 		limit = 1000
 	}
 
+	if c.Query("permission") == "Edit" {
+		permission = models.PERMISSION_EDIT
+	}
+
 	dbids := make([]int64, 0)
 	for _, id := range c.QueryStrings("dashboardIds") {
 		dashboardId, err := strconv.ParseInt(id, 10, 64)
@@ -46,6 +52,7 @@ func Search(c *middleware.Context) {
 		DashboardIds: dbids,
 		Type:         dashboardType,
 		FolderIds:    folderIds,
+		Permission:   permission,
 	}
 
 	err := bus.Dispatch(&searchQuery)

+ 0 - 12
pkg/models/dashboards.go

@@ -270,18 +270,6 @@ type GetDashboardsBySlugQuery struct {
 	Result []*Dashboard
 }
 
-type GetFoldersForSignedInUserQuery struct {
-	OrgId        int64
-	SignedInUser *SignedInUser
-	Title        string
-	Result       []*DashboardFolder
-}
-
-type DashboardFolder struct {
-	Id    int64  `json:"id"`
-	Title string `json:"title"`
-}
-
 type DashboardPermissionForUser struct {
 	DashboardId    int64          `json:"dashboardId"`
 	Permission     PermissionType `json:"permission"`

+ 1 - 0
pkg/services/search/handlers.go

@@ -21,6 +21,7 @@ func searchHandler(query *Query) error {
 		FolderIds:    query.FolderIds,
 		Tags:         query.Tags,
 		Limit:        query.Limit,
+		Permission:   query.Permission,
 	}
 
 	if err := bus.Dispatch(&dashQuery); err != nil {

+ 2 - 1
pkg/services/search/models.go

@@ -52,6 +52,7 @@ type Query struct {
 	Type         string
 	DashboardIds []int64
 	FolderIds    []int64
+	Permission   models.PermissionType
 
 	Result HitList
 }
@@ -66,7 +67,7 @@ type FindPersistedDashboardsQuery struct {
 	FolderIds    []int64
 	Tags         []string
 	Limit        int
-	IsBrowse     bool
+	Permission   models.PermissionType
 
 	Result HitList
 }

+ 3 - 50
pkg/services/sqlstore/dashboard.go

@@ -1,6 +1,7 @@
 package sqlstore
 
 import (
+	"fmt"
 	"strings"
 	"time"
 
@@ -21,7 +22,6 @@ func init() {
 	bus.AddHandler("sql", GetDashboardSlugById)
 	bus.AddHandler("sql", GetDashboardUIDById)
 	bus.AddHandler("sql", GetDashboardsByPluginId)
-	bus.AddHandler("sql", GetFoldersForSignedInUser)
 	bus.AddHandler("sql", GetDashboardPermissionsForUser)
 	bus.AddHandler("sql", GetDashboardsBySlug)
 }
@@ -256,7 +256,7 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear
 		limit = 1000
 	}
 
-	sb := NewSearchBuilder(query.SignedInUser, limit).
+	sb := NewSearchBuilder(query.SignedInUser, limit, query.Permission).
 		WithTags(query.Tags).
 		WithDashboardIdsIn(query.DashboardIds)
 
@@ -279,6 +279,7 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear
 	var res []DashboardSearchProjection
 
 	sql, params := sb.ToSql()
+	fmt.Printf("%s, %v", sql, params)
 	sqlog.Info("sql", "sql", sql, "params", params)
 	err := x.Sql(sql, params...).Find(&res)
 	if err != nil {
@@ -358,54 +359,6 @@ func GetDashboardTags(query *m.GetDashboardTagsQuery) error {
 	return err
 }
 
-func GetFoldersForSignedInUser(query *m.GetFoldersForSignedInUserQuery) error {
-	query.Result = make([]*m.DashboardFolder, 0)
-	var err error
-
-	if query.SignedInUser.OrgRole == m.ROLE_ADMIN {
-		sql := `SELECT distinct d.id, d.title
-		FROM dashboard AS d WHERE d.is_folder = ? AND d.org_id = ?
-		ORDER BY d.title ASC`
-
-		err = x.Sql(sql, dialect.BooleanStr(true), query.OrgId).Find(&query.Result)
-	} else {
-		params := make([]interface{}, 0)
-		sql := `SELECT distinct d.id, d.title
-		FROM dashboard AS d
-			LEFT JOIN dashboard_acl AS da ON d.id = da.dashboard_id
-			LEFT JOIN team_member AS ugm ON ugm.team_id =  da.team_id
-			LEFT JOIN org_user ou ON ou.role = da.role AND ou.user_id = ?
-			LEFT JOIN org_user ouRole ON ouRole.role = 'Editor' AND ouRole.user_id = ? AND ouRole.org_id = ?`
-		params = append(params, query.SignedInUser.UserId)
-		params = append(params, query.SignedInUser.UserId)
-		params = append(params, query.OrgId)
-
-		sql += ` WHERE
-			d.org_id = ? AND
-			d.is_folder = ? AND
-			(
-				(d.has_acl = ? AND da.permission > 1 AND (da.user_id = ? OR ugm.user_id = ? OR ou.id IS NOT NULL))
-				OR (d.has_acl = ? AND ouRole.id IS NOT NULL)
-			)`
-		params = append(params, query.OrgId)
-		params = append(params, dialect.BooleanStr(true))
-		params = append(params, dialect.BooleanStr(true))
-		params = append(params, query.SignedInUser.UserId)
-		params = append(params, query.SignedInUser.UserId)
-		params = append(params, dialect.BooleanStr(false))
-
-		if len(query.Title) > 0 {
-			sql += " AND d.title " + dialect.LikeStr() + " ?"
-			params = append(params, "%"+query.Title+"%")
-		}
-
-		sql += ` ORDER BY d.title ASC`
-		err = x.Sql(sql, params...).Find(&query.Result)
-	}
-
-	return err
-}
-
 func DeleteDashboard(cmd *m.DeleteDashboardCommand) error {
 	return inTransaction(func(sess *DBSession) error {
 		dashboard := m.Dashboard{Id: cmd.Id, OrgId: cmd.OrgId}

+ 15 - 11
pkg/services/sqlstore/dashboard_folder_test.go

@@ -227,12 +227,14 @@ func TestDashboardFolderDataAccess(t *testing.T) {
 
 			Convey("Admin users", func() {
 				Convey("Should have write access to all dashboard folders in their org", func() {
-					query := m.GetFoldersForSignedInUserQuery{
+					query := search.FindPersistedDashboardsQuery{
 						OrgId:        1,
-						SignedInUser: &m.SignedInUser{UserId: adminUser.Id, OrgRole: m.ROLE_ADMIN},
+						SignedInUser: &m.SignedInUser{UserId: adminUser.Id, OrgRole: m.ROLE_ADMIN, OrgId: 1},
+						Permission:   m.PERMISSION_VIEW,
+						Type:         "dash-folder",
 					}
 
-					err := GetFoldersForSignedInUser(&query)
+					err := SearchDashboards(&query)
 					So(err, ShouldBeNil)
 
 					So(len(query.Result), ShouldEqual, 2)
@@ -260,13 +262,14 @@ func TestDashboardFolderDataAccess(t *testing.T) {
 			})
 
 			Convey("Editor users", func() {
-				query := m.GetFoldersForSignedInUserQuery{
+				query := search.FindPersistedDashboardsQuery{
 					OrgId:        1,
-					SignedInUser: &m.SignedInUser{UserId: editorUser.Id, OrgRole: m.ROLE_EDITOR},
+					SignedInUser: &m.SignedInUser{UserId: editorUser.Id, OrgRole: m.ROLE_EDITOR, OrgId: 1},
+					Permission:   m.PERMISSION_EDIT,
 				}
 
 				Convey("Should have write access to all dashboard folders with default ACL", func() {
-					err := GetFoldersForSignedInUser(&query)
+					err := SearchDashboards(&query)
 					So(err, ShouldBeNil)
 
 					So(len(query.Result), ShouldEqual, 2)
@@ -295,7 +298,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
 				Convey("Should have write access to one dashboard folder if default role changed to view for one folder", func() {
 					updateTestDashboardWithAcl(folder1.Id, editorUser.Id, m.PERMISSION_VIEW)
 
-					err := GetFoldersForSignedInUser(&query)
+					err := SearchDashboards(&query)
 					So(err, ShouldBeNil)
 
 					So(len(query.Result), ShouldEqual, 1)
@@ -305,13 +308,14 @@ func TestDashboardFolderDataAccess(t *testing.T) {
 			})
 
 			Convey("Viewer users", func() {
-				query := m.GetFoldersForSignedInUserQuery{
+				query := search.FindPersistedDashboardsQuery{
 					OrgId:        1,
-					SignedInUser: &m.SignedInUser{UserId: viewerUser.Id, OrgRole: m.ROLE_VIEWER},
+					SignedInUser: &m.SignedInUser{UserId: viewerUser.Id, OrgRole: m.ROLE_VIEWER, OrgId: 1},
+					Permission:   m.PERMISSION_EDIT,
 				}
 
 				Convey("Should have no write access to any dashboard folders with default ACL", func() {
-					err := GetFoldersForSignedInUser(&query)
+					err := SearchDashboards(&query)
 					So(err, ShouldBeNil)
 
 					So(len(query.Result), ShouldEqual, 0)
@@ -338,7 +342,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
 				Convey("Should be able to get one dashboard folder if default role changed to edit for one folder", func() {
 					updateTestDashboardWithAcl(folder1.Id, viewerUser.Id, m.PERMISSION_EDIT)
 
-					err := GetFoldersForSignedInUser(&query)
+					err := SearchDashboards(&query)
 					So(err, ShouldBeNil)
 
 					So(len(query.Result), ShouldEqual, 1)

+ 4 - 2
pkg/services/sqlstore/search_builder.go

@@ -18,12 +18,14 @@ type SearchBuilder struct {
 	whereTypeFolder     bool
 	whereTypeDash       bool
 	whereFolderIds      []int64
+	permission          m.PermissionType
 }
 
-func NewSearchBuilder(signedInUser *m.SignedInUser, limit int) *SearchBuilder {
+func NewSearchBuilder(signedInUser *m.SignedInUser, limit int, permission m.PermissionType) *SearchBuilder {
 	searchBuilder := &SearchBuilder{
 		signedInUser: signedInUser,
 		limit:        limit,
+		permission:   permission,
 	}
 
 	return searchBuilder
@@ -174,7 +176,7 @@ func (sb *SearchBuilder) buildSearchWhereClause() {
 		}
 	}
 
-	sb.writeDashboardPermissionFilter(sb.signedInUser, m.PERMISSION_VIEW)
+	sb.writeDashboardPermissionFilter(sb.signedInUser, sb.permission)
 
 	if len(sb.whereTitle) > 0 {
 		sb.sql.WriteString(" AND dashboard.title " + dialect.LikeStr() + " ?")

+ 2 - 1
pkg/services/sqlstore/search_builder_test.go

@@ -16,7 +16,8 @@ func TestSearchBuilder(t *testing.T) {
 			OrgId:  1,
 			UserId: 1,
 		}
-		sb := NewSearchBuilder(signedInUser, 1000)
+
+		sb := NewSearchBuilder(signedInUser, 1000, m.PERMISSION_VIEW)
 
 		Convey("When building a normal search", func() {
 			sql, params := sb.IsStarred().WithTitle("test").ToSql()

+ 2 - 2
pkg/services/sqlstore/sqlbuilder.go

@@ -12,7 +12,7 @@ type SqlBuilder struct {
 	params []interface{}
 }
 
-func (sb *SqlBuilder) writeDashboardPermissionFilter(user *m.SignedInUser, minPermission m.PermissionType) {
+func (sb *SqlBuilder) writeDashboardPermissionFilter(user *m.SignedInUser, permission m.PermissionType) {
 
 	if user.OrgRole == m.ROLE_ADMIN {
 		return
@@ -40,6 +40,6 @@ func (sb *SqlBuilder) writeDashboardPermissionFilter(user *m.SignedInUser, minPe
 		)
 	)`)
 
-	sb.params = append(sb.params, user.OrgId, minPermission, user.UserId, user.UserId)
+	sb.params = append(sb.params, user.OrgId, permission, user.UserId, user.UserId)
 	sb.params = append(sb.params, okRoles...)
 }

+ 7 - 1
public/app/features/dashboard/folder_picker/folder_picker.ts

@@ -30,7 +30,13 @@ export class FolderPickerCtrl {
   }
 
   getOptions(query) {
-    return this.backendSrv.get('api/dashboards/folders', { query: query }).then(result => {
+    const params = {
+      query: query,
+      type: 'dash-folder',
+      permission: 'Edit',
+    };
+
+    return this.backendSrv.get('api/search', params).then(result => {
       if (
         query === '' ||
         query.toLowerCase() === 'g' ||