mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Nested folders: Do not expose the sequential ID from the folder store (#60702)
* Nested folders: Do not expose the sequential ID from the folder store
This commit is contained in:
committed by
GitHub
parent
9c0d830e26
commit
e2ed42c2a3
@@ -97,41 +97,61 @@ func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.
|
|||||||
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
|
var dashFolder *folder.Folder
|
||||||
f, err := s.store.Get(ctx, *cmd)
|
var err error
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not get guardian by the folder ID because it differs from the nested folder ID
|
|
||||||
// and the legacy folder ID has been associated with the permissions:
|
|
||||||
// use the folde UID instead that is the same for both
|
|
||||||
g, err := guardian.NewByUID(ctx, f.UID, f.OrgID, cmd.SignedInUser)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if canView, err := g.CanView(); err != nil || !canView {
|
|
||||||
if err != nil {
|
|
||||||
return nil, toFolderError(err)
|
|
||||||
}
|
|
||||||
return nil, dashboards.ErrFolderAccessDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
return f, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cmd.UID != nil:
|
case cmd.UID != nil:
|
||||||
return s.getFolderByUID(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.UID)
|
dashFolder, err = s.getFolderByUID(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.UID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
case cmd.ID != nil:
|
case cmd.ID != nil:
|
||||||
return s.getFolderByID(ctx, cmd.SignedInUser, *cmd.ID, cmd.OrgID)
|
dashFolder, err = s.getFolderByID(ctx, cmd.SignedInUser, *cmd.ID, cmd.OrgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
case cmd.Title != nil:
|
case cmd.Title != nil:
|
||||||
return s.getFolderByTitle(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.Title)
|
dashFolder, err = s.getFolderByTitle(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.Title)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, folder.ErrBadRequest.Errorf("either on of UID, ID, Title fields must be present")
|
return nil, folder.ErrBadRequest.Errorf("either on of UID, ID, Title fields must be present")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
|
||||||
|
return dashFolder, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.ID != nil {
|
||||||
|
cmd.ID = nil
|
||||||
|
cmd.UID = &dashFolder.UID
|
||||||
|
}
|
||||||
|
f, err := s.store.Get(ctx, *cmd)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not get guardian by the folder ID because it differs from the nested folder ID
|
||||||
|
// and the legacy folder ID has been associated with the permissions:
|
||||||
|
// use the folde UID instead that is the same for both
|
||||||
|
g, err := guardian.NewByUID(ctx, f.UID, f.OrgID, cmd.SignedInUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if canView, err := g.CanView(); err != nil || !canView {
|
||||||
|
if err != nil {
|
||||||
|
return nil, toFolderError(err)
|
||||||
|
}
|
||||||
|
return nil, dashboards.ErrFolderAccessDenied
|
||||||
|
}
|
||||||
|
|
||||||
|
// always expose the dashboard store sequential ID
|
||||||
|
f.ID = dashFolder.ID
|
||||||
|
|
||||||
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetChildren(ctx context.Context, cmd *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
func (s *Service) GetChildren(ctx context.Context, cmd *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||||
@@ -147,12 +167,21 @@ func (s *Service) GetChildren(ctx context.Context, cmd *folder.GetChildrenQuery)
|
|||||||
|
|
||||||
filtered := make([]*folder.Folder, 0, len(children))
|
filtered := make([]*folder.Folder, 0, len(children))
|
||||||
for _, f := range children {
|
for _, f := range children {
|
||||||
|
// fetch folder from dashboard store
|
||||||
|
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, f.OrgID, f.UID)
|
||||||
|
if err != nil {
|
||||||
|
s.log.Error("failed to fetch folder by UID: %s from dashboard store", f.UID, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
g, err := guardian.New(ctx, f.ID, f.OrgID, cmd.SignedInUser)
|
g, err := guardian.New(ctx, f.ID, f.OrgID, cmd.SignedInUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
canView, err := g.CanView()
|
canView, err := g.CanView()
|
||||||
if err != nil || canView {
|
if err != nil || canView {
|
||||||
|
// always expose the dashboard store sequential ID
|
||||||
|
f.ID = dashFolder.ID
|
||||||
filtered = append(filtered, f)
|
filtered = append(filtered, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -372,33 +401,38 @@ func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (
|
|||||||
}
|
}
|
||||||
user := cmd.SignedInUser
|
user := cmd.SignedInUser
|
||||||
|
|
||||||
foldr, err := s.legacyUpdate(ctx, cmd)
|
dashFolder, err := s.legacyUpdate(ctx, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
|
if !s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
|
||||||
if cmd.NewUID != nil && *cmd.NewUID != "" {
|
return dashFolder, nil
|
||||||
if !util.IsValidShortUID(*cmd.NewUID) {
|
|
||||||
return nil, dashboards.ErrDashboardInvalidUid
|
|
||||||
} else if util.IsShortUIDTooLong(*cmd.NewUID) {
|
|
||||||
return nil, dashboards.ErrDashboardUidTooLong
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foldr, err := s.store.Update(ctx, folder.UpdateFolderCommand{
|
|
||||||
UID: cmd.UID,
|
|
||||||
OrgID: cmd.OrgID,
|
|
||||||
NewUID: cmd.NewUID,
|
|
||||||
NewTitle: cmd.NewTitle,
|
|
||||||
NewDescription: cmd.NewDescription,
|
|
||||||
SignedInUser: user,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return foldr, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd.NewUID != nil && *cmd.NewUID != "" {
|
||||||
|
if !util.IsValidShortUID(*cmd.NewUID) {
|
||||||
|
return nil, dashboards.ErrDashboardInvalidUid
|
||||||
|
} else if util.IsShortUIDTooLong(*cmd.NewUID) {
|
||||||
|
return nil, dashboards.ErrDashboardUidTooLong
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foldr, err := s.store.Update(ctx, folder.UpdateFolderCommand{
|
||||||
|
UID: cmd.UID,
|
||||||
|
OrgID: cmd.OrgID,
|
||||||
|
NewUID: cmd.NewUID,
|
||||||
|
NewTitle: cmd.NewTitle,
|
||||||
|
NewDescription: cmd.NewDescription,
|
||||||
|
SignedInUser: user,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// always expose the dashboard store sequential ID
|
||||||
|
foldr.ID = dashFolder.ID
|
||||||
|
|
||||||
return foldr, nil
|
return foldr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,12 +163,12 @@ func (ss *sqlStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.F
|
|||||||
exists := false
|
exists := false
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
|
case q.UID != nil:
|
||||||
|
exists, err = sess.SQL("SELECT * FROM folder WHERE uid = ? AND org_id = ?", q.UID, q.OrgID).Get(foldr)
|
||||||
case q.ID != nil:
|
case q.ID != nil:
|
||||||
exists, err = sess.SQL("SELECT * FROM folder WHERE id = ?", q.ID).Get(foldr)
|
exists, err = sess.SQL("SELECT * FROM folder WHERE id = ?", q.ID).Get(foldr)
|
||||||
case q.Title != nil:
|
case q.Title != nil:
|
||||||
exists, err = sess.SQL("SELECT * FROM folder WHERE title = ? AND org_id = ?", q.Title, q.OrgID).Get(foldr)
|
exists, err = sess.SQL("SELECT * FROM folder WHERE title = ? AND org_id = ?", q.Title, q.OrgID).Get(foldr)
|
||||||
case q.UID != nil:
|
|
||||||
exists, err = sess.SQL("SELECT * FROM folder WHERE uid = ? AND org_id = ?", q.UID, q.OrgID).Get(foldr)
|
|
||||||
default:
|
default:
|
||||||
return folder.ErrBadRequest.Errorf("one of ID, UID, or Title must be included in the command")
|
return folder.ErrBadRequest.Errorf("one of ID, UID, or Title must be included in the command")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user