diff --git a/pkg/registry/apis/dashboard/legacysearcher/search_client.go b/pkg/registry/apis/dashboard/legacysearcher/search_client.go index bd2e4a896a8..c0e18288ea5 100644 --- a/pkg/registry/apis/dashboard/legacysearcher/search_client.go +++ b/pkg/registry/apis/dashboard/legacysearcher/search_client.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/apis/dashboard" folderv0alpha1 "github.com/grafana/grafana/pkg/apis/folder/v0alpha1" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/storage/unified/resource" @@ -40,9 +41,6 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resource.Resour req.Query = strings.ReplaceAll(req.Query, "*", "") } - // TODO add missing support for the following query params: - // - folderIds (won't support, must use folderUIDs) - // - permission query := &dashboards.FindPersistedDashboardsQuery{ Title: req.Query, Limit: req.Limit, @@ -51,6 +49,10 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resource.Resour IsDeleted: req.IsDeleted, } + if req.Permission == int64(dashboardaccess.PERMISSION_EDIT) { + query.Permission = dashboardaccess.PERMISSION_EDIT + } + var queryType string if req.Options.Key.Resource == dashboard.DASHBOARD_RESOURCE { queryType = searchstore.TypeDashboard @@ -123,22 +125,11 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resource.Resour } } - // TODO need to test this - // emptyResponse, err := a.dashService.GetSharedDashboardUIDsQuery(ctx, query) - - // if err != nil { - // return nil, err - // } else if emptyResponse { - // return nil, nil - // } - res, err := c.dashboardStore.FindDashboards(ctx, query) if err != nil { return nil, err } - // TODO sort if query.Sort == "" see sortedHits in services/search/service.go - searchFields := resource.StandardSearchFields() list := &resource.ResourceSearchResponse{ Results: &resource.ResourceTable{ diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 3964922fcda..ed8a8fa1d19 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -1755,6 +1755,10 @@ func (dr *DashboardServiceImpl) searchDashboardsThroughK8sRaw(ctx context.Contex request.IsDeleted = query.IsDeleted } + if query.Permission > 0 { + request.Permission = int64(query.Permission) + } + if query.Limit < 1 { query.Limit = 1000 } diff --git a/pkg/storage/unified/resource/resource.pb.go b/pkg/storage/unified/resource/resource.pb.go index ee8801f361b..dc6593d385f 100644 --- a/pkg/storage/unified/resource/resource.pb.go +++ b/pkg/storage/unified/resource/resource.pb.go @@ -2016,6 +2016,7 @@ type ResourceSearchRequest struct { Explain bool `protobuf:"varint,9,opt,name=explain,proto3" json:"explain,omitempty"` IsDeleted bool `protobuf:"varint,10,opt,name=is_deleted,json=isDeleted,proto3" json:"is_deleted,omitempty"` Page int64 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"` + Permission int64 `protobuf:"varint,12,opt,name=permission,proto3" json:"permission,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2127,6 +2128,13 @@ func (x *ResourceSearchRequest) GetPage() int64 { return 0 } +func (x *ResourceSearchRequest) GetPermission() int64 { + if x != nil { + return x.Permission + } + return 0 +} + type ResourceSearchResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Error details @@ -4238,8 +4246,8 @@ var file_resource_proto_rawDesc = string([]byte{ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xee, - 0x04, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x8e, + 0x05, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, @@ -4265,7 +4273,9 @@ var file_resource_proto_rawDesc = string([]byte{ 0x6c, 0x61, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x1a, 0x30, 0x0a, 0x04, 0x53, 0x6f, 0x72, 0x74, 0x12, + 0x03, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x70, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x30, 0x0a, 0x04, 0x53, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x1a, 0x33, 0x0a, 0x05, 0x46, 0x61, 0x63, diff --git a/pkg/storage/unified/resource/resource.proto b/pkg/storage/unified/resource/resource.proto index f16f194d360..c11ed29f259 100644 --- a/pkg/storage/unified/resource/resource.proto +++ b/pkg/storage/unified/resource/resource.proto @@ -457,6 +457,8 @@ message ResourceSearchRequest { bool is_deleted = 10; int64 page = 11; + + int64 permission = 12; } message ResourceSearchResponse { diff --git a/pkg/storage/unified/search/bleve.go b/pkg/storage/unified/search/bleve.go index bf9748cf5bc..2b76bb97529 100644 --- a/pkg/storage/unified/search/bleve.go +++ b/pkg/storage/unified/search/bleve.go @@ -18,6 +18,7 @@ import ( "github.com/blevesearch/bleve/v2/search/query" bleveSearch "github.com/blevesearch/bleve/v2/search/searcher" index "github.com/blevesearch/bleve_index_api" + "github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" "github.com/grafana/grafana/pkg/services/featuremgmt" "go.opentelemetry.io/otel/trace" "k8s.io/apimachinery/pkg/selection" @@ -611,11 +612,16 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resource.Res if !ok { return nil, resource.AsErrorResult(fmt.Errorf("missing auth info")) } + verb := utils.VerbList + if req.Permission == int64(dashboardaccess.PERMISSION_EDIT) { + verb = utils.VerbPatch + } + checker, err := access.Compile(ctx, auth, authlib.ListRequest{ Namespace: b.key.Namespace, Group: b.key.Group, Resource: b.key.Resource, - Verb: utils.VerbList, + Verb: verb, }) if err != nil { return nil, resource.AsErrorResult(err)