search: handle "permission" query param in search (#100607)

handle "permission" query param in search
This commit is contained in:
Will Assis 2025-02-13 13:35:53 -03:00 committed by GitHub
parent 6e4c1a57c1
commit 155492c8a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 31 additions and 18 deletions

View File

@ -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{

View File

@ -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
}

View File

@ -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,

View File

@ -457,6 +457,8 @@ message ResourceSearchRequest {
bool is_deleted = 10;
int64 page = 11;
int64 permission = 12;
}
message ResourceSearchResponse {

View File

@ -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)