Guardian: Introduce additional constructors (#59577)
* Guardian: Use dashboard UID instead of ID * Apply suggestions from code review Introduce several guardian constructors and each time use the most appropriate one.
This commit is contained in:
@@ -2,6 +2,7 @@ package guardian
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -21,30 +22,106 @@ var permissionMap = map[string]models.PermissionType{
|
||||
|
||||
var _ DashboardGuardian = new(AccessControlDashboardGuardian)
|
||||
|
||||
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboardId.
|
||||
func NewAccessControlDashboardGuardian(
|
||||
ctx context.Context, dashboardId int64, user *user.SignedInUser,
|
||||
store db.DB, ac accesscontrol.AccessControl,
|
||||
folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService,
|
||||
dashboardService dashboards.DashboardService,
|
||||
) *AccessControlDashboardGuardian {
|
||||
) (*AccessControlDashboardGuardian, error) {
|
||||
var dashboard *models.Dashboard
|
||||
if dashboardId != 0 {
|
||||
q := &models.GetDashboardQuery{
|
||||
Id: dashboardId,
|
||||
OrgId: user.OrgID,
|
||||
}
|
||||
|
||||
if err := dashboardService.GetDashboard(ctx, q); err != nil {
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return nil, ErrGuardianDashboardNotFound.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
return nil, ErrGuardianGetDashboardFailure.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
dashboard = q.Result
|
||||
}
|
||||
|
||||
return &AccessControlDashboardGuardian{
|
||||
ctx: ctx,
|
||||
log: log.New("dashboard.permissions"),
|
||||
dashboardID: dashboardId,
|
||||
dashboard: dashboard,
|
||||
user: user,
|
||||
store: store,
|
||||
ac: ac,
|
||||
folderPermissionsService: folderPermissionsService,
|
||||
dashboardPermissionsService: dashboardPermissionsService,
|
||||
dashboardService: dashboardService,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboardUID.
|
||||
func NewAccessControlDashboardGuardianByUID(
|
||||
ctx context.Context, dashboardUID string, user *user.SignedInUser,
|
||||
store db.DB, ac accesscontrol.AccessControl,
|
||||
folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService,
|
||||
dashboardService dashboards.DashboardService,
|
||||
) (*AccessControlDashboardGuardian, error) {
|
||||
var dashboard *models.Dashboard
|
||||
if dashboardUID != "" {
|
||||
q := &models.GetDashboardQuery{
|
||||
Uid: dashboardUID,
|
||||
OrgId: user.OrgID,
|
||||
}
|
||||
|
||||
if err := dashboardService.GetDashboard(ctx, q); err != nil {
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return nil, ErrGuardianDashboardNotFound.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
return nil, ErrGuardianGetDashboardFailure.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
dashboard = q.Result
|
||||
}
|
||||
|
||||
return &AccessControlDashboardGuardian{
|
||||
ctx: ctx,
|
||||
log: log.New("dashboard.permissions"),
|
||||
dashboard: dashboard,
|
||||
user: user,
|
||||
store: store,
|
||||
ac: ac,
|
||||
folderPermissionsService: folderPermissionsService,
|
||||
dashboardPermissionsService: dashboardPermissionsService,
|
||||
dashboardService: dashboardService,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboard.
|
||||
// This constructor should be preferred over the other two if the dashboard in available
|
||||
// since it avoids querying the database for fetching the dashboard.
|
||||
func NewAccessControlDashboardGuardianByDashboard(
|
||||
ctx context.Context, dashboard *models.Dashboard, user *user.SignedInUser,
|
||||
store db.DB, ac accesscontrol.AccessControl,
|
||||
folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService,
|
||||
dashboardService dashboards.DashboardService,
|
||||
) (*AccessControlDashboardGuardian, error) {
|
||||
return &AccessControlDashboardGuardian{
|
||||
ctx: ctx,
|
||||
log: log.New("dashboard.permissions"),
|
||||
dashboard: dashboard,
|
||||
user: user,
|
||||
store: store,
|
||||
ac: ac,
|
||||
folderPermissionsService: folderPermissionsService,
|
||||
dashboardPermissionsService: dashboardPermissionsService,
|
||||
dashboardService: dashboardService,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type AccessControlDashboardGuardian struct {
|
||||
ctx context.Context
|
||||
log log.Logger
|
||||
dashboardID int64
|
||||
dashboard *models.Dashboard
|
||||
user *user.SignedInUser
|
||||
store db.DB
|
||||
@@ -55,8 +132,8 @@ type AccessControlDashboardGuardian struct {
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) CanSave() (bool, error) {
|
||||
if err := a.loadDashboard(); err != nil {
|
||||
return false, err
|
||||
if a.dashboard == nil {
|
||||
return false, ErrGuardianDashboardNotFound
|
||||
}
|
||||
|
||||
if a.dashboard.IsFolder {
|
||||
@@ -69,9 +146,10 @@ func (a *AccessControlDashboardGuardian) CanSave() (bool, error) {
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) CanEdit() (bool, error) {
|
||||
if err := a.loadDashboard(); err != nil {
|
||||
return false, err
|
||||
if a.dashboard == nil {
|
||||
return false, ErrGuardianDashboardNotFound
|
||||
}
|
||||
|
||||
if setting.ViewersCanEdit {
|
||||
return a.CanView()
|
||||
}
|
||||
@@ -86,8 +164,8 @@ func (a *AccessControlDashboardGuardian) CanEdit() (bool, error) {
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) CanView() (bool, error) {
|
||||
if err := a.loadDashboard(); err != nil {
|
||||
return false, err
|
||||
if a.dashboard == nil {
|
||||
return false, ErrGuardianDashboardNotFound
|
||||
}
|
||||
|
||||
if a.dashboard.IsFolder {
|
||||
@@ -100,8 +178,8 @@ func (a *AccessControlDashboardGuardian) CanView() (bool, error) {
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) CanAdmin() (bool, error) {
|
||||
if err := a.loadDashboard(); err != nil {
|
||||
return false, err
|
||||
if a.dashboard == nil {
|
||||
return false, ErrGuardianDashboardNotFound
|
||||
}
|
||||
|
||||
if a.dashboard.IsFolder {
|
||||
@@ -118,8 +196,8 @@ func (a *AccessControlDashboardGuardian) CanAdmin() (bool, error) {
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) CanDelete() (bool, error) {
|
||||
if err := a.loadDashboard(); err != nil {
|
||||
return false, err
|
||||
if a.dashboard == nil {
|
||||
return false, ErrGuardianDashboardNotFound
|
||||
}
|
||||
|
||||
if a.dashboard.IsFolder {
|
||||
@@ -145,11 +223,11 @@ func (a *AccessControlDashboardGuardian) CanCreate(folderID int64, isFolder bool
|
||||
func (a *AccessControlDashboardGuardian) evaluate(evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
ok, err := a.ac.Evaluate(a.ctx, a.user, evaluator)
|
||||
if err != nil {
|
||||
a.log.Debug("Failed to evaluate access control to folder or dashboard", "error", err, "userId", a.user.UserID, "id", a.dashboardID)
|
||||
a.log.Debug("Failed to evaluate access control to folder or dashboard", "error", err, "userId", a.user.UserID, "id", a.dashboard.Id)
|
||||
}
|
||||
|
||||
if !ok && err == nil {
|
||||
a.log.Debug("Access denied to folder or dashboard", "userId", a.user.UserID, "id", a.dashboardID, "permissions", evaluator.GoString())
|
||||
a.log.Debug("Access denied to folder or dashboard", "userId", a.user.UserID, "id", a.dashboard.Id, "permissions", evaluator.GoString())
|
||||
}
|
||||
|
||||
return ok, err
|
||||
@@ -162,8 +240,8 @@ func (a *AccessControlDashboardGuardian) CheckPermissionBeforeUpdate(permission
|
||||
|
||||
// GetACL translate access control permissions to dashboard acl info
|
||||
func (a *AccessControlDashboardGuardian) GetACL() ([]*models.DashboardACLInfoDTO, error) {
|
||||
if err := a.loadDashboard(); err != nil {
|
||||
return nil, err
|
||||
if a.dashboard == nil {
|
||||
return nil, ErrGuardianGetDashboardFailure
|
||||
}
|
||||
|
||||
var svc accesscontrol.PermissionsService
|
||||
@@ -254,17 +332,6 @@ func (a *AccessControlDashboardGuardian) GetHiddenACL(cfg *setting.Cfg) ([]*mode
|
||||
return hiddenACL, nil
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) loadDashboard() error {
|
||||
if a.dashboard == nil {
|
||||
query := &models.GetDashboardQuery{Id: a.dashboardID, OrgId: a.user.OrgID}
|
||||
if err := a.dashboardService.GetDashboard(a.ctx, query); err != nil {
|
||||
return err
|
||||
}
|
||||
a.dashboard = query.Result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AccessControlDashboardGuardian) loadParentFolder(folderID int64) (*models.Dashboard, error) {
|
||||
if folderID == 0 {
|
||||
return &models.Dashboard{Uid: accesscontrol.GeneralFolderUID}, nil
|
||||
|
||||
@@ -616,9 +616,21 @@ func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []acce
|
||||
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, ac, teamSvc, userSvc)
|
||||
require.NoError(t, err)
|
||||
if dashboardSvc == nil {
|
||||
dashboardSvc = &dashboards.FakeDashboardService{}
|
||||
fakeDashboardService := dashboards.NewFakeDashboardService(t)
|
||||
fakeDashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
OrgId: q.OrgId,
|
||||
}
|
||||
}).Return(nil)
|
||||
dashboardSvc = fakeDashboardService
|
||||
}
|
||||
return NewAccessControlDashboardGuardian(context.Background(), dash.Id, &user.SignedInUser{OrgID: 1}, store, ac, folderPermissions, dashboardPermissions, dashboardSvc), dash
|
||||
|
||||
g, err := NewAccessControlDashboardGuardian(context.Background(), dash.Id, &user.SignedInUser{OrgID: 1}, store, ac, folderPermissions, dashboardPermissions, dashboardSvc)
|
||||
require.NoError(t, err)
|
||||
return g, dash
|
||||
}
|
||||
|
||||
func testDashSvc(t *testing.T) dashboards.DashboardService {
|
||||
|
||||
@@ -12,11 +12,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrGuardianPermissionExists = errors.New("permission already exists")
|
||||
ErrGuardianOverride = errors.New("you can only override a permission to be higher")
|
||||
ErrGuardianPermissionExists = errors.New("permission already exists")
|
||||
ErrGuardianOverride = errors.New("you can only override a permission to be higher")
|
||||
ErrGuardianGetDashboardFailure = errutil.NewBase(errutil.StatusInternal, "guardian.getDashboardFailure", errutil.WithPublicMessage("Failed to get dashboard"))
|
||||
ErrGuardianDashboardNotFound = errutil.NewBase(errutil.StatusNotFound, "guardian.dashboardNotFound")
|
||||
)
|
||||
|
||||
// DashboardGuardian to be used for guard against operations without access on dashboard and acl
|
||||
@@ -54,11 +57,38 @@ type dashboardGuardianImpl struct {
|
||||
|
||||
// New factory for creating a new dashboard guardian instance
|
||||
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
||||
var New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) DashboardGuardian {
|
||||
var New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
panic("no guardian factory implementation provided")
|
||||
}
|
||||
|
||||
func newDashboardGuardian(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) *dashboardGuardianImpl {
|
||||
// NewByUID factory for creating a new dashboard guardian instance
|
||||
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
||||
var NewByUID = func(ctx context.Context, dashUID string, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
panic("no guardian factory implementation provided")
|
||||
}
|
||||
|
||||
// NewByDashboard factory for creating a new dashboard guardian instance
|
||||
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
||||
var NewByDashboard = func(ctx context.Context, dash *models.Dashboard, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
panic("no guardian factory implementation provided")
|
||||
}
|
||||
|
||||
// newDashboardGuardian creates a dashboard guardian by the provided dashId.
|
||||
func newDashboardGuardian(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
|
||||
if dashId != 0 {
|
||||
q := &models.GetDashboardQuery{
|
||||
Id: dashId,
|
||||
OrgId: orgId,
|
||||
}
|
||||
|
||||
if err := dashSvc.GetDashboard(ctx, q); err != nil {
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return nil, ErrGuardianDashboardNotFound.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
return nil, ErrGuardianGetDashboardFailure.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &dashboardGuardianImpl{
|
||||
user: user,
|
||||
dashId: dashId,
|
||||
@@ -68,7 +98,53 @@ func newDashboardGuardian(ctx context.Context, dashId int64, orgId int64, user *
|
||||
store: store,
|
||||
dashboardService: dashSvc,
|
||||
teamService: teamSvc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newDashboardGuardianByUID creates a dashboard guardian by the provided dashUID.
|
||||
func newDashboardGuardianByUID(ctx context.Context, dashUID string, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
|
||||
dashID := int64(0)
|
||||
if dashUID != "" {
|
||||
q := &models.GetDashboardQuery{
|
||||
Uid: dashUID,
|
||||
OrgId: orgId,
|
||||
}
|
||||
|
||||
if err := dashSvc.GetDashboard(ctx, q); err != nil {
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return nil, ErrGuardianDashboardNotFound.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
return nil, ErrGuardianGetDashboardFailure.Errorf("failed to get dashboard by UID: %w", err)
|
||||
}
|
||||
dashID = q.Result.Id
|
||||
}
|
||||
|
||||
return &dashboardGuardianImpl{
|
||||
user: user,
|
||||
dashId: dashID,
|
||||
orgId: orgId,
|
||||
log: log.New("dashboard.permissions"),
|
||||
ctx: ctx,
|
||||
store: store,
|
||||
dashboardService: dashSvc,
|
||||
teamService: teamSvc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboard.
|
||||
// This constructor should be preferred over the other two if the dashboard in available
|
||||
// since it avoids querying the database for fetching the dashboard.
|
||||
func newDashboardGuardianByDashboard(ctx context.Context, dash *models.Dashboard, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
|
||||
return &dashboardGuardianImpl{
|
||||
user: user,
|
||||
dashId: dash.Id,
|
||||
orgId: orgId,
|
||||
log: log.New("dashboard.permissions"),
|
||||
ctx: ctx,
|
||||
store: store,
|
||||
dashboardService: dashSvc,
|
||||
teamService: teamSvc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (g *dashboardGuardianImpl) CanSave() (bool, error) {
|
||||
@@ -319,7 +395,8 @@ func (g *dashboardGuardianImpl) GetHiddenACL(cfg *setting.Cfg) ([]*models.Dashbo
|
||||
|
||||
// nolint:unused
|
||||
type FakeDashboardGuardian struct {
|
||||
DashId int64
|
||||
DashID int64
|
||||
DashUID string
|
||||
OrgId int64
|
||||
User *user.SignedInUser
|
||||
CanSaveValue bool
|
||||
@@ -379,10 +456,25 @@ func (g *FakeDashboardGuardian) GetHiddenACL(cfg *setting.Cfg) ([]*models.Dashbo
|
||||
|
||||
// nolint:unused
|
||||
func MockDashboardGuardian(mock *FakeDashboardGuardian) {
|
||||
New = func(_ context.Context, dashId int64, orgId int64, user *user.SignedInUser) DashboardGuardian {
|
||||
New = func(_ context.Context, dashID int64, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
mock.OrgId = orgId
|
||||
mock.DashId = dashId
|
||||
mock.DashID = dashID
|
||||
mock.User = user
|
||||
return mock
|
||||
return mock, nil
|
||||
}
|
||||
|
||||
NewByUID = func(_ context.Context, dashUID string, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
mock.OrgId = orgId
|
||||
mock.DashUID = dashUID
|
||||
mock.User = user
|
||||
return mock, nil
|
||||
}
|
||||
|
||||
NewByDashboard = func(_ context.Context, dash *models.Dashboard, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
mock.OrgId = orgId
|
||||
mock.DashUID = dash.Uid
|
||||
mock.DashID = dash.Id
|
||||
mock.User = user
|
||||
return mock, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ const (
|
||||
orgID = int64(1)
|
||||
defaultDashboardID = int64(-1)
|
||||
dashboardID = int64(1)
|
||||
dashboardUID = "uid"
|
||||
parentFolderID = int64(2)
|
||||
childDashboardID = int64(3)
|
||||
userID = int64(1)
|
||||
@@ -697,6 +698,14 @@ func TestGuardianGetHiddenACL(t *testing.T) {
|
||||
{Inherited: true, UserId: 3, UserLogin: "user3", Permission: models.PERMISSION_VIEW},
|
||||
}
|
||||
}).Return(nil)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
OrgId: q.OrgId,
|
||||
}
|
||||
}).Return(nil)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.HiddenUsers = map[string]struct{}{"user2": {}}
|
||||
@@ -707,7 +716,8 @@ func TestGuardianGetHiddenACL(t *testing.T) {
|
||||
UserID: 1,
|
||||
Login: "user1",
|
||||
}
|
||||
g := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
|
||||
g, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hiddenACL, err := g.GetHiddenACL(cfg)
|
||||
require.NoError(t, err)
|
||||
@@ -723,7 +733,16 @@ func TestGuardianGetHiddenACL(t *testing.T) {
|
||||
Login: "user1",
|
||||
IsGrafanaAdmin: true,
|
||||
}
|
||||
g := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil)
|
||||
g, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hiddenACL, err := g.GetHiddenACL(cfg)
|
||||
require.NoError(t, err)
|
||||
@@ -750,6 +769,14 @@ func TestGuardianGetACLWithoutDuplicates(t *testing.T) {
|
||||
{Inherited: false, UserId: 6, UserLogin: "user6", Permission: models.PERMISSION_EDIT},
|
||||
}
|
||||
}).Return(nil)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
OrgId: q.OrgId,
|
||||
}
|
||||
}).Return(nil)
|
||||
|
||||
t.Run("Should get acl without duplicates", func(t *testing.T) {
|
||||
user := &user.SignedInUser{
|
||||
@@ -757,7 +784,8 @@ func TestGuardianGetACLWithoutDuplicates(t *testing.T) {
|
||||
UserID: 1,
|
||||
Login: "user1",
|
||||
}
|
||||
g := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
|
||||
g, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
|
||||
require.NoError(t, err)
|
||||
|
||||
acl, err := g.GetACLWithoutDuplicates()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -43,7 +44,17 @@ func orgRoleScenario(desc string, t *testing.T, role org.RoleType, fn scenarioFu
|
||||
OrgRole: role,
|
||||
}
|
||||
store := dbtest.NewFakeDB()
|
||||
guard := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
|
||||
|
||||
fakeDashboardService := dashboards.NewFakeDashboardService(t)
|
||||
fakeDashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil)
|
||||
guard, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, fakeDashboardService, &teamtest.FakeService{})
|
||||
require.NoError(t, err)
|
||||
|
||||
sc := &scenarioContext{
|
||||
t: t,
|
||||
@@ -65,7 +76,17 @@ func apiKeyScenario(desc string, t *testing.T, role org.RoleType, fn scenarioFun
|
||||
ApiKeyID: 10,
|
||||
}
|
||||
store := dbtest.NewFakeDB()
|
||||
guard := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil)
|
||||
guard, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
|
||||
require.NoError(t, err)
|
||||
|
||||
sc := &scenarioContext{
|
||||
t: t,
|
||||
orgRoleScenario: desc,
|
||||
@@ -96,9 +117,20 @@ func permissionScenario(desc string, dashboardID int64, sc *scenarioContext,
|
||||
q := args.Get(1).(*models.GetDashboardACLInfoListQuery)
|
||||
q.Result = permissions
|
||||
}).Return(nil)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
OrgId: q.OrgId,
|
||||
}
|
||||
}).Return(nil)
|
||||
|
||||
sc.permissionScenario = desc
|
||||
sc.g = newDashboardGuardian(context.Background(), dashboardID, sc.givenUser.OrgID, sc.givenUser, store, dashSvc, teamSvc)
|
||||
g, err := newDashboardGuardian(context.Background(), dashboardID, sc.givenUser.OrgID, sc.givenUser, store, dashSvc, teamSvc)
|
||||
require.NoError(t, err)
|
||||
sc.g = g
|
||||
|
||||
sc.givenDashboardID = dashboardID
|
||||
sc.givenPermissions = permissions
|
||||
sc.givenTeams = teams
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
@@ -27,16 +28,32 @@ func ProvideService(
|
||||
}
|
||||
|
||||
func InitLegacyGuardian(store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) {
|
||||
New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) DashboardGuardian {
|
||||
New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
return newDashboardGuardian(ctx, dashId, orgId, user, store, dashSvc, teamSvc)
|
||||
}
|
||||
|
||||
NewByUID = func(ctx context.Context, dashUID string, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
return newDashboardGuardianByUID(ctx, dashUID, orgId, user, store, dashSvc, teamSvc)
|
||||
}
|
||||
|
||||
NewByDashboard = func(ctx context.Context, dash *models.Dashboard, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
return newDashboardGuardianByDashboard(ctx, dash, orgId, user, store, dashSvc, teamSvc)
|
||||
}
|
||||
}
|
||||
|
||||
func InitAccessControlGuardian(
|
||||
store db.DB, ac accesscontrol.AccessControl, folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService, dashboardService dashboards.DashboardService,
|
||||
) {
|
||||
New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) DashboardGuardian {
|
||||
New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
return NewAccessControlDashboardGuardian(ctx, dashId, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
|
||||
}
|
||||
|
||||
NewByUID = func(ctx context.Context, dashUID string, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
return NewAccessControlDashboardGuardianByUID(ctx, dashUID, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
|
||||
}
|
||||
|
||||
NewByDashboard = func(ctx context.Context, dash *models.Dashboard, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
|
||||
return NewAccessControlDashboardGuardianByDashboard(ctx, dash, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user