chore: move dashboard_acl models into dashboard service (#62151)

This commit is contained in:
Kristin Laemmert
2023-01-26 08:46:30 -05:00
committed by GitHub
parent c5cb5be3cc
commit e8b8a9e276
65 changed files with 553 additions and 572 deletions

View File

@@ -3,7 +3,6 @@ package dashboards
import (
"context"
"github.com/grafana/grafana/pkg/models"
alertmodels "github.com/grafana/grafana/pkg/services/alerting/models"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/quota"
@@ -15,7 +14,7 @@ import (
type DashboardService interface {
BuildSaveDashboardCommand(ctx context.Context, dto *SaveDashboardDTO, shouldValidateAlerts bool, validateProvisionedDashboard bool) (*SaveDashboardCommand, error)
DeleteDashboard(ctx context.Context, dashboardId int64, orgId int64) error
FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error)
FindDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error)
GetDashboard(ctx context.Context, query *GetDashboardQuery) (*Dashboard, error)
GetDashboardACLInfoList(ctx context.Context, query *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error)
GetDashboards(ctx context.Context, query *GetDashboardsQuery) ([]*Dashboard, error)
@@ -26,7 +25,7 @@ type DashboardService interface {
ImportDashboard(ctx context.Context, dto *SaveDashboardDTO) (*Dashboard, error)
MakeUserAdmin(ctx context.Context, orgID int64, userID, dashboardID int64, setViewAndEditPermissions bool) error
SaveDashboard(ctx context.Context, dto *SaveDashboardDTO, allowUiUpdate bool) (*Dashboard, error)
SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error
SearchDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) error
UpdateDashboardACL(ctx context.Context, uid int64, items []*DashboardACL) error
DeleteACLByUser(ctx context.Context, userID int64) error
CountDashboardsInFolder(ctx context.Context, query *CountDashboardsInFolderQuery) (int64, error)
@@ -57,7 +56,7 @@ type DashboardProvisioningService interface {
type Store interface {
DeleteDashboard(ctx context.Context, cmd *DeleteDashboardCommand) error
DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *DeleteOrphanedProvisionedDashboardsCommand) error
FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error)
FindDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error)
GetDashboard(ctx context.Context, query *GetDashboardQuery) (*Dashboard, error)
GetDashboardACLInfoList(ctx context.Context, query *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error)
GetDashboardUIDByID(ctx context.Context, query *GetDashboardRefByIDQuery) (*DashboardRef, error)

View File

@@ -0,0 +1,32 @@
package dashboards
import (
"errors"
)
type PermissionType int
const (
PERMISSION_VIEW PermissionType = 1 << iota
PERMISSION_EDIT
PERMISSION_ADMIN
)
func (p PermissionType) String() string {
names := map[int]string{
int(PERMISSION_VIEW): "View",
int(PERMISSION_EDIT): "Edit",
int(PERMISSION_ADMIN): "Admin",
}
return names[int(p)]
}
// Typed errors
var (
ErrDashboardACLInfoMissing = errors.New("user id and team id cannot both be empty for a dashboard permission")
ErrDashboardPermissionDashboardEmpty = errors.New("dashboard id must be greater than zero for a dashboard permission")
ErrFolderACLInfoMissing = errors.New("user id and team id cannot both be empty for a folder permission")
ErrFolderPermissionFolderEmpty = errors.New("folder id must be greater than zero for a folder permission")
ErrPermissionsWithRoleNotAllowed = errors.New("permissions cannot have both a user and team")
ErrPermissionsWithUserAndTeamNotAllowed = errors.New("team and user permissions cannot have an associated role")
)

View File

@@ -0,0 +1,26 @@
package dashboards
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPermissionType_String(t *testing.T) {
testCases := []struct {
permissionType PermissionType
expected string
}{
{PERMISSION_ADMIN, "Admin"},
{PERMISSION_EDIT, "Edit"},
{PERMISSION_VIEW, "View"},
}
for _, tc := range testCases {
t.Run(tc.expected, func(t *testing.T) {
assert.Equal(t, tc.expected, fmt.Sprint(tc.permissionType))
assert.Equal(t, tc.expected, tc.permissionType.String())
})
}
}

View File

@@ -7,8 +7,6 @@ import (
folder "github.com/grafana/grafana/pkg/services/folder"
mock "github.com/stretchr/testify/mock"
models "github.com/grafana/grafana/pkg/models"
)
// FakeDashboardService is an autogenerated mock type for the DashboardService type
@@ -89,11 +87,11 @@ func (_m *FakeDashboardService) DeleteDashboard(ctx context.Context, dashboardId
}
// FindDashboards provides a mock function with given fields: ctx, query
func (_m *FakeDashboardService) FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) {
func (_m *FakeDashboardService) FindDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) {
ret := _m.Called(ctx, query)
var r0 []DashboardSearchProjection
if rf, ok := ret.Get(0).(func(context.Context, *models.FindPersistedDashboardsQuery) []DashboardSearchProjection); ok {
if rf, ok := ret.Get(0).(func(context.Context, *FindPersistedDashboardsQuery) []DashboardSearchProjection); ok {
r0 = rf(ctx, query)
} else {
if ret.Get(0) != nil {
@@ -102,7 +100,7 @@ func (_m *FakeDashboardService) FindDashboards(ctx context.Context, query *model
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *models.FindPersistedDashboardsQuery) error); ok {
if rf, ok := ret.Get(1).(func(context.Context, *FindPersistedDashboardsQuery) error); ok {
r1 = rf(ctx, query)
} else {
r1 = ret.Error(1)
@@ -329,11 +327,11 @@ func (_m *FakeDashboardService) SaveDashboard(ctx context.Context, dto *SaveDash
}
// SearchDashboards provides a mock function with given fields: ctx, query
func (_m *FakeDashboardService) SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error {
func (_m *FakeDashboardService) SearchDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) error {
ret := _m.Called(ctx, query)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *models.FindPersistedDashboardsQuery) error); ok {
if rf, ok := ret.Get(0).(func(context.Context, *FindPersistedDashboardsQuery) error); ok {
r0 = rf(ctx, query)
} else {
r0 = ret.Error(0)

View File

@@ -4,7 +4,6 @@ import (
"context"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/org"
@@ -108,7 +107,7 @@ func (d *DashboardStore) HasEditPermissionInFolders(ctx context.Context, query *
builder := db.NewSqlBuilder(d.cfg, d.store.GetDialect())
builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?",
query.SignedInUser.OrgID, d.store.GetDialect().BooleanStr(true))
builder.WriteDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_EDIT)
builder.WriteDashboardPermissionFilter(query.SignedInUser, dashboards.PERMISSION_EDIT)
type folderCount struct {
Count int64
@@ -140,7 +139,7 @@ func (d *DashboardStore) HasAdminPermissionInDashboardsOrFolders(ctx context.Con
builder := db.NewSqlBuilder(d.cfg, d.store.GetDialect())
builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ?", query.SignedInUser.OrgID)
builder.WriteDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_ADMIN)
builder.WriteDashboardPermissionFilter(query.SignedInUser, dashboards.PERMISSION_ADMIN)
type folderCount struct {
Count int64

View File

@@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
@@ -45,9 +44,9 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{
OrgID: 1,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.Equal(t, models.ErrDashboardACLInfoMissing, err)
require.Equal(t, dashboards.ErrDashboardACLInfoMissing, err)
})
t.Run("Folder acl should include default acl", func(t *testing.T) {
@@ -103,7 +102,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
OrgID: 1,
UserID: currentUser.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.Nil(t, err)
@@ -122,7 +121,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
OrgID: 1,
UserID: currentUser.ID,
DashboardID: childDash.ID,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.Nil(t, err)
@@ -147,7 +146,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
OrgID: 1,
UserID: currentUser.ID,
DashboardID: childDash.ID,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.Nil(t, err)
@@ -174,7 +173,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
OrgID: 1,
UserID: currentUser.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.Nil(t, err)
@@ -183,7 +182,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
require.Nil(t, err)
require.Equal(t, savedFolder.ID, q1Result[0].DashboardID)
require.Equal(t, models.PERMISSION_EDIT, q1Result[0].Permission)
require.Equal(t, dashboards.PERMISSION_EDIT, q1Result[0].Permission)
require.Equal(t, "Edit", q1Result[0].PermissionName)
require.Equal(t, currentUser.ID, q1Result[0].UserID)
require.Equal(t, currentUser.Login, q1Result[0].UserLogin)
@@ -208,7 +207,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
OrgID: 1,
TeamID: team1.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.Nil(t, err)
@@ -216,7 +215,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
q1Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q1)
require.Nil(t, err)
require.Equal(t, savedFolder.ID, q1Result[0].DashboardID)
require.Equal(t, models.PERMISSION_EDIT, q1Result[0].Permission)
require.Equal(t, dashboards.PERMISSION_EDIT, q1Result[0].Permission)
require.Equal(t, team1.ID, q1Result[0].TeamID)
})
@@ -229,7 +228,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
OrgID: 1,
TeamID: team1.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_ADMIN,
Permission: dashboards.PERMISSION_ADMIN,
})
require.Nil(t, err)
@@ -238,7 +237,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) {
require.Nil(t, err)
require.Equal(t, 1, len(q3Result))
require.Equal(t, savedFolder.ID, q3Result[0].DashboardID)
require.Equal(t, models.PERMISSION_ADMIN, q3Result[0].Permission)
require.Equal(t, dashboards.PERMISSION_ADMIN, q3Result[0].Permission)
require.Equal(t, team1.ID, q3Result[0].TeamID)
})
})

