| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | package folders | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana-openapi-client-go/models" | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/db" | 
					
						
							| 
									
										
										
										
											2024-04-30 19:15:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/tracing" | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/featuremgmt" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/org" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/org/orgimpl" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/quota/quotaimpl" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/user" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/user/userimpl" | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/tests" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/tests/testinfra" | 
					
						
							| 
									
										
										
										
											2024-09-26 07:21:39 +08:00
										 |  |  | 	"github.com/stretchr/testify/assert" | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const orgID = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-05 16:06:11 +08:00
										 |  |  | func TestIntegrationUpdateFolder(t *testing.T) { | 
					
						
							|  |  |  | 	if testing.Short() { | 
					
						
							|  |  |  | 		t.Skip("skipping integration test") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 	testUpdateFolder(t, []string{}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIntegrationUpdateFolderK8s(t *testing.T) { | 
					
						
							|  |  |  | 	if testing.Short() { | 
					
						
							|  |  |  | 		t.Skip("skipping integration test") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testUpdateFolder(t, []string{featuremgmt.FlagKubernetesClientDashboardsFolders}) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-02-05 16:06:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | func testUpdateFolder(t *testing.T, featureToggles []string) { | 
					
						
							| 
									
										
										
										
											2024-02-05 16:06:11 +08:00
										 |  |  | 	dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 		DisableAnonymous:     true, | 
					
						
							|  |  |  | 		EnableQuota:          true, | 
					
						
							|  |  |  | 		EnableFeatureToggles: featureToggles, | 
					
						
							| 
									
										
										
										
											2024-02-05 16:06:11 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) | 
					
						
							|  |  |  | 	store, cfg := env.SQLStore, env.Cfg | 
					
						
							| 
									
										
										
										
											2024-02-05 16:06:11 +08:00
										 |  |  | 	// Create user
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	createUser(t, store, cfg, user.CreateUserCommand{ | 
					
						
							| 
									
										
										
										
											2024-02-05 16:06:11 +08:00
										 |  |  | 		DefaultOrgRole: string(org.RoleAdmin), | 
					
						
							|  |  |  | 		Password:       "admin", | 
					
						
							|  |  |  | 		Login:          "admin", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	adminClient := tests.GetClient(grafanaListedAddr, "admin", "admin") | 
					
						
							|  |  |  | 	resp, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 		Title: "folder", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("update folder should succeed", func(t *testing.T) { | 
					
						
							|  |  |  | 		resp, err := adminClient.Folders.UpdateFolder(resp.Payload.UID, &models.UpdateFolderCommand{ | 
					
						
							|  |  |  | 			Title:   "new title", | 
					
						
							|  |  |  | 			Version: resp.Payload.Version, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 		require.Equal(t, "new title", resp.Payload.Title) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | func TestIntegrationCreateFolder(t *testing.T) { | 
					
						
							|  |  |  | 	if testing.Short() { | 
					
						
							|  |  |  | 		t.Skip("skipping integration test") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 	testCreateFolder(t, []string{}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIntegrationCreateFolderK8s(t *testing.T) { | 
					
						
							|  |  |  | 	if testing.Short() { | 
					
						
							|  |  |  | 		t.Skip("skipping integration test") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testCreateFolder(t, []string{featuremgmt.FlagKubernetesClientDashboardsFolders}) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | func testCreateFolder(t *testing.T, featureToggles []string) { | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 		DisableAnonymous:     true, | 
					
						
							|  |  |  | 		EnableQuota:          true, | 
					
						
							|  |  |  | 		EnableFeatureToggles: featureToggles, | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) | 
					
						
							|  |  |  | 	store, cfg := env.SQLStore, env.Cfg | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	// Create user
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	createUser(t, store, cfg, user.CreateUserCommand{ | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 		DefaultOrgRole: string(org.RoleAdmin), | 
					
						
							|  |  |  | 		Password:       "admin", | 
					
						
							|  |  |  | 		Login:          "admin", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	adminClient := tests.GetClient(grafanaListedAddr, "admin", "admin") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("create folder under root should succeed", func(t *testing.T) { | 
					
						
							|  |  |  | 		resp, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 			Title: "folder", | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 		t.Run("create folder with same name under root should succeed", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 			_, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 				Title: "folder", | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 			require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIntegrationNestedFoldersOn(t *testing.T) { | 
					
						
							|  |  |  | 	if testing.Short() { | 
					
						
							|  |  |  | 		t.Skip("skipping integration test") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 	testNestedFoldersOn(t, []string{}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIntegrationNestedFoldersOnK8s(t *testing.T) { | 
					
						
							|  |  |  | 	if testing.Short() { | 
					
						
							|  |  |  | 		t.Skip("skipping integration test") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	testNestedFoldersOn(t, []string{featuremgmt.FlagKubernetesClientDashboardsFolders}) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | func testNestedFoldersOn(t *testing.T, featureToggles []string) { | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ | 
					
						
							|  |  |  | 		DisableAnonymous:     true, | 
					
						
							|  |  |  | 		EnableQuota:          true, | 
					
						
							| 
									
										
										
										
											2025-03-31 18:02:19 +08:00
										 |  |  | 		EnableFeatureToggles: featureToggles, | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) | 
					
						
							|  |  |  | 	store, cfg := env.SQLStore, env.Cfg | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	// Create user
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	createUser(t, store, cfg, user.CreateUserCommand{ | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 		DefaultOrgRole: string(org.RoleAdmin), | 
					
						
							|  |  |  | 		Password:       "admin", | 
					
						
							|  |  |  | 		Login:          "admin", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	adminClient := tests.GetClient(grafanaListedAddr, "admin", "admin") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("create folder under root should succeed", func(t *testing.T) { | 
					
						
							|  |  |  | 		resp, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 			Title: "folder", | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 		t.Run("create folder with same name under root should succeed", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 			_, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 				Title: "folder", | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 			require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("create subfolder should succeed", func(t *testing.T) { | 
					
						
							|  |  |  | 		resp, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 			Title: "parent", | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 		parentUID := resp.Payload.UID | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		resp, err = adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 			Title:     "subfolder", | 
					
						
							|  |  |  | 			ParentUID: parentUID, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 		t.Run("create subfolder with same name should succeed", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 			resp, err = adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 				Title:     "subfolder", | 
					
						
							|  |  |  | 				ParentUID: parentUID, | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 			require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("create subfolder with same name under other folder should succeed", func(t *testing.T) { | 
					
						
							|  |  |  | 			resp, err := adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 				Title: "other", | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 			require.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 			other := resp.Payload.UID | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			resp, err = adminClient.Folders.CreateFolder(&models.CreateFolderCommand{ | 
					
						
							|  |  |  | 				Title:     "subfolder", | 
					
						
							|  |  |  | 				ParentUID: other, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			require.NoError(t, err) | 
					
						
							|  |  |  | 			assert.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 			assert.Equal(t, other, resp.Payload.ParentUID) | 
					
						
							|  |  |  | 			subfolderUnderOther := resp.Payload.UID | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 			t.Run("move subfolder to other folder containing folder with the same name should be ok", func(t *testing.T) { | 
					
						
							|  |  |  | 				resp, err := adminClient.Folders.MoveFolder(subfolderUnderOther, &models.MoveFolderCommand{ | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 					ParentUID: parentUID, | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2024-10-29 13:58:39 +08:00
										 |  |  | 				require.NoError(t, err) | 
					
						
							|  |  |  | 				assert.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 				assert.Equal(t, parentUID, resp.Payload.ParentUID) | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("move subfolder to root should succeed", func(t *testing.T) { | 
					
						
							|  |  |  | 				resp, err := adminClient.Folders.MoveFolder(subfolderUnderOther, &models.MoveFolderCommand{}) | 
					
						
							|  |  |  | 				require.NoError(t, err) | 
					
						
							|  |  |  | 				assert.Equal(t, http.StatusOK, resp.Code()) | 
					
						
							|  |  |  | 				assert.Equal(t, "", resp.Payload.ParentUID) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 07:21:39 +08:00
										 |  |  | func createUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 21:04:47 +08:00
										 |  |  | 	cfg.AutoAssignOrg = true | 
					
						
							|  |  |  | 	cfg.AutoAssignOrgId = orgID | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-26 07:21:39 +08:00
										 |  |  | 	quotaService := quotaimpl.ProvideService(db, cfg) | 
					
						
							|  |  |  | 	orgService, err := orgimpl.ProvideService(db, cfg, quotaService) | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2024-04-30 19:15:56 +08:00
										 |  |  | 	usrSvc, err := userimpl.ProvideService( | 
					
						
							| 
									
										
										
										
											2024-09-26 07:21:39 +08:00
										 |  |  | 		db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), | 
					
						
							| 
									
										
										
										
											2024-04-30 19:15:56 +08:00
										 |  |  | 		quotaService, supportbundlestest.NewFakeBundleService(), | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2024-01-25 17:29:56 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u, err := usrSvc.Create(context.Background(), &cmd) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	return u.ID | 
					
						
							|  |  |  | } |