Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9db1f4079 | |||
| 69ccfd6bfc |
@@ -618,10 +618,6 @@ export interface FeatureToggles {
|
||||
*/
|
||||
exploreLogsShardSplitting?: boolean;
|
||||
/**
|
||||
* Used in Logs Drilldown to query by aggregated metrics
|
||||
*/
|
||||
exploreLogsAggregatedMetrics?: boolean;
|
||||
/**
|
||||
* Used in Logs Drilldown to limit the time range
|
||||
*/
|
||||
exploreLogsLimitedTimeRange?: boolean;
|
||||
|
||||
@@ -552,6 +552,7 @@ func (s *SearchHandler) getDashboardsUIDsSharedWithUser(ctx context.Context, use
|
||||
// gets dashboards that the user was granted read access to
|
||||
permissions := user.GetPermissions()
|
||||
dashboardPermissions := permissions[dashboards.ActionDashboardsRead]
|
||||
folderPermissions := permissions[dashboards.ActionFoldersRead]
|
||||
dashboardUids := make([]string, 0)
|
||||
sharedDashboards := make([]string, 0)
|
||||
|
||||
@@ -562,6 +563,13 @@ func (s *SearchHandler) getDashboardsUIDsSharedWithUser(ctx context.Context, use
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, folderPermission := range folderPermissions {
|
||||
if folderUid, found := strings.CutPrefix(folderPermission, dashboards.ScopeFoldersPrefix); found {
|
||||
if !slices.Contains(dashboardUids, folderUid) && folderUid != foldermodel.SharedWithMeFolderUID && folderUid != foldermodel.GeneralFolderUID {
|
||||
dashboardUids = append(dashboardUids, folderUid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(dashboardUids) == 0 {
|
||||
return sharedDashboards, nil
|
||||
@@ -572,9 +580,15 @@ func (s *SearchHandler) getDashboardsUIDsSharedWithUser(ctx context.Context, use
|
||||
return sharedDashboards, err
|
||||
}
|
||||
|
||||
folderKey, err := asResourceKey(user.GetNamespace(), folders.RESOURCE)
|
||||
if err != nil {
|
||||
return sharedDashboards, err
|
||||
}
|
||||
|
||||
dashboardSearchRequest := &resourcepb.ResourceSearchRequest{
|
||||
Fields: []string{"folder"},
|
||||
Limit: int64(len(dashboardUids)),
|
||||
Federated: []*resourcepb.ResourceKey{folderKey},
|
||||
Fields: []string{"folder"},
|
||||
Limit: int64(len(dashboardUids)),
|
||||
Options: &resourcepb.ListOptions{
|
||||
Key: key,
|
||||
Fields: []*resourcepb.Requirement{{
|
||||
@@ -610,12 +624,6 @@ func (s *SearchHandler) getDashboardsUIDsSharedWithUser(ctx context.Context, use
|
||||
}
|
||||
}
|
||||
|
||||
// only folders the user has access to will be returned here
|
||||
folderKey, err := asResourceKey(user.GetNamespace(), folders.RESOURCE)
|
||||
if err != nil {
|
||||
return sharedDashboards, err
|
||||
}
|
||||
|
||||
folderSearchRequest := &resourcepb.ResourceSearchRequest{
|
||||
Fields: []string{"folder"},
|
||||
Limit: int64(len(allFolders)),
|
||||
@@ -628,6 +636,7 @@ func (s *SearchHandler) getDashboardsUIDsSharedWithUser(ctx context.Context, use
|
||||
}},
|
||||
},
|
||||
}
|
||||
// only folders the user has access to will be returned here
|
||||
foldersResult, err := s.client.Search(ctx, folderSearchRequest)
|
||||
if err != nil {
|
||||
return sharedDashboards, err
|
||||
|
||||
@@ -507,6 +507,15 @@ func TestSearchHandlerSharedDashboards(t *testing.T) {
|
||||
[]byte("publicfolder"), // folder uid
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &resourcepb.ResourceKey{
|
||||
Name: "sharedfolder",
|
||||
Resource: "folder",
|
||||
},
|
||||
Cells: [][]byte{
|
||||
[]byte("privatefolder"), // folder uid
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -550,6 +559,15 @@ func TestSearchHandlerSharedDashboards(t *testing.T) {
|
||||
[]byte("privatefolder"), // folder uid
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &resourcepb.ResourceKey{
|
||||
Name: "sharedfolder",
|
||||
Resource: "folder",
|
||||
},
|
||||
Cells: [][]byte{
|
||||
[]byte("privatefolder"), // folder uid
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -571,6 +589,7 @@ func TestSearchHandlerSharedDashboards(t *testing.T) {
|
||||
allPermissions := make(map[int64]map[string][]string)
|
||||
permissions := make(map[string][]string)
|
||||
permissions[dashboards.ActionDashboardsRead] = []string{"dashboards:uid:dashboardinroot", "dashboards:uid:dashboardinprivatefolder", "dashboards:uid:dashboardinpublicfolder"}
|
||||
permissions[dashboards.ActionFoldersRead] = []string{"folders:uid:sharedfolder"}
|
||||
allPermissions[1] = permissions
|
||||
// "Permissions" is where we store the uid of dashboards shared with the user
|
||||
req = req.WithContext(identity.WithRequester(req.Context(), &user.SignedInUser{Namespace: "test", OrgID: 1, Permissions: allPermissions}))
|
||||
@@ -581,14 +600,19 @@ func TestSearchHandlerSharedDashboards(t *testing.T) {
|
||||
|
||||
// first call gets all dashboards user has permission for
|
||||
firstCall := mockClient.MockCalls[0]
|
||||
assert.Equal(t, firstCall.Options.Fields[0].Values, []string{"dashboardinroot", "dashboardinprivatefolder", "dashboardinpublicfolder"})
|
||||
assert.Equal(t, firstCall.Options.Fields[0].Values, []string{"dashboardinroot", "dashboardinprivatefolder", "dashboardinpublicfolder", "sharedfolder"})
|
||||
// verify federated field is set to include folders
|
||||
assert.NotNil(t, firstCall.Federated)
|
||||
assert.Equal(t, 1, len(firstCall.Federated))
|
||||
assert.Equal(t, "folder.grafana.app", firstCall.Federated[0].Group)
|
||||
assert.Equal(t, "folders", firstCall.Federated[0].Resource)
|
||||
// second call gets folders associated with the previous dashboards
|
||||
secondCall := mockClient.MockCalls[1]
|
||||
assert.Equal(t, secondCall.Options.Fields[0].Values, []string{"privatefolder", "publicfolder"})
|
||||
// lastly, search ONLY for dashboards user has permission to read that are within folders the user does NOT have
|
||||
// lastly, search ONLY for dashboards and folders user has permission to read that are within folders the user does NOT have
|
||||
// permission to read
|
||||
thirdCall := mockClient.MockCalls[2]
|
||||
assert.Equal(t, thirdCall.Options.Fields[0].Values, []string{"dashboardinprivatefolder"})
|
||||
assert.Equal(t, thirdCall.Options.Fields[0].Values, []string{"dashboardinprivatefolder", "sharedfolder"})
|
||||
|
||||
resp := rr.Result()
|
||||
defer func() {
|
||||
|
||||
@@ -1024,13 +1024,6 @@ var (
|
||||
FrontendOnly: true,
|
||||
Owner: grafanaObservabilityLogsSquad,
|
||||
},
|
||||
{
|
||||
Name: "exploreLogsAggregatedMetrics",
|
||||
Description: "Used in Logs Drilldown to query by aggregated metrics",
|
||||
Stage: FeatureStageExperimental,
|
||||
FrontendOnly: true,
|
||||
Owner: grafanaObservabilityLogsSquad,
|
||||
},
|
||||
{
|
||||
Name: "exploreLogsLimitedTimeRange",
|
||||
Description: "Used in Logs Drilldown to limit the time range",
|
||||
|
||||
Generated
-1
@@ -141,7 +141,6 @@ newFiltersUI,GA,@grafana/dashboards-squad,false,false,false
|
||||
vizActionsAuth,preview,@grafana/dataviz-squad,false,false,true
|
||||
alertingPrometheusRulesPrimary,experimental,@grafana/alerting-squad,false,false,true
|
||||
exploreLogsShardSplitting,experimental,@grafana/observability-logs,false,false,true
|
||||
exploreLogsAggregatedMetrics,experimental,@grafana/observability-logs,false,false,true
|
||||
exploreLogsLimitedTimeRange,experimental,@grafana/observability-logs,false,false,true
|
||||
appPlatformGrpcClientAuth,experimental,@grafana/identity-access-team,false,false,false
|
||||
groupAttributeSync,privatePreview,@grafana/identity-access-team,false,false,false
|
||||
|
||||
|
+2
-1
@@ -1369,7 +1369,8 @@
|
||||
"metadata": {
|
||||
"name": "exploreLogsAggregatedMetrics",
|
||||
"resourceVersion": "1764664939750",
|
||||
"creationTimestamp": "2024-08-29T13:55:59Z"
|
||||
"creationTimestamp": "2024-08-29T13:55:59Z",
|
||||
"deletionTimestamp": "2026-01-12T22:13:12Z"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Used in Logs Drilldown to query by aggregated metrics",
|
||||
|
||||
Reference in New Issue
Block a user