View File

@@ -11,7 +11,6 @@ import (
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
alertmodels "github.com/grafana/grafana/pkg/services/alerting/models"
"github.com/grafana/grafana/pkg/services/dashboards"
@@ -249,11 +248,11 @@ func (d *DashboardStore) UpdateDashboardACL(ctx context.Context, dashboardID int
for _, item := range items {
if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) {
return models.ErrDashboardACLInfoMissing
return dashboards.ErrDashboardACLInfoMissing
}
if item.DashboardID == 0 {
return models.ErrDashboardPermissionDashboardEmpty
return dashboards.ErrDashboardPermissionDashboardEmpty
}
sess.Nullable("user_id", "team_id")
@@ -1003,7 +1002,7 @@ func (d *DashboardStore) GetDashboards(ctx context.Context, query *dashboards.Ge
return dashboards, nil
}
func (d *DashboardStore) FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]dashboards.DashboardSearchProjection, error) {
func (d *DashboardStore) FindDashboards(ctx context.Context, query *dashboards.FindPersistedDashboardsQuery) ([]dashboards.DashboardSearchProjection, error) {
filters := []interface{}{
permissions.DashboardPermissionFilter{
OrgRole: query.SignedInUser.OrgRole,

View File

@@ -8,7 +8,6 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder"
@@ -51,7 +50,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and no acls are set", func(t *testing.T) {
t.Run("should return all dashboards", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
OrgId: 1,
DashboardIds: []int64{flder.ID, dashInRoot.ID},
@@ -70,12 +69,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
DashboardID: flder.ID,
OrgID: 1,
UserID: otherUser,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should not return folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
OrgId: 1, DashboardIds: []int64{flder.ID, dashInRoot.ID},
}
@@ -88,12 +87,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("when the user is given permission", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, flder.ID, dashboards.DashboardACL{
DashboardID: flder.ID, OrgID: 1, UserID: currentUser.ID, Permission: models.PERMISSION_EDIT,
DashboardID: flder.ID, OrgID: 1, UserID: currentUser.ID, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should be able to access folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
OrgId: 1,
DashboardIds: []int64{flder.ID, dashInRoot.ID},
@@ -108,7 +107,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("when the user is an admin", func(t *testing.T) {
t.Run("should be able to access folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
UserID: currentUser.ID,
OrgID: 1,
@@ -131,12 +130,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, flder.ID)
require.NoError(t, err)
err = updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{
DashboardID: flder.ID, OrgID: 1, UserID: otherUser, Permission: models.PERMISSION_EDIT,
DashboardID: flder.ID, OrgID: 1, UserID: otherUser, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should not return folder or child", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer}, OrgId: 1, DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID},
}
err := testSearchDashboards(dashboardStore, query)
@@ -147,12 +146,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("when the user is given permission to child", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{
DashboardID: childDash.ID, OrgID: 1, UserID: currentUser.ID, Permission: models.PERMISSION_EDIT,
DashboardID: childDash.ID, OrgID: 1, UserID: currentUser.ID, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should be able to search for child dashboard but not folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer}, OrgId: 1, DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID}}
query := &dashboards.FindPersistedDashboardsQuery{SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer}, OrgId: 1, DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID}}
err := testSearchDashboards(dashboardStore, query)
require.NoError(t, err)
require.Equal(t, len(query.Result), 2)
@@ -163,7 +162,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("when the user is an admin", func(t *testing.T) {
t.Run("should be able to search for child dash and folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
UserID: currentUser.ID,
OrgID: 1,
@@ -206,7 +205,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
setup2()
t.Run("and one folder is expanded, the other collapsed", func(t *testing.T) {
t.Run("should return dashboards in root and expanded folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
FolderIds: []int64{
rootFolderId, folder1.ID}, SignedInUser: &user.SignedInUser{UserID: currentUser.ID,
OrgID: 1, OrgRole: org.RoleViewer,
@@ -226,7 +225,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and acl is set for one dashboard folder", func(t *testing.T) {
const otherUser int64 = 999
err := updateDashboardACL(t, dashboardStore, folder1.ID, dashboards.DashboardACL{
DashboardID: folder1.ID, OrgID: 1, UserID: otherUser, Permission: models.PERMISSION_EDIT,
DashboardID: folder1.ID, OrgID: 1, UserID: otherUser, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
@@ -234,7 +233,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
moveDashboard(t, dashboardStore, 1, childDash2.Data, folder1.ID)
t.Run("should not return folder with acl or its children", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
OrgId: 1,
DashboardIds: []int64{folder1.ID, childDash1.ID, childDash2.ID, dashInRoot.ID},
@@ -250,7 +249,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.ID)
t.Run("should return folder without acl and its children", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
OrgId: 1,
DashboardIds: []int64{folder2.ID, childDash1.ID, childDash2.ID, dashInRoot.ID},
@@ -267,14 +266,14 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and a dashboard with an acl is moved to the folder without an acl", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, childDash1.ID, dashboards.DashboardACL{
DashboardID: childDash1.ID, OrgID: 1, UserID: otherUser, Permission: models.PERMISSION_EDIT,
DashboardID: childDash1.ID, OrgID: 1, UserID: otherUser, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.ID)
t.Run("should return folder without acl but not the dashboard with acl", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
OrgId: 1,
DashboardIds: []int64{folder2.ID, childDash1.ID, childDash2.ID, dashInRoot.ID},
@@ -313,10 +312,10 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
setup3()
t.Run("Admin users", func(t *testing.T) {
t.Run("Should have write access to all dashboard folders in their org", func(t *testing.T) {
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
SignedInUser: &user.SignedInUser{UserID: adminUser.ID, OrgRole: org.RoleAdmin, OrgID: 1},
Permission: models.PERMISSION_VIEW,
Permission: dashboards.PERMISSION_VIEW,
Type: "dash-folder",
}
@@ -348,10 +347,10 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
})
t.Run("Editor users", func(t *testing.T) {
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
SignedInUser: &user.SignedInUser{UserID: editorUser.ID, OrgRole: org.RoleEditor, OrgID: 1},
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
}
t.Run("Should have write access to all dashboard folders with default ACL", func(t *testing.T) {
@@ -365,7 +364,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Should have write access to one dashboard folder if default role changed to view for one folder", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, folder1.ID, dashboards.DashboardACL{
DashboardID: folder1.ID, OrgID: 1, UserID: editorUser.ID, Permission: models.PERMISSION_VIEW,
DashboardID: folder1.ID, OrgID: 1, UserID: editorUser.ID, Permission: dashboards.PERMISSION_VIEW,
})
require.NoError(t, err)
@@ -396,10 +395,10 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
})
t.Run("Viewer users", func(t *testing.T) {
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
SignedInUser: &user.SignedInUser{UserID: viewerUser.ID, OrgRole: org.RoleViewer, OrgID: 1},
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
}
t.Run("Should have no write access to any dashboard folders with default ACL", func(t *testing.T) {
@@ -411,7 +410,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Should be able to get one dashboard folder if default role changed to edit for one folder", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, folder1.ID, dashboards.DashboardACL{
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: models.PERMISSION_EDIT,
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)
@@ -444,7 +443,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and admin permission is given for user with org role viewer in one dashboard folder", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, folder1.ID, dashboards.DashboardACL{
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: models.PERMISSION_ADMIN,
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: dashboards.PERMISSION_ADMIN,
})
require.NoError(t, err)
@@ -460,7 +459,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and edit permission is given for user with org role viewer in one dashboard folder", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, folder1.ID, dashboards.DashboardACL{
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: models.PERMISSION_EDIT,
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: dashboards.PERMISSION_EDIT,
})
require.NoError(t, err)

View File

@@ -323,7 +323,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
err := dashboardStore.DeleteDashboard(context.Background(), deleteCmd)
require.NoError(t, err)
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
FolderIds: []int64{savedFolder.ID},
SignedInUser: &user.SignedInUser{},
@@ -390,7 +390,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
t.Run("Should be able to find dashboard folder", func(t *testing.T) {
setup()
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
Title: "1 test dash folder",
OrgId: 1,
SignedInUser: &user.SignedInUser{
@@ -414,7 +414,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
t.Run("Should be able to limit find results", func(t *testing.T) {
setup()
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
Limit: 1,
SignedInUser: &user.SignedInUser{
@@ -435,7 +435,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
t.Run("Should be able to find results beyond limit using paging", func(t *testing.T) {
setup()
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
Limit: 1,
Page: 2,
@@ -460,7 +460,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
t.Run("Should be able to filter by tag and type", func(t *testing.T) {
setup()
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
Type: "dash-db",
Tags: []string{"prod"},
@@ -482,7 +482,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
t.Run("Should be able to find a dashboard folder's children", func(t *testing.T) {
setup()
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
OrgId: 1,
FolderIds: []int64{savedFolder.ID},
SignedInUser: &user.SignedInUser{
@@ -509,7 +509,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
t.Run("Should be able to find dashboards by ids", func(t *testing.T) {
setup()
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
DashboardIds: []int64{savedDash.ID, savedDash2.ID},
SignedInUser: &user.SignedInUser{
OrgID: 1,
@@ -547,7 +547,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
})
require.NoError(t, err)
query := models.FindPersistedDashboardsQuery{
query := dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
UserID: 10,
OrgID: 1,
@@ -623,7 +623,7 @@ func TestIntegrationDashboard_SortingOptions(t *testing.T) {
dashA := insertTestDashboard(t, dashboardStore, "Alfa", 1, 0, false)
assert.NotZero(t, dashA.ID)
assert.Less(t, dashB.ID, dashA.ID)
qNoSort := &models.FindPersistedDashboardsQuery{
qNoSort := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
@@ -639,7 +639,7 @@ func TestIntegrationDashboard_SortingOptions(t *testing.T) {
assert.Equal(t, dashA.ID, results[0].ID)
assert.Equal(t, dashB.ID, results[1].ID)
qSort := &models.FindPersistedDashboardsQuery{
qSort := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
@@ -673,7 +673,7 @@ func TestIntegrationDashboard_Filter(t *testing.T) {
require.NoError(t, err)
insertTestDashboard(t, dashboardStore, "Alfa", 1, 0, false)
dashB := insertTestDashboard(t, dashboardStore, "Beta", 1, 0, false)
qNoFilter := &models.FindPersistedDashboardsQuery{
qNoFilter := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
@@ -687,7 +687,7 @@ func TestIntegrationDashboard_Filter(t *testing.T) {
require.NoError(t, err)
require.Len(t, results, 2)
qFilter := &models.FindPersistedDashboardsQuery{
qFilter := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
@@ -840,7 +840,7 @@ func updateDashboardACL(t *testing.T, dashboardStore *DashboardStore, dashboardI
// testSearchDashboards is a (near) copy of the dashboard service
// SearchDashboards, which is a wrapper around FindDashboards.
func testSearchDashboards(d *DashboardStore, query *models.FindPersistedDashboardsQuery) error {
func testSearchDashboards(d *DashboardStore, query *dashboards.FindPersistedDashboardsQuery) error {
res, err := d.FindDashboards(context.Background(), query)
if err != nil {
return err
@@ -849,7 +849,7 @@ func testSearchDashboards(d *DashboardStore, query *models.FindPersistedDashboar
return nil
}
func makeQueryResult(query *models.FindPersistedDashboardsQuery, res []dashboards.DashboardSearchProjection) {
func makeQueryResult(query *dashboards.FindPersistedDashboardsQuery, res []dashboards.DashboardSearchProjection) {
query.Result = make([]*models.Hit, 0)
hits := make(map[int64]*models.Hit)

View File

@@ -337,7 +337,7 @@ type DashboardACL struct {
UserID int64 `xorm:"user_id"`
TeamID int64 `xorm:"team_id"`
Role *org.RoleType // pointer to be nullable
Permission models.PermissionType
Permission PermissionType
Created time.Time
Updated time.Time
@@ -353,23 +353,23 @@ type DashboardACLInfoDTO struct {
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
UserID int64 `json:"userId" xorm:"user_id"`
UserLogin string `json:"userLogin"`
UserEmail string `json:"userEmail"`
UserAvatarURL string `json:"userAvatarUrl" xorm:"user_avatar_url"`
TeamID int64 `json:"teamId" xorm:"team_id"`
TeamEmail string `json:"teamEmail"`
TeamAvatarURL string `json:"teamAvatarUrl" xorm:"team_avatar_url"`
Team string `json:"team"`
Role *org.RoleType `json:"role,omitempty"`
Permission models.PermissionType `json:"permission"`
PermissionName string `json:"permissionName"`
UID string `json:"uid" xorm:"uid"`
Title string `json:"title"`
Slug string `json:"slug"`
IsFolder bool `json:"isFolder"`
URL string `json:"url" xorm:"url"`
Inherited bool `json:"inherited"`
UserID int64 `json:"userId" xorm:"user_id"`
UserLogin string `json:"userLogin"`
UserEmail string `json:"userEmail"`
UserAvatarURL string `json:"userAvatarUrl" xorm:"user_avatar_url"`
TeamID int64 `json:"teamId" xorm:"team_id"`
TeamEmail string `json:"teamEmail"`
TeamAvatarURL string `json:"teamAvatarUrl" xorm:"team_avatar_url"`
Team string `json:"team"`
Role *org.RoleType `json:"role,omitempty"`
Permission PermissionType `json:"permission"`
PermissionName string `json:"permissionName"`
UID string `json:"uid" xorm:"uid"`
Title string `json:"title"`
Slug string `json:"slug"`
IsFolder bool `json:"isFolder"`
URL string `json:"url" xorm:"url"`
Inherited bool `json:"inherited"`
}
func (dto *DashboardACLInfoDTO) hasSameRoleAs(other *DashboardACLInfoDTO) bool {
@@ -398,3 +398,23 @@ type GetDashboardACLInfoListQuery struct {
DashboardID int64
OrgID int64
}
type FindPersistedDashboardsQuery struct {
Title string
OrgId int64
SignedInUser *user.SignedInUser
IsStarred bool
DashboardIds []int64
DashboardUIDs []string
Type string
FolderIds []int64
Tags []string
Limit int64
Page int64
Permission PermissionType
Sort models.SortOption
Filters []interface{}
Result models.HitList
}

View File

@@ -401,7 +401,7 @@ func (dr *DashboardServiceImpl) MakeUserAdmin(ctx context.Context, orgID int64,
OrgID: orgID,
DashboardID: dashboardID,
UserID: userID,
Permission: models.PERMISSION_ADMIN,
Permission: dashboards.PERMISSION_ADMIN,
Created: time.Now(),
Updated: time.Now(),
},
@@ -413,7 +413,7 @@ func (dr *DashboardServiceImpl) MakeUserAdmin(ctx context.Context, orgID int64,
OrgID: orgID,
DashboardID: dashboardID,
Role: &rtEditor,
Permission: models.PERMISSION_EDIT,
Permission: dashboards.PERMISSION_EDIT,
Created: time.Now(),
Updated: time.Now(),
},
@@ -421,7 +421,7 @@ func (dr *DashboardServiceImpl) MakeUserAdmin(ctx context.Context, orgID int64,
OrgID: orgID,
DashboardID: dashboardID,
Role: &rtViewer,
Permission: models.PERMISSION_VIEW,
Permission: dashboards.PERMISSION_VIEW,
Created: time.Now(),
Updated: time.Now(),
},
@@ -497,14 +497,14 @@ func (dr *DashboardServiceImpl) setDefaultPermissions(ctx context.Context, dto *
var permissions []accesscontrol.SetResourcePermissionCommand
if !provisioned && dto.User.IsRealUser() && !dto.User.IsAnonymous {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: dto.User.UserID, Permission: models.PERMISSION_ADMIN.String(),
UserID: dto.User.UserID, Permission: dashboards.PERMISSION_ADMIN.String(),
})
}
if !inFolder {
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
{BuiltinRole: string(org.RoleEditor), Permission: models.PERMISSION_EDIT.String()},
{BuiltinRole: string(org.RoleViewer), Permission: models.PERMISSION_VIEW.String()},
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
}...)
}
@@ -538,11 +538,11 @@ func (dr *DashboardServiceImpl) GetDashboards(ctx context.Context, query *dashbo
return dr.dashboardStore.GetDashboards(ctx, query)
}
func (dr *DashboardServiceImpl) FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]dashboards.DashboardSearchProjection, error) {
func (dr *DashboardServiceImpl) FindDashboards(ctx context.Context, query *dashboards.FindPersistedDashboardsQuery) ([]dashboards.DashboardSearchProjection, error) {
return dr.dashboardStore.FindDashboards(ctx, query)
}
func (dr *DashboardServiceImpl) SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error {
func (dr *DashboardServiceImpl) SearchDashboards(ctx context.Context, query *dashboards.FindPersistedDashboardsQuery) error {
res, err := dr.FindDashboards(ctx, query)
if err != nil {
return err
@@ -564,7 +564,7 @@ func getHitType(item dashboards.DashboardSearchProjection) models.HitType {
return hitType
}
func makeQueryResult(query *models.FindPersistedDashboardsQuery, res []dashboards.DashboardSearchProjection) {
func makeQueryResult(query *dashboards.FindPersistedDashboardsQuery, res []dashboards.DashboardSearchProjection) {
query.Result = make([]*models.Hit, 0)
hits := make(map[int64]*models.Hit)

View File

@@ -1,16 +1,14 @@
// Code generated by mockery v2.15.0. DO NOT EDIT.
// Code generated by mockery v2.16.0. DO NOT EDIT.
package dashboards
import (
context "context"
alertingmodels "github.com/grafana/grafana/pkg/services/alerting/models"
folder "github.com/grafana/grafana/pkg/services/folder"
mock "github.com/stretchr/testify/mock"
models "github.com/grafana/grafana/pkg/models"
models "github.com/grafana/grafana/pkg/services/alerting/models"
quota "github.com/grafana/grafana/pkg/services/quota"
)
@@ -107,11 +105,11 @@ func (_m *FakeDashboardStore) DeleteOrphanedProvisionedDashboards(ctx context.Co
}
// FindDashboards provides a mock function with given fields: ctx, query
func (_m *FakeDashboardStore) FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) {
func (_m *FakeDashboardStore) FindDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) {
ret := _m.Called(ctx, query)
var r0 []DashboardSearchProjection
if rf, ok := ret.Get(0).(func(context.Context, *models.FindPersistedDashboardsQuery) []DashboardSearchProjection); ok {
if rf, ok := ret.Get(0).(func(context.Context, *FindPersistedDashboardsQuery) []DashboardSearchProjection); ok {
r0 = rf(ctx, query)
} else {
if ret.Get(0) != nil {
@@ -120,7 +118,7 @@ func (_m *FakeDashboardStore) FindDashboards(ctx context.Context, query *models.
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *models.FindPersistedDashboardsQuery) error); ok {
if rf, ok := ret.Get(1).(func(context.Context, *FindPersistedDashboardsQuery) error); ok {
r1 = rf(ctx, query)
} else {
r1 = ret.Error(1)
@@ -379,11 +377,11 @@ func (_m *FakeDashboardStore) HasEditPermissionInFolders(ctx context.Context, qu
}
// SaveAlerts provides a mock function with given fields: ctx, dashID, alerts
func (_m *FakeDashboardStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*alertingmodels.Alert) error {
func (_m *FakeDashboardStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error {
ret := _m.Called(ctx, dashID, alerts)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, int64, []*alertingmodels.Alert) error); ok {
if rf, ok := ret.Get(0).(func(context.Context, int64, []*models.Alert) error); ok {
r0 = rf(ctx, dashID, alerts)
} else {
r0 = ret.Error(0)