2022-03-10 12:19:50 -05:00
|
|
|
package dashboards
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
"math/rand"
|
|
|
|
|
"testing"
|
|
|
|
|
|
2023-01-26 10:21:10 +02:00
|
|
|
"github.com/google/go-cmp/cmp"
|
2022-03-10 12:19:50 -05:00
|
|
|
"github.com/stretchr/testify/mock"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
|
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
2022-11-11 14:28:24 +01:00
|
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
2023-01-26 10:21:10 +02:00
|
|
|
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
2022-03-10 12:19:50 -05:00
|
|
|
"github.com/grafana/grafana/pkg/util"
|
|
|
|
|
)
|
|
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
func TestNewFolderNameScopeResolver(t *testing.T) {
|
2022-03-10 12:19:50 -05:00
|
|
|
t.Run("prefix should be expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
prefix, _ := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-10 12:19:50 -05:00
|
|
|
require.Equal(t, "folders:name:", prefix)
|
|
|
|
|
})
|
|
|
|
|
|
2022-03-30 15:14:26 +02:00
|
|
|
t.Run("resolver should convert to uid scope", func(t *testing.T) {
|
2022-03-10 12:19:50 -05:00
|
|
|
orgId := rand.Int63()
|
|
|
|
|
title := "Very complex :title with: and /" + util.GenerateShortUID()
|
2024-01-12 16:43:39 +01:00
|
|
|
db := &folder.Folder{Title: title, UID: util.GenerateShortUID()}
|
2023-03-03 15:56:33 +00:00
|
|
|
folderStore := foldertest.NewFakeFolderStore(t)
|
2024-01-25 11:29:56 +02:00
|
|
|
folderStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
2022-03-10 12:19:50 -05:00
|
|
|
|
|
|
|
|
scope := "folders:name:" + title
|
|
|
|
|
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewFolderNameScopeResolver(folderStore, foldertest.NewFakeService())
|
2022-05-02 09:29:30 +02:00
|
|
|
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
2022-03-10 12:19:50 -05:00
|
|
|
require.NoError(t, err)
|
2022-05-02 09:29:30 +02:00
|
|
|
require.Len(t, resolvedScopes, 1)
|
2022-11-11 14:28:24 +01:00
|
|
|
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.UID), resolvedScopes[0])
|
2024-01-25 11:29:56 +02:00
|
|
|
folderStore.AssertCalled(t, "GetFolderByTitle", mock.Anything, orgId, title, mock.Anything)
|
2022-03-10 12:19:50 -05:00
|
|
|
})
|
2023-01-26 10:21:10 +02:00
|
|
|
t.Run("resolver should include inherited scopes if any", func(t *testing.T) {
|
|
|
|
|
orgId := rand.Int63()
|
|
|
|
|
title := "Very complex :title with: and /" + util.GenerateShortUID()
|
2023-03-03 15:56:33 +00:00
|
|
|
|
2024-01-12 16:43:39 +01:00
|
|
|
db := &folder.Folder{Title: title, UID: util.GenerateShortUID()}
|
2023-03-03 15:56:33 +00:00
|
|
|
|
|
|
|
|
folderStore := foldertest.NewFakeFolderStore(t)
|
2024-01-25 11:29:56 +02:00
|
|
|
folderStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
2023-03-03 15:56:33 +00:00
|
|
|
|
2023-01-26 10:21:10 +02:00
|
|
|
scope := "folders:name:" + title
|
|
|
|
|
|
|
|
|
|
folderSvc := foldertest.NewFakeService()
|
|
|
|
|
folderSvc.ExpectedFolders = []*folder.Folder{
|
|
|
|
|
{
|
|
|
|
|
UID: "parent",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
UID: "grandparent",
|
|
|
|
|
},
|
|
|
|
|
}
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewFolderNameScopeResolver(folderStore, folderSvc)
|
2023-01-26 10:21:10 +02:00
|
|
|
|
|
|
|
|
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, resolvedScopes, 3)
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff([]string{
|
2023-03-03 15:56:33 +00:00
|
|
|
fmt.Sprintf("folders:uid:%v", db.UID),
|
2023-01-26 10:21:10 +02:00
|
|
|
"folders:uid:parent",
|
|
|
|
|
"folders:uid:grandparent",
|
|
|
|
|
}, resolvedScopes); diff != "" {
|
|
|
|
|
t.Errorf("Result mismatch (-want +got):\n%s", diff)
|
|
|
|
|
}
|
2023-03-03 15:56:33 +00:00
|
|
|
|
2024-01-25 11:29:56 +02:00
|
|
|
folderStore.AssertCalled(t, "GetFolderByTitle", mock.Anything, orgId, title, mock.Anything)
|
2023-01-26 10:21:10 +02:00
|
|
|
})
|
2022-03-10 12:19:50 -05:00
|
|
|
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-10 12:19:50 -05:00
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:123")
|
2022-03-10 12:19:50 -05:00
|
|
|
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
|
|
|
|
})
|
|
|
|
|
t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-10 12:19:50 -05:00
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:name:")
|
2022-03-10 12:19:50 -05:00
|
|
|
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
|
|
|
|
})
|
|
|
|
|
t.Run("returns 'not found' if folder does not exist", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
folderStore := foldertest.NewFakeFolderStore(t)
|
|
|
|
|
_, resolver := NewFolderNameScopeResolver(folderStore, foldertest.NewFakeService())
|
2022-03-10 12:19:50 -05:00
|
|
|
|
|
|
|
|
orgId := rand.Int63()
|
2024-01-25 11:29:56 +02:00
|
|
|
folderStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
2022-03-10 12:19:50 -05:00
|
|
|
|
|
|
|
|
scope := "folders:name:" + util.GenerateShortUID()
|
|
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
2022-06-30 09:31:54 -04:00
|
|
|
require.ErrorIs(t, err, ErrDashboardNotFound)
|
2022-05-02 09:29:30 +02:00
|
|
|
require.Nil(t, resolvedScopes)
|
2022-03-10 12:19:50 -05:00
|
|
|
})
|
|
|
|
|
}
|
2022-03-15 10:37:16 -04:00
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
func TestNewFolderIDScopeResolver(t *testing.T) {
|
2022-03-15 10:37:16 -04:00
|
|
|
t.Run("prefix should be expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
prefix, _ := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-30 15:14:26 +02:00
|
|
|
require.Equal(t, "folders:id:", prefix)
|
2022-03-15 10:37:16 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-15 10:37:16 -04:00
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:uid:123")
|
2022-03-15 10:37:16 -04:00
|
|
|
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
|
|
|
|
})
|
2022-03-30 15:14:26 +02:00
|
|
|
|
|
|
|
|
t.Run("resolver should convert id 0 to general uid scope", func(t *testing.T) {
|
|
|
|
|
var (
|
2023-03-02 08:09:57 -05:00
|
|
|
orgId = rand.Int63()
|
|
|
|
|
scope = "folders:id:0"
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver = NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-30 15:14:26 +02:00
|
|
|
)
|
|
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
resolved, err := resolver.Resolve(context.Background(), orgId, scope)
|
2022-03-30 15:14:26 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
require.Len(t, resolved, 1)
|
|
|
|
|
require.Equal(t, "folders:uid:general", resolved[0])
|
2022-03-30 15:14:26 +02:00
|
|
|
})
|
|
|
|
|
|
2022-03-15 10:37:16 -04:00
|
|
|
t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
2022-03-15 10:37:16 -04:00
|
|
|
|
2022-05-02 09:29:30 +02:00
|
|
|
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:")
|
2022-03-15 10:37:16 -04:00
|
|
|
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
|
|
|
|
})
|
|
|
|
|
t.Run("returns 'not found' if folder does not exist", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
folderStore := foldertest.NewFakeFolderStore(t)
|
|
|
|
|
folderStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
|
|
|
|
_, resolver := NewFolderIDScopeResolver(folderStore, foldertest.NewFakeService())
|
2022-03-15 10:37:16 -04:00
|
|
|
|
|
|
|
|
orgId := rand.Int63()
|
2022-03-30 15:14:26 +02:00
|
|
|
scope := "folders:id:10"
|
2022-05-02 09:29:30 +02:00
|
|
|
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
2022-06-30 09:31:54 -04:00
|
|
|
require.ErrorIs(t, err, ErrDashboardNotFound)
|
2022-05-02 09:29:30 +02:00
|
|
|
require.Nil(t, resolvedScopes)
|
2022-03-15 10:37:16 -04:00
|
|
|
})
|
|
|
|
|
}
|
2022-06-07 11:02:20 +02:00
|
|
|
|
|
|
|
|
func TestNewDashboardIDScopeResolver(t *testing.T) {
|
|
|
|
|
t.Run("prefix should be expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
prefix, _ := NewDashboardIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
2022-06-07 11:02:20 +02:00
|
|
|
require.Equal(t, "dashboards:id:", prefix)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewDashboardIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
2022-06-07 11:02:20 +02:00
|
|
|
_, err := resolver.Resolve(context.Background(), rand.Int63(), "dashboards:uid:123")
|
|
|
|
|
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewDashboardUIDScopeResolver(t *testing.T) {
|
|
|
|
|
t.Run("prefix should be expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
prefix, _ := NewDashboardUIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
2022-06-07 11:02:20 +02:00
|
|
|
require.Equal(t, "dashboards:uid:", prefix)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
2023-03-03 15:56:33 +00:00
|
|
|
_, resolver := NewDashboardUIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
2022-06-07 11:02:20 +02:00
|
|
|
_, err := resolver.Resolve(context.Background(), rand.Int63(), "dashboards:id:123")
|
|
|
|
|
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
|
|
|
|
})
|
|
|
|
|
}
|