K8s: Remove kubernetesClientDashboardsFolders feature flag (#108626)
This commit is contained in:
@@ -204,7 +204,7 @@ func (hs *HTTPServer) GetDashboard(c *contextmodel.ReqContext) response.Response
|
||||
}
|
||||
metrics.MFolderIDsAPICount.WithLabelValues(metrics.GetDashboard).Inc()
|
||||
// lookup folder title & url
|
||||
if dash.FolderUID != "" && hs.Features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
|
||||
if dash.FolderUID != "" {
|
||||
queryResult, err := hs.folderService.Get(ctx, &folder.GetFolderQuery{
|
||||
OrgID: c.GetOrgID(),
|
||||
UID: &dash.FolderUID,
|
||||
|
||||
+26
-94
@@ -19,32 +19,23 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/serverlock"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/client"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardversion/dashvertest"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
||||
libraryelementsfake "github.com/grafana/grafana/pkg/services/libraryelements/fake"
|
||||
"github.com/grafana/grafana/pkg/services/librarypanels"
|
||||
@@ -59,14 +50,10 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards/api"
|
||||
publicdashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
"github.com/grafana/grafana/pkg/services/search/sort"
|
||||
"github.com/grafana/grafana/pkg/services/star/startest"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
||||
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/services/user/usertest"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/grafana/grafana/pkg/web/webtest"
|
||||
)
|
||||
@@ -712,25 +699,42 @@ func TestIntegrationDashboardAPIEndpoint(t *testing.T) {
|
||||
|
||||
t.Run("Given provisioned dashboard", func(t *testing.T) {
|
||||
mockSQLStore := dbtest.NewFakeDB()
|
||||
dashboardStore := dashboards.NewFakeDashboardStore(t)
|
||||
dashboardStore.On("GetProvisionedDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(&dashboards.DashboardProvisioningSearchResults{ExternalID: "/dashboard1.json"}, nil).Once()
|
||||
|
||||
dashboardService := dashboards.NewFakeDashboardService(t)
|
||||
dashboardProvisioningService := dashboards.NewFakeDashboardProvisioning(t)
|
||||
|
||||
dataValue, err := simplejson.NewJson([]byte(`{"id": 1, "editable": true, "style": "dark"}`))
|
||||
require.NoError(t, err)
|
||||
qResult := &dashboards.Dashboard{ID: 1, Data: dataValue}
|
||||
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
||||
|
||||
dashboardProvisioningService.On("GetProvisionedDashboardDataByDashboardID", mock.Anything, mock.AnythingOfType("int64")).Return(&dashboards.DashboardProvisioning{ExternalID: "/dashboard1.json"}, nil)
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", org.RoleEditor, func(sc *scenarioContext) {
|
||||
fakeProvisioningService := provisioning.NewProvisioningServiceMock(context.Background())
|
||||
fakeProvisioningService.GetDashboardProvisionerResolvedPathFunc = func(name string) string {
|
||||
return "/tmp/grafana/dashboards"
|
||||
}
|
||||
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, fakeProvisioningService, dashboardStore, dashboardService, nil)
|
||||
hs := &HTTPServer{
|
||||
Cfg: setting.NewCfg(),
|
||||
ProvisioningService: fakeProvisioningService,
|
||||
LibraryPanelService: &mockLibraryPanelService{},
|
||||
LibraryElementService: &libraryelementsfake.LibraryElementService{},
|
||||
dashboardProvisioningService: dashboardProvisioningService,
|
||||
SQLStore: mockSQLStore,
|
||||
AccessControl: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
DashboardService: dashboardService,
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
starService: startest.NewStarServiceFake(),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
}
|
||||
hs.callGetDashboard(sc)
|
||||
|
||||
assert.Equal(t, "../../../dashboard1.json", dash.Meta.ProvisionedExternalId, mockSQLStore)
|
||||
assert.Equal(t, http.StatusOK, sc.resp.Code)
|
||||
|
||||
dash := dtos.DashboardFullWithMeta{}
|
||||
err := json.NewDecoder(sc.resp.Body).Decode(&dash)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "../../../dashboard1.json", dash.Meta.ProvisionedExternalId)
|
||||
}, mockSQLStore)
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When allowUiUpdates is true and calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", org.RoleEditor, func(sc *scenarioContext) {
|
||||
@@ -748,7 +752,7 @@ func TestIntegrationDashboardAPIEndpoint(t *testing.T) {
|
||||
ProvisioningService: fakeProvisioningService,
|
||||
LibraryPanelService: &mockLibraryPanelService{},
|
||||
LibraryElementService: &libraryelementsfake.LibraryElementService{},
|
||||
dashboardProvisioningService: mockDashboardProvisioningService{},
|
||||
dashboardProvisioningService: dashboardProvisioningService,
|
||||
SQLStore: mockSQLStore,
|
||||
AccessControl: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
DashboardService: dashboardService,
|
||||
@@ -771,6 +775,7 @@ func TestIntegrationDashboardAPIEndpoint(t *testing.T) {
|
||||
t.Run("v2 dashboards should not be returned in api", func(t *testing.T) {
|
||||
mockSQLStore := dbtest.NewFakeDB()
|
||||
dashboardService := dashboards.NewFakeDashboardService(t)
|
||||
dashboardProvisioningService := dashboards.NewFakeDashboardProvisioning(t)
|
||||
|
||||
dataValue, err := simplejson.NewJson([]byte(`{"id": 1, "apiVersion": "v2"}`))
|
||||
require.NoError(t, err)
|
||||
@@ -794,7 +799,7 @@ func TestIntegrationDashboardAPIEndpoint(t *testing.T) {
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
starService: startest.NewStarServiceFake(),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
dashboardProvisioningService: mockDashboardProvisioningService{},
|
||||
dashboardProvisioningService: dashboardProvisioningService,
|
||||
folderService: foldertest.NewFakeService(),
|
||||
log: log.New("test"),
|
||||
namespacer: func(orgID int64) string { return strconv.FormatInt(orgID, 10) },
|
||||
@@ -912,79 +917,6 @@ func TestDashboardVersionsAPIEndpoint(t *testing.T) {
|
||||
}, mockSQLStore)
|
||||
}
|
||||
|
||||
func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, provisioningService provisioning.ProvisioningService, dashboardStore dashboards.Store, dashboardService dashboards.DashboardService, folderStore folder.FolderStore) dtos.DashboardFullWithMeta {
|
||||
t.Helper()
|
||||
|
||||
if provisioningService == nil {
|
||||
provisioningService = provisioning.NewProvisioningServiceMock(context.Background())
|
||||
}
|
||||
|
||||
features := featuremgmt.WithFeatures()
|
||||
var err error
|
||||
if dashboardStore == nil {
|
||||
sql, cfg := db.InitTestDBWithCfg(t)
|
||||
dashboardStore, err = database.ProvideDashboardStore(sql, cfg, features, tagimpl.ProvideService(sql))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
libraryPanelsService := mockLibraryPanelService{}
|
||||
libraryElementsService := libraryelementsfake.LibraryElementService{}
|
||||
cfg := setting.NewCfg()
|
||||
ac := accesscontrolmock.New()
|
||||
folderPermissions := accesscontrolmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := accesscontrolmock.NewMockedPermissionsService()
|
||||
|
||||
db := db.InitTestDB(t)
|
||||
fStore := folderimpl.ProvideStore(db)
|
||||
quotaService := quotatest.New(false, nil)
|
||||
folderSvc := folderimpl.ProvideService(
|
||||
fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore,
|
||||
nil, db, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil,
|
||||
dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig)
|
||||
if dashboardService == nil {
|
||||
dashboardService, err = service.ProvideDashboardServiceImpl(
|
||||
cfg, dashboardStore, folderStore, features, folderPermissions,
|
||||
ac, actest.FakeService{}, folderSvc, nil, client.MockTestRestConfig{}, nil, quotaService, nil, nil, nil,
|
||||
dualwrite.ProvideTestService(), sort.ProvideService(),
|
||||
serverlock.ProvideService(db, tracing.InitializeTracerForTest()), kvstore.NewFakeKVStore(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
dashboardService.(dashboards.PermissionsRegistrationService).RegisterDashboardPermissions(dashboardPermissions)
|
||||
}
|
||||
|
||||
dashboardProvisioningService, err := service.ProvideDashboardServiceImpl(
|
||||
cfg, dashboardStore, folderStore, features, folderPermissions,
|
||||
ac, actest.FakeService{}, folderSvc, nil, client.MockTestRestConfig{}, nil, quotaService, nil, nil, nil,
|
||||
dualwrite.ProvideTestService(), sort.ProvideService(),
|
||||
serverlock.ProvideService(db, tracing.InitializeTracerForTest()), kvstore.NewFakeKVStore(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
hs := &HTTPServer{
|
||||
Cfg: cfg,
|
||||
LibraryPanelService: &libraryPanelsService,
|
||||
LibraryElementService: &libraryElementsService,
|
||||
SQLStore: sc.sqlStore,
|
||||
ProvisioningService: provisioningService,
|
||||
AccessControl: accesscontrolmock.New(),
|
||||
dashboardProvisioningService: dashboardProvisioningService,
|
||||
DashboardService: dashboardService,
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
starService: startest.NewStarServiceFake(),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
}
|
||||
|
||||
hs.callGetDashboard(sc)
|
||||
|
||||
require.Equal(sc.t, 200, sc.resp.Code)
|
||||
|
||||
dash := dtos.DashboardFullWithMeta{}
|
||||
err = json.NewDecoder(sc.resp.Body).Decode(&dash)
|
||||
require.NoError(sc.t, err)
|
||||
|
||||
return dash
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) callGetDashboard(sc *scenarioContext) {
|
||||
sc.handlerFunc = hs.GetDashboard
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
claims "github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
@@ -20,7 +17,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -198,13 +194,6 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
// Only set default permissions if the Folder API Server is disabled.
|
||||
if !hs.Features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
|
||||
if err := hs.setDefaultFolderPermissions(c.Req.Context(), cmd.OrgID, cmd.SignedInUser, folder); err != nil {
|
||||
hs.log.Error("Could not set the default folder permissions", "folder", folder.Title, "user", cmd.SignedInUser, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
folderDTO, err := hs.newToFolderDto(c, folder)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
@@ -214,46 +203,6 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
|
||||
return response.JSON(http.StatusOK, folderDTO)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int64, user identity.Requester, folder *folder.Folder) error {
|
||||
if !hs.Cfg.RBAC.PermissionsOnCreation("folder") {
|
||||
return nil
|
||||
}
|
||||
|
||||
var permissions []accesscontrol.SetResourcePermissionCommand
|
||||
|
||||
if user.IsIdentityType(claims.TypeUser, claims.TypeServiceAccount) {
|
||||
userID, err := user.GetInternalID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
|
||||
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
|
||||
isNested := folder.ParentUID != ""
|
||||
if !isNested || !hs.Features.IsEnabled(ctx, featuremgmt.FlagNestedFolders) {
|
||||
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
}
|
||||
|
||||
_, err := hs.folderPermissionsService.SetPermissions(ctx, orgID, folder.UID, permissions...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if user.IsIdentityType(claims.TypeUser, claims.TypeServiceAccount) {
|
||||
// Clear permission cache for the user who's created the folder, so that new permissions are fetched for their next call
|
||||
// Required for cases when caller wants to immediately interact with the newly created object
|
||||
hs.accesscontrolService.ClearUserPermissionCache(user)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// swagger:route POST /folders/{folder_uid}/move folders moveFolder
|
||||
//
|
||||
// Move folder.
|
||||
|
||||
+27
-73
@@ -620,9 +620,6 @@ func TestGetFolderLegacyAndUnifiedStorage(t *testing.T) {
|
||||
}
|
||||
|
||||
featuresArr := []any{featuremgmt.FlagNestedFolders}
|
||||
if tc.unifiedStorageEnabled {
|
||||
featuresArr = append(featuresArr, featuremgmt.FlagKubernetesClientDashboardsFolders)
|
||||
}
|
||||
|
||||
server := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
hs.Cfg = cfg
|
||||
@@ -676,39 +673,6 @@ func TestGetFolderLegacyAndUnifiedStorage(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetDefaultPermissionsWhenCreatingFolder(t *testing.T) {
|
||||
folderService := &foldertest.FakeService{}
|
||||
folderWithoutParentInput := "{ \"uid\": \"uid\", \"title\": \"Folder\"}"
|
||||
|
||||
type testCase struct {
|
||||
description string
|
||||
expectedCallsToSetPermissions int
|
||||
expectedCode int
|
||||
expectedFolder *folder.Folder
|
||||
permissions []accesscontrol.Permission
|
||||
featuresArr []any
|
||||
input string
|
||||
}
|
||||
|
||||
tcs := []testCase{
|
||||
{
|
||||
description: "folder creation succeeds, via legacy storage",
|
||||
expectedCallsToSetPermissions: 1,
|
||||
input: folderWithoutParentInput,
|
||||
expectedCode: http.StatusOK,
|
||||
expectedFolder: &folder.Folder{UID: "uid", Title: "Folder"},
|
||||
permissions: []accesscontrol.Permission{{Action: dashboards.ActionFoldersCreate}},
|
||||
},
|
||||
{
|
||||
description: "folder creation succeeds, via API Server",
|
||||
expectedCallsToSetPermissions: 0,
|
||||
input: folderWithoutParentInput,
|
||||
expectedCode: http.StatusOK,
|
||||
expectedFolder: &folder.Folder{UID: "uid", Title: "Folder"},
|
||||
permissions: []accesscontrol.Permission{{Action: dashboards.ActionFoldersCreate}},
|
||||
featuresArr: []any{featuremgmt.FlagKubernetesClientDashboardsFolders},
|
||||
},
|
||||
}
|
||||
|
||||
// we need to save these values because they are defined at `setting` package level
|
||||
// and modified when we invoke setting.NewCfgFromINIFile
|
||||
prevCookieSameSiteDisabled := setting.CookieSameSiteDisabled
|
||||
@@ -725,42 +689,32 @@ func TestSetDefaultPermissionsWhenCreatingFolder(t *testing.T) {
|
||||
setting.CookieSameSiteDisabled = prevCookieSameSiteDisabled
|
||||
setting.CookieSameSiteMode = prevCookieSameSiteMode
|
||||
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
folderService.ExpectedFolder = tc.expectedFolder
|
||||
folderPermService := acmock.NewMockedPermissionsService()
|
||||
folderPermService.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||
|
||||
srv := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
hs.Cfg = cfg
|
||||
|
||||
featuresArr := append(tc.featuresArr, featuremgmt.FlagNestedFolders)
|
||||
hs.Features = featuremgmt.WithFeatures(
|
||||
featuresArr...,
|
||||
)
|
||||
hs.folderService = folderService
|
||||
hs.folderPermissionsService = folderPermService
|
||||
hs.accesscontrolService = actest.FakeService{}
|
||||
})
|
||||
|
||||
input := strings.NewReader(tc.input)
|
||||
req := srv.NewPostRequest("/api/folders", input)
|
||||
req = webtest.RequestWithSignedInUser(req, userWithPermissions(1, tc.permissions))
|
||||
resp, err := srv.SendJSON(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expectedCode, resp.StatusCode)
|
||||
|
||||
folder := dtos.Folder{}
|
||||
err = json.NewDecoder(resp.Body).Decode(&folder)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, resp.Body.Close())
|
||||
|
||||
folderPermService.AssertNumberOfCalls(t, "SetPermissions", tc.expectedCallsToSetPermissions)
|
||||
|
||||
if tc.expectedCode == http.StatusOK {
|
||||
assert.Equal(t, "uid", folder.UID)
|
||||
assert.Equal(t, "Folder", folder.Title)
|
||||
}
|
||||
})
|
||||
folderService := &foldertest.FakeService{
|
||||
ExpectedFolder: &folder.Folder{UID: "uid", Title: "Folder"},
|
||||
}
|
||||
folderPermService := acmock.NewMockedPermissionsService()
|
||||
folderPermService.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||
|
||||
srv := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
hs.Cfg = cfg
|
||||
hs.Features = featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)
|
||||
hs.folderService = folderService
|
||||
hs.folderPermissionsService = folderPermService
|
||||
hs.accesscontrolService = actest.FakeService{}
|
||||
})
|
||||
|
||||
input := strings.NewReader("{ \"uid\": \"uid\", \"title\": \"Folder\"}")
|
||||
req := srv.NewPostRequest("/api/folders", input)
|
||||
req = webtest.RequestWithSignedInUser(req, userWithPermissions(1, []accesscontrol.Permission{{Action: dashboards.ActionFoldersCreate}}))
|
||||
resp, err := srv.SendJSON(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
folder := dtos.Folder{}
|
||||
err = json.NewDecoder(resp.Body).Decode(&folder)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, resp.Body.Close())
|
||||
|
||||
assert.Equal(t, "uid", folder.UID)
|
||||
assert.Equal(t, "Folder", folder.Title)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user