Cfg: Move ViewersCanEdit into cfg (#64876)

move ViewersCanEdit into cfg
This commit is contained in:
Jo 2023-03-16 09:54:01 +00:00 committed by GitHub
parent 7fd7c6ed78
commit 6b6cf5f4b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 94 additions and 94 deletions

View File

@ -9,7 +9,6 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/grafanads"
)
@ -68,7 +67,7 @@ func (hs *HTTPServer) declareFixedRoles() error {
Grants: []string{string(org.RoleEditor)},
}
if setting.ViewersCanEdit {
if hs.Cfg.ViewersCanEdit {
datasourcesExplorerRole.Grants = append(datasourcesExplorerRole.Grants, string(org.RoleViewer))
}

View File

@ -697,7 +697,7 @@ func setUpACL() {
}
}).Return(result, nil)
guardian.InitLegacyGuardian(store, dashSvc, teamSvc)
guardian.InitLegacyGuardian(setting.NewCfg(), store, dashSvc, teamSvc)
}
func setUpRBACGuardian(t *testing.T) {

View File

@ -65,6 +65,7 @@ func (hs *HTTPServer) registerRoutes() {
reqCanAccessTeams := middleware.AdminOrEditorAndFeatureEnabled(hs.Cfg.EditorsCanAdmin)
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
ensureEditorOrViewerCanEdit := middleware.EnsureEditorOrViewerCanEdit(hs.Cfg)
authorize := ac.Middleware(hs.AccessControl)
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService)
quota := middleware.Quota(hs.QuotaService)
@ -177,7 +178,7 @@ func (hs *HTTPServer) registerRoutes() {
if f, ok := reqSignedIn.(func(c *contextmodel.ReqContext)); ok {
f(c)
}
middleware.EnsureEditorOrViewerCanEdit(c)
ensureEditorOrViewerCanEdit(c)
}, ac.EvalPermission(ac.ActionDatasourcesExplore)), hs.Index)
r.Get("/playlists/", reqSignedIn, hs.Index)

View File

@ -340,6 +340,6 @@ func setUp(confs ...setUpConf) *HTTPServer {
dashSvc := &dashboards.FakeDashboardService{}
qResult := aclMockResp
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(store, dashSvc, teamSvc)
guardian.InitLegacyGuardian(setting.NewCfg(), store, dashSvc, teamSvc)
return hs
}

View File

@ -82,7 +82,7 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(nil, nil).Maybe()
hs.DashboardService = dashSvc
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
guardian.InitLegacyGuardian(setting.NewCfg(), sc.sqlStore, dashSvc, teamSvc)
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec()
assert.Equal(t, 403, sc.resp.Code)
@ -133,7 +133,7 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
dashSvc := dashboards.NewFakeDashboardService(t)
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(nil, errutil.Error{PublicMessage: "some error"}).Maybe()
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
guardian.InitLegacyGuardian(sc.cfg, sc.sqlStore, dashSvc, teamSvc)
d := setUpSnapshotTest(t, 0, ts.URL)
hs := buildHttpServer(d, true)
hs.DashboardService = dashSvc
@ -153,7 +153,7 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
dashSvc := dashboards.NewFakeDashboardService(t)
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(nil, dashboards.ErrDashboardNotFound).Maybe()
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
guardian.InitLegacyGuardian(sc.cfg, sc.sqlStore, dashSvc, teamSvc)
d := setUpSnapshotTest(t, 0, ts.URL)
hs := buildHttpServer(d, true)
hs.DashboardService = dashSvc
@ -185,7 +185,7 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
{Role: &editorRole, Permission: dashboards.PERMISSION_EDIT},
}
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResultACL, nil)
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
guardian.InitLegacyGuardian(sc.cfg, sc.sqlStore, dashSvc, teamSvc)
d := setUpSnapshotTest(t, 0, ts.URL)
hs := buildHttpServer(d, true)
hs.DashboardService = dashSvc

View File

