grafana/pkg/services/folder/model.go

211 lines
6.3 KiB
Go
Raw Normal View History

package folder
import (
"fmt"
"time"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/slugify"
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/errutil"
)
var ErrMaximumDepthReached = errutil.BadRequest("folder.maximum-depth-reached", errutil.WithPublicMessage("Maximum nested folder depth reached"))
var ErrBadRequest = errutil.BadRequest("folder.bad-request")
var ErrDatabaseError = errutil.Internal("folder.database-error")
var ErrConflict = errutil.Conflict("folder.conflict")
var ErrInternal = errutil.Internal("folder.internal")
var ErrCircularReference = errutil.BadRequest("folder.circular-reference", errutil.WithPublicMessage("Circular reference detected"))
var ErrTargetRegistrySrvConflict = errutil.Internal("folder.target-registry-srv-conflict")
var ErrFolderNotEmpty = errutil.BadRequest("folder.not-empty", errutil.WithPublicMessage("Folder cannot be deleted: folder is not empty"))
const (
Folders: Show dashboards and folders with directly assigned permissions in "Shared" folder (#78465) * Folders: Show folders user has access to at the root level * Refactor * Refactor * Hide parent folders user has no access to * Skip expensive computation if possible * Fix tests * Fix potential nil access * Fix duplicated folders * Fix linter error * Fix querying folders if no managed permissions set * Update benchmark * Add special shared with me folder and fetch available non-root folders on demand * Fix parents query * Improve db query for folders * Reset benchmark changes * Fix permissions for shared with me folder * Simplify dedup * Add option to include shared folder permission to user's permissions * Fix nil UID * Remove duplicated folders from shared list * Folders: Fix fetching empty folder * Nested folders: Show dashboards with directly assigned permissions * Fix slow dashboards fetch * Refactor * Fix cycle dependencies * Move shared folder to models * Fix shared folder links * Refactor * Use feature flag for permissions * Use feature flag * Review comments * Expose shared folder UID through frontend settings * Add frontend type for sharedWithMeFolderUID option * Refactor: apply review suggestions * Fix parent uid for shared folder * Fix listing shared dashboards for users with access to all folders * Prevent creating folder with "shared" UID * Add tests for shared folders * Add test for shared dashboards * Fix linter * Add metrics for shared with me folder * Add metrics for shared with me dashboards * Fix tests * Tests: add metrics as a dependency * Fix access control metadata for shared with me folder * Use constant for shared with me * Optimize parent folders access check, fetch all folders in one query. * Use labels for metrics
2023-12-05 09:13:31 -06:00
GeneralFolderUID = "general"
RootFolderUID = ""
MaxNestedFolderDepth = 4
SharedWithMeFolderUID = "sharedwithme"
)
var ErrFolderNotFound = errutil.NotFound("folder.notFound")
type Folder struct {
// Deprecated: use UID instead
ID int64 `xorm:"pk autoincr 'id'"`
OrgID int64 `xorm:"org_id"`
UID string `xorm:"uid"`
ParentUID string `xorm:"parent_uid"`
Title string
Description string
Created time.Time
Updated time.Time
// TODO: validate if this field is required/relevant to folders.
// currently there is no such column
Version int
URL string
UpdatedBy int64
CreatedBy int64
HasACL bool
Fullpath string `xorm:"fullpath"`
FullpathUIDs string `xorm:"fullpath_uids"`
}
var GeneralFolder = Folder{ID: 0, Title: "General"}
Folders: Show dashboards and folders with directly assigned permissions in "Shared" folder (#78465) * Folders: Show folders user has access to at the root level * Refactor * Refactor * Hide parent folders user has no access to * Skip expensive computation if possible * Fix tests * Fix potential nil access * Fix duplicated folders * Fix linter error * Fix querying folders if no managed permissions set * Update benchmark * Add special shared with me folder and fetch available non-root folders on demand * Fix parents query * Improve db query for folders * Reset benchmark changes * Fix permissions for shared with me folder * Simplify dedup * Add option to include shared folder permission to user's permissions * Fix nil UID * Remove duplicated folders from shared list * Folders: Fix fetching empty folder * Nested folders: Show dashboards with directly assigned permissions * Fix slow dashboards fetch * Refactor * Fix cycle dependencies * Move shared folder to models * Fix shared folder links * Refactor * Use feature flag for permissions * Use feature flag * Review comments * Expose shared folder UID through frontend settings * Add frontend type for sharedWithMeFolderUID option * Refactor: apply review suggestions * Fix parent uid for shared folder * Fix listing shared dashboards for users with access to all folders * Prevent creating folder with "shared" UID * Add tests for shared folders * Add test for shared dashboards * Fix linter * Add metrics for shared with me folder * Add metrics for shared with me dashboards * Fix tests * Tests: add metrics as a dependency * Fix access control metadata for shared with me folder * Use constant for shared with me * Optimize parent folders access check, fetch all folders in one query. * Use labels for metrics
2023-12-05 09:13:31 -06:00
var SharedWithMeFolder = Folder{
Title: "Shared with me",
Description: "Dashboards and folders shared with me",
UID: SharedWithMeFolderUID,
ParentUID: "",
ID: -1,
}
func (f *Folder) IsGeneral() bool {
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()
// nolint:staticcheck
return f.ID == GeneralFolder.ID && f.Title == GeneralFolder.Title
}
func (f *Folder) WithURL() *Folder {
if f == nil || f.URL != "" {
return f
}
// copy of dashboards.GetFolderURL()
f.URL = fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, f.UID, slugify.Slugify(f.Title))
return f
}
// NewFolder tales a title and returns a Folder with the Created and Updated
// fields set to the current time.
func NewFolder(title string, description string) *Folder {
return &Folder{
Title: title,
Description: description,
Created: time.Now(),
Updated: time.Now(),
}
}
// CreateFolderCommand captures the information required by the folder service
// to create a folder.
type CreateFolderCommand struct {
UID string `json:"uid"`
OrgID int64 `json:"-"`
Title string `json:"title"`
Description string `json:"description"`
ParentUID string `json:"parentUid"`
SignedInUser identity.Requester `json:"-"`
}
// UpdateFolderCommand captures the information required by the folder service
// to update a folder. Use Move to update a folder's parent folder.
type UpdateFolderCommand struct {
UID string `json:"-"`
OrgID int64 `json:"-"`
// NewTitle it's an optional parameter used for overriding the existing folder title
NewTitle *string `json:"title"` // keep same json tag with the legacy command for not breaking the existing APIs
// NewDescription it's an optional parameter used for overriding the existing folder description
NewDescription *string `json:"description"` // keep same json tag with the legacy command for not breaking the existing APIs
NewParentUID *string `json:"-"`
// Version only used by the legacy folder implementation
Version int `json:"version"`
// Overwrite only used by the legacy folder implementation
Overwrite bool `json:"overwrite"`
SignedInUser identity.Requester `json:"-"`
}
// MoveFolderCommand captures the information required by the folder service
// to move a folder.
type MoveFolderCommand struct {
UID string `json:"-"`
NewParentUID string `json:"parentUid"`
OrgID int64 `json:"-"`
SignedInUser identity.Requester `json:"-"`
}
// DeleteFolderCommand captures the information required by the folder service
// to delete a folder.
type DeleteFolderCommand struct {
UID string `json:"uid" xorm:"uid"`
OrgID int64 `json:"orgId" xorm:"org_id"`
ForceDeleteRules bool `json:"forceDeleteRules"`
SignedInUser identity.Requester `json:"-"`
}
// GetFolderQuery is used for all folder Get requests. Only one of UID, ID, or
2023-06-22 03:43:38 -05:00
// Title should be set; if multiple fields are set by the caller the dashboard
// service will select the field with the most specificity, in order: ID, UID,
// Title.
type GetFolderQuery struct {
UID *string
// Deprecated: use FolderUID instead
ID *int64
Title *string
ParentUID *string
OrgID int64
SignedInUser identity.Requester `json:"-"`
}
type GetFoldersQuery struct {
OrgID int64
UIDs []string
WithFullpath bool
WithFullpathUIDs bool
BatchSize uint64
SignedInUser identity.Requester `json:"-"`
}
// GetParentsQuery captures the information required by the folder service to
// return a list of all parent folders of a given folder.
type GetParentsQuery struct {
UID string `xorm:"uid"`
OrgID int64 `xorm:"org_id"`
}
// GetChildrenQuery captures the information required by the folder service to
// return a list of child folders of the given folder.
type GetChildrenQuery struct {
UID string
OrgID int64
Depth int64
// Pagination options
Limit int64
Page int64
SignedInUser identity.Requester `json:"-"`
// array of folder uids to filter by
FolderUIDs []string `json:"-"`
}
type HasEditPermissionInFoldersQuery struct {
SignedInUser identity.Requester
}
type HasAdminPermissionInDashboardsOrFoldersQuery struct {
SignedInUser identity.Requester
}
// GetDescendantCountsQuery captures the information required by the folder service
// to return the count of descendants (direct and indirect) in a folder.
type GetDescendantCountsQuery struct {
UID *string
OrgID int64
SignedInUser identity.Requester `json:"-"`
}
type DescendantCounts map[string]int64