fix (unified-storage): Fix error when trying to get parents of folder as a viewer (#101245)

* Fix error when trying to get parents of folder as a viewer with unified-storage enabled
pull/101295/head
Will Assis 5 months ago committed by GitHub
parent ce8a874bf0
commit 1a65154e74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      pkg/services/folder/folderimpl/unifiedstore.go
  2. 87
      pkg/services/folder/folderimpl/unifiedstore_test.go

@ -2,7 +2,9 @@ package folderimpl
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@ -144,6 +146,12 @@ func (ss *FolderUnifiedStoreImpl) GetParents(ctx context.Context, q folder.GetPa
for parentUid != "" {
out, err := ss.k8sclient.Get(ctx, parentUid, q.OrgID, v1.GetOptions{})
if err != nil {
var statusError *apierrors.StatusError
if errors.As(err, &statusError) && statusError.ErrStatus.Code == http.StatusForbidden {
// If we get a Forbidden error when requesting the parent folder, it means the user does not have access
// to it, nor its parents. So we can stop looping
break
}
return nil, err
}

@ -2,6 +2,7 @@ package folderimpl
import (
"context"
"net/http"
"testing"
claims "github.com/grafana/authlib/types"
@ -12,6 +13,8 @@ import (
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/selection"
)
@ -85,6 +88,90 @@ func TestComputeFullPath(t *testing.T) {
}
}
func TestGetParents(t *testing.T) {
mockCli := new(client.MockK8sHandler)
store := FolderUnifiedStoreImpl{
k8sclient: mockCli,
}
ctx := context.Background()
orgID := int64(1)
t.Run("should return list of parent folders of a given folder uid", func(t *testing.T) {
mockCli.On("Get", mock.Anything, "parentone", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "parentone",
"annotations": map[string]interface{}{"grafana.app/folder": "parenttwo"},
},
},
}, nil).Once()
mockCli.On("Get", mock.Anything, "parenttwo", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "parenttwo",
"annotations": map[string]interface{}{"grafana.app/folder": "parentthree"},
},
},
}, nil).Once()
mockCli.On("Get", mock.Anything, "parentthree", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "parentthree",
"annotations": map[string]interface{}{"grafana.app/folder": "parentfour"},
},
},
}, nil).Once()
mockCli.On("Get", mock.Anything, "parentfour", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "parentfour",
},
},
}, nil).Once()
result, err := store.GetParents(ctx, folder.GetParentsQuery{
UID: "parentone",
OrgID: orgID,
})
require.NoError(t, err)
require.Len(t, result, 3)
require.Equal(t, "parentfour", result[0].UID)
require.Equal(t, "parentthree", result[1].UID)
require.Equal(t, "parenttwo", result[2].UID)
})
t.Run("should stop if user doesnt have access to the parent folder", func(t *testing.T) {
mockCli.On("Get", mock.Anything, "parentone", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "parentone",
"annotations": map[string]interface{}{"grafana.app/folder": "parenttwo"},
},
},
}, nil).Once()
mockCli.On("Get", mock.Anything, "parenttwo", orgID, mock.Anything, mock.Anything).Return(&unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "parenttwo",
"annotations": map[string]interface{}{"grafana.app/folder": "parentthree"},
},
},
}, nil).Once()
mockCli.On("Get", mock.Anything, "parentthree", orgID, mock.Anything, mock.Anything).Return(nil, &apierrors.StatusError{
ErrStatus: metav1.Status{Code: http.StatusForbidden},
}).Once()
result, err := store.GetParents(ctx, folder.GetParentsQuery{
UID: "parentone",
OrgID: orgID,
})
require.NoError(t, err)
require.Len(t, result, 1)
require.Equal(t, "parenttwo", result[0].UID)
})
}
func TestGetChildren(t *testing.T) {
mockCli := new(client.MockK8sHandler)
store := FolderUnifiedStoreImpl{

Loading…
Cancel
Save