@ -9,12 +9,13 @@ import (
"os"
"testing"
"github.com/grafana/grafana/pkg/services/publicdashboards"
"github.com/grafana/grafana/pkg/services/publicdashboards/api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/publicdashboards"
"github.com/grafana/grafana/pkg/services/publicdashboards/api"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
@ -165,7 +166,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
{Role: &editorRole, Permission: dashboards.PERMISSION_EDIT},
}
dashboardService.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
guardian.InitLegacyGuardian(hs.Cfg, mockSQLStore, dashboardService, teamService)
}
// This tests two scenarios:
@ -274,12 +275,8 @@ func TestDashboardAPIEndpoint(t *testing.T) {
}
setUp := func() {
origCanEdit := setting.ViewersCanEdit
t.Cleanup(func() {
setting.ViewersCanEdit = origCanEdit
})
setting.ViewersCanEdit = false
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
cfg.ViewersCanEdit = false
guardian.InitLegacyGuardian(cfg, mockSQLStore, dashboardService, teamService)
}
// This tests six scenarios:
@ -370,18 +367,14 @@ func TestDashboardAPIEndpoint(t *testing.T) {
role := org.RoleViewer
setUpInner := func() {
origCanEdit := setting.ViewersCanEdit
t.Cleanup(func() {
setting.ViewersCanEdit = origCanEdit
})
setting.ViewersCanEdit = false
cfg.ViewersCanEdit = false
dashboardService := dashboards.NewFakeDashboardService(t)
qResult := []*dashboards.DashboardACLInfoDTO{
{OrgID: 1, DashboardID: 2, UserID: 1, Permission: dashboards.PERMISSION_EDIT},
}
dashboardService.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
guardian.InitLegacyGuardian(cfg, mockSQLStore, dashboardService, teamService)
}
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/abcdefghi",
@ -414,24 +407,20 @@ func TestDashboardAPIEndpoint(t *testing.T) {
role := org.RoleViewer
setUpInner := func() {
origCanEdit := setting.ViewersCanEdit
t.Cleanup(func() {
setting.ViewersCanEdit = origCanEdit
})
setting.ViewersCanEdit = true
cfg.ViewersCanEdit = true
dashboardService := dashboards.NewFakeDashboardService(t)
qResult := []*dashboards.DashboardACLInfoDTO{
{OrgID: 1, DashboardID: 2, UserID: 1, Permission: dashboards.PERMISSION_VIEW},
}
dashboardService.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
guardian.InitLegacyGuardian(cfg, mockSQLStore, dashboardService, teamService)
}
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
setUpInner()
require.True(t, setting.ViewersCanEdit)
require.True(t, cfg.ViewersCanEdit)
sc.sqlStore = mockSQLStore
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
@ -452,18 +441,14 @@ func TestDashboardAPIEndpoint(t *testing.T) {
role := org.RoleViewer
setUpInner := func() {
origCanEdit := setting.ViewersCanEdit
t.Cleanup(func() {
setting.ViewersCanEdit = origCanEdit
})
setting.ViewersCanEdit = true
cfg.ViewersCanEdit = true
dashboardService := dashboards.NewFakeDashboardService(t)
qResult := []*dashboards.DashboardACLInfoDTO{
{OrgID: 1, DashboardID: 2, UserID: 1, Permission: dashboards.PERMISSION_ADMIN},
}
dashboardService.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
guardian.InitLegacyGuardian(cfg, mockSQLStore, dashboardService, teamService)
}
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
@ -509,12 +494,13 @@ func TestDashboardAPIEndpoint(t *testing.T) {
role := org.RoleEditor
setUpInner := func() {
cfg := setting.NewCfg()
dashboardService := dashboards.NewFakeDashboardService(t)
qResult := []*dashboards.DashboardACLInfoDTO{
{OrgID: 1, DashboardID: 2, UserID: 1, Permission: dashboards.PERMISSION_VIEW},
}
dashboardService.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
guardian.InitLegacyGuardian(cfg, mockSQLStore, dashboardService, teamService)
}
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
@ -782,7 +768,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(nil, nil)
qResult := &dashboards.Dashboard{}
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
guardian.InitLegacyGuardian(sqlmock, dashSvc, teamSvc)
guardian.InitLegacyGuardian(setting.NewCfg(), sqlmock, dashSvc, teamSvc)
}
cmd := dtos.CalculateDiffOptions{
@ -901,7 +887,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
qResult2 := []*dashboards.DashboardACLInfoDTO{{OrgID: testOrgID, DashboardID: 1, UserID: testUserID, Permission: dashboards.PERMISSION_EDIT}}
dashboardService.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(qResult2, nil)
guardian.InitLegacyGuardian(mockSQLStore, dashboardService, teamService)
guardian.InitLegacyGuardian(setting.NewCfg(), mockSQLStore, dashboardService, teamService)
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", org.RoleEditor, func(sc *scenarioContext) {
fakeProvisioningService := provisioning.NewProvisioningServiceMock(context.Background())

View File

@ -245,7 +245,7 @@ func createFolderScenario(t *testing.T, desc string, url string, routePattern st
qResult := &dashboards.Dashboard{}
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
store := dbtest.NewFakeDB()
guardian.InitLegacyGuardian(store, dashSvc, teamSvc)
guardian.InitLegacyGuardian(setting.NewCfg(), store, dashSvc, teamSvc)
folderPermissions := acmock.NewMockedPermissionsService()
folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
hs := HTTPServer{

View File

@ -133,7 +133,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
ExternalUserMngInfo: setting.ExternalUserMngInfo,
ExternalUserMngLinkUrl: setting.ExternalUserMngLinkUrl,
ExternalUserMngLinkName: setting.ExternalUserMngLinkName,
ViewersCanEdit: setting.ViewersCanEdit,
ViewersCanEdit: hs.Cfg.ViewersCanEdit,
AngularSupportEnabled: hs.Cfg.AngularSupportEnabled,
EditorsCanAdmin: hs.Cfg.EditorsCanAdmin,
DisableSanitizeHtml: hs.Cfg.DisableSanitizeHtml,

View File

@ -83,9 +83,11 @@ func removeForceLoginParams(str string) string {
return forceLoginParamsRegexp.ReplaceAllString(str, "")
}
func EnsureEditorOrViewerCanEdit(c *contextmodel.ReqContext) {
if !c.SignedInUser.HasRole(org.RoleEditor) && !setting.ViewersCanEdit {
accessForbidden(c)
func EnsureEditorOrViewerCanEdit(cfg *setting.Cfg) func(c *contextmodel.ReqContext) {
return func(c *contextmodel.ReqContext) {
if !c.SignedInUser.HasRole(org.RoleEditor) && !cfg.ViewersCanEdit {
accessForbidden(c)
}
}
}

View File

@ -4,7 +4,6 @@ import (
"context"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/setting"
)
func (s *Service) getUsageStats(ctx context.Context) (map[string]interface{}, error) {
@ -30,7 +29,7 @@ func (s *Service) getUsageStats(ctx context.Context) (map[string]interface{}, er
// FIXME: Move this to accesscontrol OSS.
// FIXME: Access Control OSS usage stats is currently disabled if Enterprise is enabled.
m["stats.authz.viewers_can_edit.count"] = 0
if setting.ViewersCanEdit {
if s.cfg.ViewersCanEdit {
m["stats.authz.viewers_can_edit.count"] = 1
}

View File

@ -836,7 +836,7 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc
accesscontrolmock.New(),
foldertest.NewFakeService(),
)
guardian.InitLegacyGuardian(sqlStore, service, &teamtest.FakeService{})
guardian.InitLegacyGuardian(cfg, sqlStore, service, &teamtest.FakeService{})
savedFolder := saveTestFolder(t, "Saved folder", testOrgID, sqlStore)
savedDashInFolder := saveTestDashboard(t, "Saved dash in folder", testOrgID, savedFolder.ID, sqlStore)

View File

@ -23,7 +23,7 @@ var _ DashboardGuardian = new(AccessControlDashboardGuardian)
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboardId.
func NewAccessControlDashboardGuardian(
ctx context.Context, dashboardId int64, user *user.SignedInUser,
ctx context.Context, cfg *setting.Cfg, dashboardId int64, user *user.SignedInUser,
store db.DB, ac accesscontrol.AccessControl,
folderPermissionsService accesscontrol.FolderPermissionsService,
dashboardPermissionsService accesscontrol.DashboardPermissionsService,
@ -48,6 +48,7 @@ func NewAccessControlDashboardGuardian(
return &AccessControlDashboardGuardian{
ctx: ctx,
cfg: cfg,
log: log.New("dashboard.permissions"),
dashboard: dashboard,
user: user,
@ -61,7 +62,7 @@ func NewAccessControlDashboardGuardian(
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboardUID.
func NewAccessControlDashboardGuardianByUID(
ctx context.Context, dashboardUID string, user *user.SignedInUser,
ctx context.Context, cfg *setting.Cfg, dashboardUID string, user *user.SignedInUser,
store db.DB, ac accesscontrol.AccessControl,
folderPermissionsService accesscontrol.FolderPermissionsService,
dashboardPermissionsService accesscontrol.DashboardPermissionsService,
@ -85,6 +86,7 @@ func NewAccessControlDashboardGuardianByUID(
}
return &AccessControlDashboardGuardian{
cfg: cfg,
ctx: ctx,
log: log.New("dashboard.permissions"),
dashboard: dashboard,
@ -101,13 +103,14 @@ func NewAccessControlDashboardGuardianByUID(
// 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 *dashboards.Dashboard, user *user.SignedInUser,
ctx context.Context, cfg *setting.Cfg, dashboard *dashboards.Dashboard, user *user.SignedInUser,
store db.DB, ac accesscontrol.AccessControl,
folderPermissionsService accesscontrol.FolderPermissionsService,
dashboardPermissionsService accesscontrol.DashboardPermissionsService,
dashboardService dashboards.DashboardService,
) (*AccessControlDashboardGuardian, error) {
return &AccessControlDashboardGuardian{
cfg: cfg,
ctx: ctx,
log: log.New("dashboard.permissions"),
dashboard: dashboard,
@ -121,6 +124,7 @@ func NewAccessControlDashboardGuardianByDashboard(
}
type AccessControlDashboardGuardian struct {
cfg *setting.Cfg
ctx context.Context
log log.Logger
dashboard *dashboards.Dashboard
@ -151,7 +155,7 @@ func (a *AccessControlDashboardGuardian) CanEdit() (bool, error) {
return false, ErrGuardianDashboardNotFound
}
if setting.ViewersCanEdit {
if a.cfg.ViewersCanEdit {
return a.CanView()
}

View File

@ -108,13 +108,14 @@ func TestAccessControlDashboardGuardian_CanSave(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, testDashSvc(t))
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, nil, testDashSvc(t))
can, err := guardian.CanSave()
require.NoError(t, err)
assert.Equal(t, tt.expected, can)
})
}
}
func TestAccessControlDashboardGuardian_CanEdit(t *testing.T) {
tests := []accessControlGuardianTestCase{
{
@ -199,12 +200,11 @@ func TestAccessControlDashboardGuardian_CanEdit(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, testDashSvc(t))
cfg := setting.NewCfg()
cfg.ViewersCanEdit = tt.viewersCanEdit
dashSvc := testDashSvc(t)
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, cfg, dashSvc)
if tt.viewersCanEdit {
setting.ViewersCanEdit = true
defer func() { setting.ViewersCanEdit = false }()
}
can, err := guardian.CanEdit()
require.NoError(t, err)
assert.Equal(t, tt.expected, can)
@ -283,7 +283,7 @@ func TestAccessControlDashboardGuardian_CanView(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, testDashSvc(t))
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, nil, testDashSvc(t))
can, err := guardian.CanView()
require.NoError(t, err)
@ -387,7 +387,7 @@ func TestAccessControlDashboardGuardian_CanAdmin(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, testDashSvc(t))
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, nil, testDashSvc(t))
can, err := guardian.CanAdmin()
require.NoError(t, err)
@ -467,7 +467,7 @@ func TestAccessControlDashboardGuardian_CanDelete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, testDashSvc(t))
guardian, _ := setupAccessControlGuardianTest(t, tt.dashUID, tt.permissions, nil, testDashSvc(t))
can, err := guardian.CanDelete()
require.NoError(t, err)
@ -531,7 +531,7 @@ func TestAccessControlDashboardGuardian_CanCreate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, "0", tt.permissions, nil)
guardian, _ := setupAccessControlGuardianTest(t, "0", tt.permissions, nil, nil)
can, err := guardian.CanCreate(tt.folderID, tt.isFolder)
require.NoError(t, err)
@ -563,7 +563,7 @@ func TestAccessControlDashboardGuardian_GetHiddenACL(t *testing.T) {
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
guardian, _ := setupAccessControlGuardianTest(t, "1", nil, testDashSvc(t))
guardian, _ := setupAccessControlGuardianTest(t, "1", nil, nil, testDashSvc(t))
mocked := accesscontrolmock.NewMockedPermissionsService()
guardian.dashboardPermissionsService = mocked
@ -585,7 +585,10 @@ func TestAccessControlDashboardGuardian_GetHiddenACL(t *testing.T) {
}
}
func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []accesscontrol.Permission, dashboardSvc dashboards.DashboardService) (*AccessControlDashboardGuardian, *dashboards.Dashboard) {
func setupAccessControlGuardianTest(t *testing.T, uid string,
permissions []accesscontrol.Permission,
cfg *setting.Cfg,
dashboardSvc dashboards.DashboardService) (*AccessControlDashboardGuardian, *dashboards.Dashboard) {
t.Helper()
store := db.InitTestDB(t)
@ -626,13 +629,13 @@ func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []acce
require.NoError(t, err)
folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions(
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, foldertest.NewFakeService(), ac, teamSvc, userSvc)
cfg, routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, foldertest.NewFakeService(), ac, teamSvc, userSvc)
require.NoError(t, err)
dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions(
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, foldertest.NewFakeService(), ac, teamSvc, userSvc)
cfg, routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, foldertest.NewFakeService(), ac, teamSvc, userSvc)
require.NoError(t, err)
g, err := NewAccessControlDashboardGuardian(context.Background(), dash.ID, &user.SignedInUser{OrgID: 1}, store, ac, folderPermissions, dashboardPermissions, dashboardSvc)
g, err := NewAccessControlDashboardGuardian(context.Background(), cfg, dash.ID, &user.SignedInUser{OrgID: 1}, store, ac, folderPermissions, dashboardPermissions, dashboardSvc)
require.NoError(t, err)
g.dashboard = dash
return g, dash

View File

@ -42,6 +42,7 @@ type DashboardGuardian interface {
}
type dashboardGuardianImpl struct {
cfg *setting.Cfg
user *user.SignedInUser
dashId int64
orgId int64
@ -73,7 +74,7 @@ var NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId
}
// 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) {
func newDashboardGuardian(ctx context.Context, cfg *setting.Cfg, dashId int64, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
if dashId != 0 {
q := &dashboards.GetDashboardQuery{
ID: dashId,
@ -89,6 +90,7 @@ func newDashboardGuardian(ctx context.Context, dashId int64, orgId int64, user *
}
return &dashboardGuardianImpl{
cfg: cfg,
user: user,
dashId: dashId,
orgId: orgId,
@ -101,7 +103,7 @@ func newDashboardGuardian(ctx context.Context, dashId int64, orgId int64, user *
}
// 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) {
func newDashboardGuardianByUID(ctx context.Context, cfg *setting.Cfg, dashUID string, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
dashID := int64(0)
if dashUID != "" {
q := &dashboards.GetDashboardQuery{
@ -120,6 +122,7 @@ func newDashboardGuardianByUID(ctx context.Context, dashUID string, orgId int64,
}
return &dashboardGuardianImpl{
cfg: cfg,
user: user,
dashId: dashID,
orgId: orgId,
@ -134,8 +137,9 @@ func newDashboardGuardianByUID(ctx context.Context, dashUID string, orgId int64,
// 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 *dashboards.Dashboard, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
func newDashboardGuardianByDashboard(ctx context.Context, cfg *setting.Cfg, dash *dashboards.Dashboard, orgId int64, user *user.SignedInUser, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) (*dashboardGuardianImpl, error) {
return &dashboardGuardianImpl{
cfg: cfg,
user: user,
dashId: dash.ID,
orgId: orgId,
@ -152,7 +156,7 @@ func (g *dashboardGuardianImpl) CanSave() (bool, error) {
}
func (g *dashboardGuardianImpl) CanEdit() (bool, error) {
if setting.ViewersCanEdit {
if g.cfg.ViewersCanEdit {
return g.HasPermission(dashboards.PERMISSION_VIEW)
}

View File

@ -714,7 +714,7 @@ func TestGuardianGetHiddenACL(t *testing.T) {
UserID: 1,
Login: "user1",
}
g, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
g, err := newDashboardGuardian(context.Background(), cfg, dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
require.NoError(t, err)
hiddenACL, err := g.GetHiddenACL(cfg)
@ -735,7 +735,7 @@ func TestGuardianGetHiddenACL(t *testing.T) {
qResult := &dashboards.Dashboard{}
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Run(func(args mock.Arguments) {
}).Return(qResult, nil)
g, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
g, err := newDashboardGuardian(context.Background(), cfg, dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
require.NoError(t, err)
hiddenACL, err := g.GetHiddenACL(cfg)
@ -777,7 +777,7 @@ func TestGuardianGetACLWithoutDuplicates(t *testing.T) {
UserID: 1,
Login: "user1",
}
g, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
g, err := newDashboardGuardian(context.Background(), setting.NewCfg(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
require.NoError(t, err)
acl, err := g.GetACLWithoutDuplicates()

View File

@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/team"
"github.com/grafana/grafana/pkg/services/team/teamtest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
type scenarioContext struct {
@ -54,7 +55,7 @@ func orgRoleScenario(desc string, t *testing.T, role org.RoleType, fn scenarioFu
UID: q.UID,
}
}).Return(qResult, nil)
guard, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, fakeDashboardService, &teamtest.FakeService{})
guard, err := newDashboardGuardian(context.Background(), setting.NewCfg(), dashboardID, orgID, user, store, fakeDashboardService, &teamtest.FakeService{})
require.NoError(t, err)
sc := &scenarioContext{
@ -86,7 +87,7 @@ func apiKeyScenario(desc string, t *testing.T, role org.RoleType, fn scenarioFun
UID: q.UID,
}
}).Return(qResult, nil)
guard, err := newDashboardGuardian(context.Background(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
guard, err := newDashboardGuardian(context.Background(), setting.NewCfg(), dashboardID, orgID, user, store, dashSvc, &teamtest.FakeService{})
require.NoError(t, err)
sc := &scenarioContext{
@ -128,7 +129,7 @@ func permissionScenario(desc string, dashboardID int64, sc *scenarioContext,
}).Return(qResultDash, nil)
sc.permissionScenario = desc
g, err := newDashboardGuardian(context.Background(), dashboardID, sc.givenUser.OrgID, sc.givenUser, store, dashSvc, teamSvc)
g, err := newDashboardGuardian(context.Background(), setting.NewCfg(), dashboardID, sc.givenUser.OrgID, sc.givenUser, store, dashSvc, teamSvc)
require.NoError(t, err)
sc.g = g

View File

@ -8,51 +8,52 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/team"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
type Provider struct{}
func ProvideService(
store db.DB, ac accesscontrol.AccessControl,
cfg *setting.Cfg, store db.DB, ac accesscontrol.AccessControl,
folderPermissionsService accesscontrol.FolderPermissionsService, dashboardPermissionsService accesscontrol.DashboardPermissionsService,
dashboardService dashboards.DashboardService, teamService team.Service,
) *Provider {
if !ac.IsDisabled() {
// TODO: Fix this hack, see https://github.com/grafana/grafana-enterprise/issues/2935
InitAccessControlGuardian(store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
InitAccessControlGuardian(cfg, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
} else {
InitLegacyGuardian(store, dashboardService, teamService)
InitLegacyGuardian(cfg, store, dashboardService, teamService)
}
return &Provider{}
}
func InitLegacyGuardian(store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) {
func InitLegacyGuardian(cfg *setting.Cfg, store db.DB, dashSvc dashboards.DashboardService, teamSvc team.Service) {
New = func(ctx context.Context, dashId int64, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
return newDashboardGuardian(ctx, dashId, orgId, user, store, dashSvc, teamSvc)
return newDashboardGuardian(ctx, cfg, 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)
return newDashboardGuardianByUID(ctx, cfg, dashUID, orgId, user, store, dashSvc, teamSvc)
}
NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
return newDashboardGuardianByDashboard(ctx, dash, orgId, user, store, dashSvc, teamSvc)
return newDashboardGuardianByDashboard(ctx, cfg, dash, orgId, user, store, dashSvc, teamSvc)
}
}
func InitAccessControlGuardian(
store db.DB, ac accesscontrol.AccessControl, folderPermissionsService accesscontrol.FolderPermissionsService,
cfg *setting.Cfg, 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, error) {
return NewAccessControlDashboardGuardian(ctx, dashId, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
return NewAccessControlDashboardGuardian(ctx, cfg, 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)
return NewAccessControlDashboardGuardianByUID(ctx, cfg, dashUID, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
}
NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId int64, user *user.SignedInUser) (DashboardGuardian, error) {
return NewAccessControlDashboardGuardianByDashboard(ctx, dash, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
return NewAccessControlDashboardGuardianByDashboard(ctx, cfg, dash, user, store, ac, folderPermissionsService, dashboardPermissionsService, dashboardService)
}
}

View File

@ -392,7 +392,7 @@ func validateAndUnMarshalArrayResponse(t *testing.T, resp response.Response) lib
func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scenarioContext)) {
t.Helper()
store := dbtest.NewFakeDB()
guardian.InitLegacyGuardian(store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
guardian.InitLegacyGuardian(setting.NewCfg(), store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel")
@ -446,7 +446,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
features, folderPermissions, dashboardPermissions, ac,
foldertest.NewFakeService(),
)
guardian.InitLegacyGuardian(sqlStore, dashboardService, &teamtest.FakeService{})
guardian.InitLegacyGuardian(sqlStore.Cfg, sqlStore, dashboardService, &teamtest.FakeService{})
service := LibraryElementService{
Cfg: sqlStore.Cfg,
SQLStore: sqlStore,

View File

@ -779,7 +779,7 @@ func scenarioWithLibraryPanel(t *testing.T, desc string, fn func(t *testing.T, s
UID: q.UID,
}
}).Return(result, nil)
guardian.InitLegacyGuardian(store, dashSvc, &teamtest.FakeService{})
guardian.InitLegacyGuardian(setting.NewCfg(), store, dashSvc, &teamtest.FakeService{})
t.Helper()
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {

View File

@ -114,7 +114,7 @@ func (s *ServiceImpl) GetNavTree(c *contextmodel.ReqContext, hasEditPerm bool, p
}
canExplore := func(context *contextmodel.ReqContext) bool {
return c.OrgRole == org.RoleAdmin || c.OrgRole == org.RoleEditor || setting.ViewersCanEdit
return c.OrgRole == org.RoleAdmin || c.OrgRole == org.RoleEditor || s.cfg.ViewersCanEdit
}
if setting.ExploreEnabled && hasAccess(canExplore, ac.EvalPermission(ac.ActionDatasourcesExplore)) {

View File

@ -102,7 +102,6 @@ var (
ExternalUserMngLinkUrl string
ExternalUserMngLinkName string
ExternalUserMngInfo string
ViewersCanEdit bool
// HTTP auth
SigV4AuthEnabled bool
@ -330,6 +329,7 @@ type Cfg struct {
// DistributedCache
RemoteCacheOptions *RemoteCacheOptions
ViewersCanEdit bool
EditorsCanAdmin bool
ApiKeyMaxSecondsToLive int64
@ -1567,7 +1567,7 @@ func readUserSettings(iniFile *ini.File, cfg *Cfg) error {
ExternalUserMngLinkName = valueAsString(users, "external_manage_link_name", "")
ExternalUserMngInfo = valueAsString(users, "external_manage_info", "")
ViewersCanEdit = users.Key("viewers_can_edit").MustBool(false)
cfg.ViewersCanEdit = users.Key("viewers_can_edit").MustBool(false)
cfg.EditorsCanAdmin = users.Key("editors_can_admin").MustBool(false)
userInviteMaxLifetimeVal := valueAsString(users, "user_invite_max_lifetime_duration", "24h")