Chore: Drop dashboard service dependency from folder service (#61614)

* Chore: Drop dashboard dependency from folder service
This commit is contained in:
Sofia Papagiannaki
2023-01-18 17:47:59 +02:00
committed by GitHub
parent a1f2d0e205
commit b80c9bb974
5 changed files with 250 additions and 139 deletions

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"strings"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/events"
@ -29,14 +30,13 @@ import (
type Service struct {
store store
log log.Logger
cfg *setting.Cfg
dashboardService dashboards.DashboardService
dashboardStore dashboards.Store
searchService *search.SearchService
features featuremgmt.FeatureToggles
permissions accesscontrol.FolderPermissionsService
accessControl accesscontrol.AccessControl
log log.Logger
cfg *setting.Cfg
dashboardStore dashboards.Store
searchService *search.SearchService
features featuremgmt.FeatureToggles
permissions accesscontrol.FolderPermissionsService
accessControl accesscontrol.AccessControl
// bus is currently used to publish events that cause scheduler to update rules.
bus bus.Bus
@ -46,7 +46,6 @@ func ProvideService(
ac accesscontrol.AccessControl,
bus bus.Bus,
cfg *setting.Cfg,
dashboardService dashboards.DashboardService,
dashboardStore dashboards.Store,
db db.DB, // DB for the (new) nested folder store
features featuremgmt.FeatureToggles,
@ -57,16 +56,15 @@ func ProvideService(
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore))
store := ProvideStore(db, cfg, features)
svr := &Service{
cfg: cfg,
log: log.New("folder-service"),
dashboardService: dashboardService,
dashboardStore: dashboardStore,
store: store,
searchService: searchService,
features: features,
permissions: folderPermissionsService,
accessControl: ac,
bus: bus,
cfg: cfg,
log: log.New("folder-service"),
dashboardStore: dashboardStore,
store: store,
searchService: searchService,
features: features,
permissions: folderPermissionsService,
accessControl: ac,
bus: bus,
}
if features.IsEnabled(featuremgmt.FlagNestedFolders) {
svr.DBMigration(db)
@ -321,7 +319,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
User: user,
}
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
saveDashboardCmd, err := s.BuildSaveDashboardCommand(ctx, dto)
if err != nil {
return nil, toFolderError(err)
}
@ -466,7 +464,7 @@ func (s *Service) legacyUpdate(ctx context.Context, cmd *folder.UpdateFolderComm
Overwrite: cmd.Overwrite,
}
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
saveDashboardCmd, err := s.BuildSaveDashboardCommand(ctx, dto)
if err != nil {
return nil, toFolderError(err)
}
@ -648,8 +646,154 @@ func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFold
return nil
}
// MakeUserAdmin is copy of DashboardServiceImpl.MakeUserAdmin
func (s *Service) MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error {
return s.dashboardService.MakeUserAdmin(ctx, orgID, userID, folderID, setViewAndEditPermissions)
rtEditor := org.RoleEditor
rtViewer := org.RoleViewer
items := []*models.DashboardACL{
{
OrgID: orgID,
DashboardID: folderID,
UserID: userID,
Permission: models.PERMISSION_ADMIN,
Created: time.Now(),
Updated: time.Now(),
},
}
if setViewAndEditPermissions {
items = append(items,
&models.DashboardACL{
OrgID: orgID,
DashboardID: folderID,
Role: &rtEditor,
Permission: models.PERMISSION_EDIT,
Created: time.Now(),
Updated: time.Now(),
},
&models.DashboardACL{
OrgID: orgID,
DashboardID: folderID,
Role: &rtViewer,
Permission: models.PERMISSION_VIEW,
Created: time.Now(),
Updated: time.Now(),
},
)
}
if err := s.dashboardStore.UpdateDashboardACL(ctx, folderID, items); err != nil {
return err
}
return nil
}
// BuildSaveDashboardCommand is a simplified version on DashboardServiceImpl.BuildSaveDashboardCommand
// keeping only the meaningful functionality for folders
func (s *Service) BuildSaveDashboardCommand(ctx context.Context, dto *dashboards.SaveDashboardDTO) (*dashboards.SaveDashboardCommand, error) {
dash := dto.Dashboard
dash.OrgID = dto.OrgID
dash.Title = strings.TrimSpace(dash.Title)
dash.Data.Set("title", dash.Title)
dash.SetUID(strings.TrimSpace(dash.UID))
if dash.Title == "" {
return nil, dashboards.ErrDashboardTitleEmpty
}
if dash.IsFolder && dash.FolderID > 0 {
return nil, dashboards.ErrDashboardFolderCannotHaveParent
}
if dash.IsFolder && strings.EqualFold(dash.Title, dashboards.RootFolderName) {
return nil, dashboards.ErrDashboardFolderNameExists
}
if !util.IsValidShortUID(dash.UID) {
return nil, dashboards.ErrDashboardInvalidUid
} else if util.IsShortUIDTooLong(dash.UID) {
return nil, dashboards.ErrDashboardUidTooLong
}
isParentFolderChanged, err := s.dashboardStore.ValidateDashboardBeforeSave(ctx, dash, dto.Overwrite)
if err != nil {
return nil, err
}
if isParentFolderChanged {
// Check that the user is allowed to add a dashboard to the folder
guardian, err := guardian.NewByDashboard(ctx, dash, dto.OrgID, dto.User)
if err != nil {
return nil, err
}
if canSave, err := guardian.CanCreate(dash.FolderID, dash.IsFolder); err != nil || !canSave {
if err != nil {
return nil, err
}
return nil, dashboards.ErrDashboardUpdateAccessDenied
}
}
guard, err := getGuardianForSavePermissionCheck(ctx, dash, dto.User)
if err != nil {
return nil, err
}
if dash.ID == 0 {
if canCreate, err := guard.CanCreate(dash.FolderID, dash.IsFolder); err != nil || !canCreate {
if err != nil {
return nil, err
}
return nil, dashboards.ErrDashboardUpdateAccessDenied
}
} else {
if canSave, err := guard.CanSave(); err != nil || !canSave {
if err != nil {
return nil, err
}
return nil, dashboards.ErrDashboardUpdateAccessDenied
}
}
cmd := &dashboards.SaveDashboardCommand{
Dashboard: dash.Data,
Message: dto.Message,
OrgID: dto.OrgID,
Overwrite: dto.Overwrite,
UserID: dto.User.UserID,
FolderID: dash.FolderID,
IsFolder: dash.IsFolder,
PluginID: dash.PluginID,
}
if !dto.UpdatedAt.IsZero() {
cmd.UpdatedAt = dto.UpdatedAt
}
return cmd, nil
}
// getGuardianForSavePermissionCheck returns the guardian to be used for checking permission of dashboard
// It replaces deleted Dashboard.GetDashboardIdForSavePermissionCheck()
func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashboard, user *user.SignedInUser) (guardian.DashboardGuardian, error) {
newDashboard := d.ID == 0
if newDashboard {
// if it's a new dashboard/folder check the parent folder permissions
guard, err := guardian.New(ctx, d.FolderID, d.OrgID, user)
if err != nil {
return nil, err
}
return guard, nil
}
guard, err := guardian.NewByDashboard(ctx, d, d.OrgID, user)
if err != nil {
return nil, err
}
return guard, nil
}
func (s *Service) nestedFolderCreate(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {