| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | package folders | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2024-01-24 02:33:32 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana-openapi-client-go/client/folders" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana-openapi-client-go/models" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/featuremgmt" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/folder" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/org" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/user" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/tests" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/tests/testinfra" | 
					
						
							| 
									
										
										
										
											2024-02-09 22:35:39 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/tests/testsuite" | 
					
						
							| 
									
										
										
										
											2024-01-24 02:33:32 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util/retryer" | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 	"github.com/stretchr/testify/assert" | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-09 22:35:39 +08:00
										 |  |  | func TestMain(m *testing.M) { | 
					
						
							|  |  |  | 	testsuite.Run(m) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | func TestGetFolders(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 	testGetFolders(t, []string{featuremgmt.FlagNestedFolders}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestGetFoldersK8s(t *testing.T) { | 
					
						
							|  |  |  | 	testGetFolders(t, []string{featuremgmt.FlagNestedFolders, featuremgmt.FlagKubernetesClientDashboardsFolders}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testGetFolders(t *testing.T, featureToggles []string) { | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 	// Setup Grafana and its Database
 | 
					
						
							|  |  |  | 	dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ | 
					
						
							|  |  |  | 		DisableLegacyAlerting: true, | 
					
						
							|  |  |  | 		EnableUnifiedAlerting: true, | 
					
						
							|  |  |  | 		DisableAnonymous:      true, | 
					
						
							|  |  |  | 		AppModeProduction:     true, | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 		EnableFeatureToggles:  featureToggles, | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p) | 
					
						
							|  |  |  | 	store, cfg := env.SQLStore, env.Cfg | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	orgID := int64(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create a users to make authenticated requests
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	tests.CreateUser(t, store, cfg, user.CreateUserCommand{ | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 		DefaultOrgRole: string(org.RoleViewer), | 
					
						
							|  |  |  | 		OrgID:          orgID, | 
					
						
							|  |  |  | 		Password:       "viewer", | 
					
						
							|  |  |  | 		Login:          "viewer", | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	tests.CreateUser(t, store, cfg, user.CreateUserCommand{ | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 		OrgID:          orgID, | 
					
						
							|  |  |  | 		DefaultOrgRole: string(org.RoleEditor), | 
					
						
							|  |  |  | 		Password:       "editor", | 
					
						
							|  |  |  | 		Login:          "editor", | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	tests.CreateUser(t, store, cfg, user.CreateUserCommand{ | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 		OrgID:          orgID, | 
					
						
							|  |  |  | 		DefaultOrgRole: string(org.RoleAdmin), | 
					
						
							|  |  |  | 		Password:       "admin", | 
					
						
							|  |  |  | 		Login:          "admin", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	adminClient := tests.GetClient(grafanaListedAddr, "admin", "admin") | 
					
						
							|  |  |  | 	editorClient := tests.GetClient(grafanaListedAddr, "editor", "editor") | 
					
						
							|  |  |  | 	viewerClient := tests.GetClient(grafanaListedAddr, "viewer", "viewer") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// access control permissions store
 | 
					
						
							| 
									
										
										
										
											2024-05-28 23:32:23 +08:00
										 |  |  | 	permissionsStore := resourcepermissions.NewStore(cfg, store, featuremgmt.WithFeatures()) | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	numberOfFolders := 5 | 
					
						
							|  |  |  | 	indexWithoutPermission := 3 | 
					
						
							| 
									
										
										
										
											2024-01-24 02:33:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < numberOfFolders; i++ { | 
					
						
							|  |  |  | 		respCode := 0 | 
					
						
							|  |  |  | 		folderUID := "" | 
					
						
							|  |  |  | 		retries := 0 | 
					
						
							|  |  |  | 		maxRetries := 3 | 
					
						
							|  |  |  | 		err := retryer.Retry(func() (retryer.RetrySignal, error) { | 
					
						
							|  |  |  | 			resp, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 				Title: fmt.Sprintf("Folder %d", i), | 
					
						
							|  |  |  | 				UID:   fmt.Sprintf("folder-%d", i), | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				if retries == maxRetries { | 
					
						
							|  |  |  | 					return retryer.FuncError, err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				retries++ | 
					
						
							|  |  |  | 				return retryer.FuncFailure, nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			respCode = resp.Code() | 
					
						
							|  |  |  | 			folderUID = resp.Payload.UID | 
					
						
							|  |  |  | 			return retryer.FuncComplete, nil | 
					
						
							|  |  |  | 		}, maxRetries, time.Millisecond*time.Duration(10), time.Second) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, respCode) | 
					
						
							|  |  |  | 		if i == indexWithoutPermission { | 
					
						
							|  |  |  | 			tests.RemoveFolderPermission(t, permissionsStore, orgID, org.RoleViewer, folderUID) | 
					
						
							|  |  |  | 			t.Log("Removed viewer permission from folder", folderUID) | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-01-24 02:33:32 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Admin can get all folders", func(t *testing.T) { | 
					
						
							|  |  |  | 		res, err := adminClient.Folders.GetFolders(folders.NewGetFoldersParams()) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders := make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-0", "folder-1", "folder-2", "folder-3", "folder-4"}, actualFolders) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Pagination works as expect for admin", func(t *testing.T) { | 
					
						
							|  |  |  | 		limit := int64(2) | 
					
						
							|  |  |  | 		page := int64(1) | 
					
						
							|  |  |  | 		res, err := adminClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders := make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-0", "folder-1"}, actualFolders) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		page = int64(2) | 
					
						
							|  |  |  | 		res, err = adminClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders = make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-2", "folder-3"}, actualFolders) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		page = int64(3) | 
					
						
							|  |  |  | 		res, err = adminClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders = make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-4"}, actualFolders) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Editor can get all folders", func(t *testing.T) { | 
					
						
							|  |  |  | 		res, err := editorClient.Folders.GetFolders(folders.NewGetFoldersParams()) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders := make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-12-29 18:35:15 +08:00
										 |  |  | 		assert.Equal(t, []string{folder.SharedWithMeFolderUID, "folder-0", "folder-1", "folder-2", "folder-3", "folder-4"}, actualFolders) | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Pagination works as expect for editor", func(t *testing.T) { | 
					
						
							|  |  |  | 		limit := int64(2) | 
					
						
							|  |  |  | 		page := int64(1) | 
					
						
							|  |  |  | 		res, err := editorClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders := make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-12-29 18:35:15 +08:00
										 |  |  | 		assert.Equal(t, []string{folder.SharedWithMeFolderUID, "folder-0", "folder-1"}, actualFolders) | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		page = int64(2) | 
					
						
							|  |  |  | 		res, err = editorClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders = make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-2", "folder-3"}, actualFolders) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		page = int64(3) | 
					
						
							|  |  |  | 		res, err = editorClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders = make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-4"}, actualFolders) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Viewer can get only the folders has access too", func(t *testing.T) { | 
					
						
							|  |  |  | 		res, err := viewerClient.Folders.GetFolders(folders.NewGetFoldersParams()) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders := make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-12-29 18:35:15 +08:00
										 |  |  | 		assert.Equal(t, []string{folder.SharedWithMeFolderUID, "folder-0", "folder-1", "folder-2", "folder-4"}, actualFolders) | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Pagination works as expect for viewer", func(t *testing.T) { | 
					
						
							|  |  |  | 		limit := int64(2) | 
					
						
							|  |  |  | 		page := int64(1) | 
					
						
							|  |  |  | 		res, err := viewerClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders := make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-12-29 18:35:15 +08:00
										 |  |  | 		assert.Equal(t, []string{folder.SharedWithMeFolderUID, "folder-0", "folder-1"}, actualFolders) | 
					
						
							| 
									
										
										
										
											2023-12-16 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		page = int64(2) | 
					
						
							|  |  |  | 		res, err = viewerClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		actualFolders = make([]string, 0, len(res.Payload)) | 
					
						
							|  |  |  | 		for i := range res.Payload { | 
					
						
							|  |  |  | 			actualFolders = append(actualFolders, res.Payload[i].UID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		assert.Equal(t, []string{"folder-2", "folder-4"}, actualFolders) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		page = int64(3) | 
					
						
							|  |  |  | 		res, err = viewerClient.Folders.GetFolders(folders.NewGetFoldersParams().WithLimit(&limit).WithPage(&page)) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		assert.Len(t, res.Payload, 0) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } |