mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Folders: Set folder creation permission as part of legacy create (#94040)
* Add folder store to dashboard permissions * Include folder store in annotation scope resolver * Add folder store when initialising library elements * Include folder store in search v2 service initialisation * Include folder store in GetInheritedScopes * Add folder store to folder permissions provider * Include cfg, folder permissions in folder service * Move setting of folder permissions for folder service create method
This commit is contained in:
@@ -587,7 +587,7 @@ func (hs *HTTPServer) GetAnnotationTags(c *contextmodel.ReqContext) response.Res
|
||||
// where <type> is the type of annotation with id <id>.
|
||||
// If annotationPermissionUpdate feature toggle is enabled, dashboard annotation scope will be resolved to the corresponding
|
||||
// dashboard and folder scopes (eg, "dashboards:uid:<annotation_dashboard_uid>", "folders:uid:<parent_folder_uid>" etc).
|
||||
func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, features featuremgmt.FeatureToggles, dashSvc dashboards.DashboardService, folderSvc folder.Service) (string, accesscontrol.ScopeAttributeResolver) {
|
||||
func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, features featuremgmt.FeatureToggles, dashSvc dashboards.DashboardService, folderStore folder.Store) (string, accesscontrol.ScopeAttributeResolver) {
|
||||
prefix := accesscontrol.ScopeAnnotationsProvider.GetResourceScope("")
|
||||
return prefix, accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
|
||||
scopeParts := strings.Split(initialScope, ":")
|
||||
@@ -649,7 +649,7 @@ func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, feature
|
||||
// Append dashboard parent scopes if dashboard is in a folder or the general scope if dashboard is not in a folder
|
||||
if dashboard.FolderUID != "" {
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(dashboard.FolderUID))
|
||||
inheritedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, dashboard.FolderUID, folderSvc)
|
||||
inheritedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, dashboard.FolderUID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -397,14 +397,15 @@ func TestAPI_Annotations(t *testing.T) {
|
||||
dashService := &dashboards.FakeDashboardService{}
|
||||
dashService.On("GetDashboard", mock.Anything, mock.Anything).Return(&dashboards.Dashboard{UID: dashUID, FolderUID: folderUID, FolderID: 1}, nil)
|
||||
folderService := &foldertest.FakeService{}
|
||||
fStore := folder.NewFakeStore()
|
||||
folderService.ExpectedFolder = &folder.Folder{UID: folderUID, ID: 1}
|
||||
folderDB := &foldertest.FakeFolderStore{}
|
||||
folderDB.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(&folder.Folder{UID: folderUID, ID: 1}, nil)
|
||||
hs.DashboardService = dashService
|
||||
hs.folderService = folderService
|
||||
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, hs.Features, dashService, folderService))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(folderDB, dashService, folderService))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, hs.Features, dashService, fStore))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(folderDB, dashService, fStore))
|
||||
})
|
||||
var body io.Reader
|
||||
if tt.body != "" {
|
||||
@@ -504,7 +505,7 @@ func TestService_AnnotationTypeScopeResolver(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
features := featuremgmt.WithFeatures(tc.featureToggles...)
|
||||
prefix, resolver := AnnotationTypeScopeResolver(fakeAnnoRepo, features, dashSvc, &foldertest.FakeService{})
|
||||
prefix, resolver := AnnotationTypeScopeResolver(fakeAnnoRepo, features, dashSvc, folder.NewFakeStore())
|
||||
require.Equal(t, "annotations:id:", prefix)
|
||||
|
||||
resolved, err := resolver.Resolve(context.Background(), 1, tc.given)
|
||||
|
||||
@@ -836,7 +836,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr
|
||||
db := db.InitTestDB(t)
|
||||
fStore := folderimpl.ProvideStore(db)
|
||||
folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()),
|
||||
dashboardStore, folderStore, db, features,
|
||||
dashboardStore, folderStore, db, features, cfg, folderPermissions,
|
||||
supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
if dashboardService == nil {
|
||||
dashboardService, err = service.ProvideDashboardServiceImpl(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -12,12 +11,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"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"
|
||||
folderalpha1 "github.com/grafana/grafana/pkg/apis/folder/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders"
|
||||
@@ -31,7 +28,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"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/util/errhttp"
|
||||
@@ -219,10 +215,6 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// 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(c.SignedInUser)
|
||||
@@ -236,36 +228,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) {
|
||||
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...)
|
||||
return err
|
||||
}
|
||||
|
||||
// swagger:route POST /folders/{folder_uid}/move folders moveFolder
|
||||
//
|
||||
// Move folder.
|
||||
|
||||
@@ -464,14 +464,15 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog
|
||||
features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db, permreg.ProvidePermissionRegistry(),
|
||||
)
|
||||
fStore := folderimpl.ProvideStore(sc.db)
|
||||
folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore,
|
||||
folderStore, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions(
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, fStore, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
require.NoError(b, err)
|
||||
|
||||
folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore,
|
||||
folderStore, sc.db, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions(
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, fStore, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
require.NoError(b, err)
|
||||
|
||||
dashboardSvc, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||
|
||||
@@ -253,6 +253,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
authInfoService login.AuthInfoService, storageService store.StorageService,
|
||||
notificationService notifications.Service, dashboardService dashboards.DashboardService,
|
||||
dashboardProvisioningService dashboards.DashboardProvisioningService, folderService folder.Service,
|
||||
folderStore folder.Store,
|
||||
dsGuardian guardian.DatasourceGuardianProvider,
|
||||
dashboardsnapshotsService dashboardsnapshots.Service, pluginSettings pluginSettings.Service,
|
||||
avatarCacheServer *avatar.AvatarCacheServer, preferenceService pref.Service,
|
||||
@@ -379,7 +380,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
hs.registerRoutes()
|
||||
|
||||
// Register access control scope resolver for annotations
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, features, dashboardService, folderService))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, features, dashboardService, folderStore))
|
||||
|
||||
if err := hs.declareFixedRoles(); err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user