mirror of
https://github.com/grafana/grafana.git
synced 2025-07-28 16:22:18 +08:00
Authz: Remove use of SignedInUser copy for permission evaluation (#78448)
* remove use of SignedInUserCopies * add extra safety to not cross assign permissions unwind circular dependency dashboardacl->dashboardaccess fix missing import * correctly set teams for permissions * fix missing inits * nit: check err * exit early for api keys
This commit is contained in:
@ -13,6 +13,7 @@ import (
|
||||
alertmodels "github.com/grafana/grafana/pkg/services/alerting/models"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels_config"
|
||||
@ -113,7 +114,7 @@ func (hs *HTTPServer) GetAlerts(c *contextmodel.ReqContext) response.Response {
|
||||
DashboardIds: dashboardIDs,
|
||||
Type: string(model.DashHitDB),
|
||||
FolderIds: folderIDs, // nolint:staticcheck
|
||||
Permission: dashboards.PERMISSION_VIEW,
|
||||
Permission: dashboardaccess.PERMISSION_VIEW,
|
||||
}
|
||||
|
||||
hits, err := hs.SearchService.SearchHandler(c.Req.Context(), &searchQuery)
|
||||
|
@ -64,7 +64,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
|
||||
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
|
||||
authorize := ac.Middleware(hs.AccessControl)
|
||||
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService)
|
||||
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService, hs.teamService)
|
||||
quota := middleware.Quota(hs.QuotaService)
|
||||
|
||||
r := hs.RouteRegister
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
@ -166,10 +167,10 @@ func (hs *HTTPServer) UpdateDashboardPermissions(c *contextmodel.ReqContext) res
|
||||
return response.Success("Dashboard permissions updated")
|
||||
}
|
||||
|
||||
var dashboardPermissionMap = map[string]dashboards.PermissionType{
|
||||
"View": dashboards.PERMISSION_VIEW,
|
||||
"Edit": dashboards.PERMISSION_EDIT,
|
||||
"Admin": dashboards.PERMISSION_ADMIN,
|
||||
var dashboardPermissionMap = map[string]dashboardaccess.PermissionType{
|
||||
"View": dashboardaccess.PERMISSION_VIEW,
|
||||
"Edit": dashboardaccess.PERMISSION_EDIT,
|
||||
"Admin": dashboardaccess.PERMISSION_ADMIN,
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getDashboardACL(ctx context.Context, user identity.Requester, dashboard *dashboards.Dashboard) ([]*dashboards.DashboardACLInfoDTO, error) {
|
||||
@ -313,11 +314,11 @@ func (hs *HTTPServer) updateDashboardAccessControl(ctx context.Context, orgID in
|
||||
func validatePermissionsUpdate(apiCmd dtos.UpdateDashboardACLCommand) error {
|
||||
for _, item := range apiCmd.Items {
|
||||
if item.UserID > 0 && item.TeamID > 0 {
|
||||
return dashboards.ErrPermissionsWithUserAndTeamNotAllowed
|
||||
return dashboardaccess.ErrPermissionsWithUserAndTeamNotAllowed
|
||||
}
|
||||
|
||||
if (item.UserID > 0 || item.TeamID > 0) && item.Role != nil {
|
||||
return dashboards.ErrPermissionsWithRoleNotAllowed
|
||||
return dashboardaccess.ErrPermissionsWithRoleNotAllowed
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dtos
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
)
|
||||
|
||||
@ -21,5 +21,5 @@ type DashboardACLUpdateItem struct {
|
||||
// * `2` - Edit
|
||||
// * `4` - Admin
|
||||
// Enum: 1,2,4
|
||||
Permission dashboards.PermissionType `json:"permission"`
|
||||
Permission dashboardaccess.PermissionType `json:"permission"`
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
@ -186,15 +187,15 @@ func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int
|
||||
}
|
||||
|
||||
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
|
||||
UserID: userID, Permission: dashboards.PERMISSION_ADMIN.String(),
|
||||
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
|
||||
isNested := folder.ParentUID != ""
|
||||
if !isNested || !hs.Features.IsEnabled(ctx, featuremgmt.FlagNestedFolders) {
|
||||
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
}
|
||||
|
||||
@ -449,7 +450,7 @@ func (hs *HTTPServer) searchFolders(c *contextmodel.ReqContext) ([]*folder.Folde
|
||||
Limit: c.QueryInt64("limit"),
|
||||
OrgId: c.SignedInUser.GetOrgID(),
|
||||
Type: "dash-folder",
|
||||
Permission: dashboards.PERMISSION_VIEW,
|
||||
Permission: dashboardaccess.PERMISSION_VIEW,
|
||||
Page: c.QueryInt64("page"),
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
dashboardservice "github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@ -270,7 +271,7 @@ func setupDB(b testing.TB) benchScenario {
|
||||
UserID: userID,
|
||||
TeamID: teamID,
|
||||
OrgID: orgID,
|
||||
Permission: dashboards.PERMISSION_VIEW,
|
||||
Permission: dashboardaccess.PERMISSION_VIEW,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
})
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@ -118,10 +119,10 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *contextmodel.ReqContext) respon
|
||||
return response.Success("Folder permissions updated")
|
||||
}
|
||||
|
||||
var folderPermissionMap = map[string]dashboards.PermissionType{
|
||||
"View": dashboards.PERMISSION_VIEW,
|
||||
"Edit": dashboards.PERMISSION_EDIT,
|
||||
"Admin": dashboards.PERMISSION_ADMIN,
|
||||
var folderPermissionMap = map[string]dashboardaccess.PermissionType{
|
||||
"View": dashboardaccess.PERMISSION_VIEW,
|
||||
"Edit": dashboardaccess.PERMISSION_EDIT,
|
||||
"Admin": dashboardaccess.PERMISSION_ADMIN,
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getFolderACL(ctx context.Context, user identity.Requester, folder *folder.Folder) ([]*dashboards.DashboardACLInfoDTO, error) {
|
||||
|
@ -437,6 +437,7 @@ func TestGetOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
|
||||
}
|
||||
hs.authInfoService = &authinfotest.FakeService{}
|
||||
hs.userService = &usertest.FakeUserService{ExpectedSignedInUser: userWithPermissions(1, tc.permissions)}
|
||||
hs.accesscontrolService = &actest.FakeService{}
|
||||
})
|
||||
|
||||
u := userWithPermissions(1, tc.permissions)
|
||||
@ -482,6 +483,7 @@ func TestPostOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
|
||||
ExpectedUser: &user.User{},
|
||||
ExpectedSignedInUser: userWithPermissions(1, tt.permissions),
|
||||
}
|
||||
hs.accesscontrolService = &actest.FakeService{}
|
||||
})
|
||||
|
||||
u := userWithPermissions(1, tt.permissions)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
"github.com/grafana/grafana/pkg/services/search/model"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -28,14 +28,14 @@ func (hs *HTTPServer) Search(c *contextmodel.ReqContext) response.Response {
|
||||
page := c.QueryInt64("page")
|
||||
dashboardType := c.Query("type")
|
||||
sort := c.Query("sort")
|
||||
permission := dashboards.PERMISSION_VIEW
|
||||
permission := dashboardaccess.PERMISSION_VIEW
|
||||
|
||||
if limit > 5000 {
|
||||
return response.Error(422, "Limit is above maximum allowed (5000), use page parameter to access hits beyond limit", nil)
|
||||
}
|
||||
|
||||
if c.Query("permission") == "Edit" {
|
||||
permission = dashboards.PERMISSION_EDIT
|
||||
permission = dashboardaccess.PERMISSION_EDIT
|
||||
}
|
||||
|
||||
dbIDs := make([]int64, 0)
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
|
||||
@ -63,7 +63,7 @@ func (sb *SQLBuilder) AddParams(params ...any) {
|
||||
sb.params = append(sb.params, params...)
|
||||
}
|
||||
|
||||
func (sb *SQLBuilder) WriteDashboardPermissionFilter(user identity.Requester, permission dashboards.PermissionType, queryType string) {
|
||||
func (sb *SQLBuilder) WriteDashboardPermissionFilter(user identity.Requester, permission dashboardaccess.PermissionType, queryType string) {
|
||||
var (
|
||||
sql string
|
||||
params []any
|
||||
|
@ -104,26 +104,20 @@ type User struct {
|
||||
// HasGlobalAccess checks user access with globally assigned permissions only
|
||||
func HasGlobalAccess(ac AccessControl, service Service, c *contextmodel.ReqContext) func(evaluator Evaluator) bool {
|
||||
return func(evaluator Evaluator) bool {
|
||||
userCopy := *c.SignedInUser
|
||||
userCopy.OrgID = GlobalOrgID
|
||||
userCopy.OrgRole = ""
|
||||
userCopy.OrgName = ""
|
||||
if userCopy.Permissions[GlobalOrgID] == nil {
|
||||
permissions, err := service.GetUserPermissions(c.Req.Context(), &userCopy, Options{})
|
||||
var targetOrgID int64 = GlobalOrgID
|
||||
tmpUser, err := makeTmpUser(c.Req.Context(), service, nil, nil, c.SignedInUser, targetOrgID)
|
||||
if err != nil {
|
||||
c.Logger.Error("Failed fetching permissions for user", "userID", userCopy.UserID, "error", err)
|
||||
}
|
||||
userCopy.Permissions[GlobalOrgID] = GroupScopesByAction(permissions)
|
||||
deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err))
|
||||
}
|
||||
|
||||
hasAccess, err := ac.Evaluate(c.Req.Context(), &userCopy, evaluator)
|
||||
hasAccess, err := ac.Evaluate(c.Req.Context(), tmpUser, evaluator)
|
||||
if err != nil {
|
||||
c.Logger.Error("Error from access control system", "error", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// set on user so we don't fetch global permissions every time this is called
|
||||
c.SignedInUser.Permissions[GlobalOrgID] = userCopy.Permissions[GlobalOrgID]
|
||||
c.SignedInUser.Permissions[tmpUser.GetOrgID()] = tmpUser.GetPermissions()
|
||||
|
||||
return hasAccess
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/pluginutils"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -116,17 +115,10 @@ func (s *Service) getUserPermissions(ctx context.Context, user identity.Requeste
|
||||
}
|
||||
}
|
||||
|
||||
namespace, identifier := user.GetNamespacedID()
|
||||
|
||||
var userID int64
|
||||
switch namespace {
|
||||
case authn.NamespaceUser, authn.NamespaceServiceAccount:
|
||||
var err error
|
||||
userID, err = strconv.ParseInt(identifier, 10, 64)
|
||||
userID, err := identity.UserIdentifier(user.GetNamespacedID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
dbPermissions, err := s.store.GetUserPermissions(ctx, accesscontrol.GetUserPermissionsQuery{
|
||||
OrgID: user.GetOrgID(),
|
||||
|
@ -13,6 +13,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"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/services/user/usertest"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -32,6 +34,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
acService accesscontrol.Service
|
||||
userCache user.Service
|
||||
ctxSignedInUser *user.SignedInUser
|
||||
teamService team.Service
|
||||
expectedStatus int
|
||||
}{
|
||||
{
|
||||
@ -46,6 +49,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
acService: &actest.FakeService{
|
||||
ExpectedPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}},
|
||||
},
|
||||
teamService: &teamtest.FakeService{},
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
@ -58,6 +62,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
acService: &actest.FakeService{},
|
||||
userCache: &usertest.FakeUserService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
@ -69,6 +74,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
accessControl: ac,
|
||||
userCache: &usertest.FakeUserService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
acService: &actest.FakeService{},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
@ -80,8 +86,11 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
evaluator: accesscontrol.EvalPermission("users:read", "users:*"),
|
||||
accessControl: ac,
|
||||
userCache: &usertest.FakeUserService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{accesscontrol.GlobalOrgID: {"users:read": {"users:*"}}}},
|
||||
acService: &actest.FakeService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
acService: &actest.FakeService{
|
||||
ExpectedPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}},
|
||||
},
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
@ -93,6 +102,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
accessControl: ac,
|
||||
userCache: &usertest.FakeUserService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
acService: &actest.FakeService{},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
@ -106,6 +116,20 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
userCache: &usertest.FakeUserService{ExpectedError: fmt.Errorf("user not found")},
|
||||
acService: &actest.FakeService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
name: "should return 403 early when api key org ID doesn't match",
|
||||
orgIDGetter: func(c *contextmodel.ReqContext) (int64, error) {
|
||||
return 2, nil
|
||||
},
|
||||
evaluator: accesscontrol.EvalPermission("users:read", "users:*"),
|
||||
accessControl: ac,
|
||||
userCache: &usertest.FakeUserService{},
|
||||
acService: &actest.FakeService{},
|
||||
ctxSignedInUser: &user.SignedInUser{ApiKeyID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
@ -118,6 +142,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
acService: &actest.FakeService{
|
||||
ExpectedPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}},
|
||||
},
|
||||
teamService: &teamtest.FakeService{},
|
||||
userCache: &usertest.FakeUserService{
|
||||
GetSignedInUserFn: func(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
|
||||
return &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: nil}, nil
|
||||
@ -133,6 +158,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
},
|
||||
evaluator: accesscontrol.EvalPermission("users:read", "users:*"),
|
||||
accessControl: ac,
|
||||
teamService: &teamtest.FakeService{},
|
||||
acService: &actest.FakeService{
|
||||
ExpectedPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}},
|
||||
},
|
||||
@ -151,6 +177,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
},
|
||||
evaluator: accesscontrol.EvalPermission("users:read", "users:*"),
|
||||
accessControl: ac,
|
||||
teamService: &teamtest.FakeService{},
|
||||
acService: &actest.FakeService{
|
||||
ExpectedErr: fmt.Errorf("failed to get user permissions"),
|
||||
},
|
||||
@ -172,6 +199,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
acService: &actest.FakeService{},
|
||||
userCache: &usertest.FakeUserService{},
|
||||
ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}},
|
||||
teamService: &teamtest.FakeService{},
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
}
|
||||
@ -189,6 +217,7 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) {
|
||||
tc.accessControl,
|
||||
service,
|
||||
tc.userCache,
|
||||
tc.teamService,
|
||||
)(tc.orgIDGetter, tc.evaluator)
|
||||
|
||||
// Create test server
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
rs "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgimpl"
|
||||
@ -248,7 +248,7 @@ func createUserAndTeam(t *testing.T, userSrv user.Service, teamSvc team.Service,
|
||||
team, err := teamSvc.CreateTeam("team", "", orgID)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = teamSvc.AddTeamMember(user.ID, orgID, team.ID, false, dashboards.PERMISSION_VIEW)
|
||||
err = teamSvc.AddTeamMember(user.ID, orgID, team.ID, false, dashboardaccess.PERMISSION_VIEW)
|
||||
require.NoError(t, err)
|
||||
|
||||
return user, team
|
||||
@ -296,7 +296,7 @@ func createUsersAndTeams(t *testing.T, svcs helperServices, orgID int64, users [
|
||||
team, err := svcs.teamSvc.CreateTeam(fmt.Sprintf("team%v", i+1), "", orgID)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svcs.teamSvc.AddTeamMember(user.ID, orgID, team.ID, false, dashboards.PERMISSION_VIEW)
|
||||
err = svcs.teamSvc.AddTeamMember(user.ID, orgID, team.ID, false, dashboardaccess.PERMISSION_VIEW)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svcs.orgSvc.UpdateOrgUser(context.Background(),
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"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"
|
||||
@ -179,60 +180,108 @@ type userCache interface {
|
||||
GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error)
|
||||
}
|
||||
|
||||
func AuthorizeInOrgMiddleware(ac AccessControl, service Service, cache userCache) func(OrgIDGetter, Evaluator) web.Handler {
|
||||
type teamService interface {
|
||||
GetTeamIDsByUser(ctx context.Context, query *team.GetTeamIDsByUserQuery) ([]int64, error)
|
||||
}
|
||||
|
||||
func AuthorizeInOrgMiddleware(ac AccessControl, service Service, userService userCache, teamService teamService) func(OrgIDGetter, Evaluator) web.Handler {
|
||||
return func(getTargetOrg OrgIDGetter, evaluator Evaluator) web.Handler {
|
||||
return func(c *contextmodel.ReqContext) {
|
||||
// We need to copy the user here because we're going to mutate it
|
||||
userCopy := *(c.SignedInUser)
|
||||
targetOrgID, err := getTargetOrg(c)
|
||||
if err != nil {
|
||||
deny(c, nil, fmt.Errorf("failed to get target org: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
if userCopy.OrgID != targetOrgID {
|
||||
switch targetOrgID {
|
||||
case GlobalOrgID:
|
||||
userCopy.OrgID = GlobalOrgID
|
||||
userCopy.OrgRole = org.RoleNone
|
||||
userCopy.OrgName = ""
|
||||
default:
|
||||
query := user.GetSignedInUserQuery{UserID: c.UserID, OrgID: targetOrgID}
|
||||
queryResult, err := cache.GetSignedInUserWithCacheCtx(c.Req.Context(), &query)
|
||||
tmpUser, err := makeTmpUser(c.Req.Context(), service, userService, teamService, c.SignedInUser, targetOrgID)
|
||||
if err != nil {
|
||||
deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err))
|
||||
return
|
||||
}
|
||||
userCopy.OrgID = queryResult.OrgID
|
||||
userCopy.OrgName = queryResult.OrgName
|
||||
userCopy.OrgRole = queryResult.OrgRole
|
||||
}
|
||||
}
|
||||
|
||||
if userCopy.Permissions[targetOrgID] == nil {
|
||||
permissions, err := service.GetUserPermissions(c.Req.Context(), &userCopy, Options{})
|
||||
if err != nil {
|
||||
deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err))
|
||||
}
|
||||
|
||||
// guard against nil map
|
||||
if userCopy.Permissions == nil {
|
||||
userCopy.Permissions = make(map[int64]map[string][]string)
|
||||
}
|
||||
userCopy.Permissions[targetOrgID] = GroupScopesByAction(permissions)
|
||||
}
|
||||
|
||||
authorize(c, ac, &userCopy, evaluator)
|
||||
authorize(c, ac, tmpUser, evaluator)
|
||||
|
||||
// guard against nil map
|
||||
if c.SignedInUser.Permissions == nil {
|
||||
c.SignedInUser.Permissions = make(map[int64]map[string][]string)
|
||||
}
|
||||
c.SignedInUser.Permissions[targetOrgID] = userCopy.Permissions[targetOrgID]
|
||||
c.SignedInUser.Permissions[tmpUser.GetOrgID()] = tmpUser.GetPermissions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// makeTmpUser creates a temporary user that can be used to evaluate access across orgs.
|
||||
func makeTmpUser(ctx context.Context, service Service, cache userCache,
|
||||
teamService teamService, reqUser identity.Requester, targetOrgID int64) (identity.Requester, error) {
|
||||
tmpUser := &user.SignedInUser{
|
||||
OrgID: reqUser.GetOrgID(),
|
||||
OrgName: reqUser.GetOrgName(),
|
||||
OrgRole: reqUser.GetOrgRole(),
|
||||
IsGrafanaAdmin: reqUser.GetIsGrafanaAdmin(),
|
||||
Login: reqUser.GetLogin(),
|
||||
Teams: reqUser.GetTeams(),
|
||||
Permissions: map[int64]map[string][]string{
|
||||
reqUser.GetOrgID(): reqUser.GetPermissions(),
|
||||
},
|
||||
}
|
||||
|
||||
namespace, identifier := reqUser.GetNamespacedID()
|
||||
id, _ := identity.IntIdentifier(namespace, identifier)
|
||||
switch namespace {
|
||||
case identity.NamespaceUser:
|
||||
tmpUser.UserID = id
|
||||
case identity.NamespaceAPIKey:
|
||||
tmpUser.ApiKeyID = id
|
||||
if tmpUser.OrgID != targetOrgID {
|
||||
return nil, errors.New("API key does not belong to target org")
|
||||
}
|
||||
case identity.NamespaceServiceAccount:
|
||||
tmpUser.UserID = id
|
||||
tmpUser.IsServiceAccount = true
|
||||
}
|
||||
|
||||
if tmpUser.OrgID != targetOrgID {
|
||||
switch targetOrgID {
|
||||
case GlobalOrgID:
|
||||
tmpUser.OrgID = GlobalOrgID
|
||||
tmpUser.OrgRole = org.RoleNone
|
||||
tmpUser.OrgName = ""
|
||||
tmpUser.Teams = []int64{}
|
||||
default:
|
||||
if cache == nil {
|
||||
return nil, errors.New("user cache is nil")
|
||||
}
|
||||
query := user.GetSignedInUserQuery{UserID: tmpUser.UserID, OrgID: targetOrgID}
|
||||
queryResult, err := cache.GetSignedInUserWithCacheCtx(ctx, &query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmpUser.OrgID = queryResult.OrgID
|
||||
tmpUser.OrgName = queryResult.OrgName
|
||||
tmpUser.OrgRole = queryResult.OrgRole
|
||||
|
||||
if teamService != nil {
|
||||
teamIDs, err := teamService.GetTeamIDsByUser(ctx, &team.GetTeamIDsByUserQuery{OrgID: targetOrgID, UserID: tmpUser.UserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmpUser.Teams = teamIDs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tmpUser.Permissions[targetOrgID] == nil || len(tmpUser.Permissions[targetOrgID]) == 0 {
|
||||
permissions, err := service.GetUserPermissions(ctx, tmpUser, Options{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tmpUser.Permissions[targetOrgID] = GroupScopesByAction(permissions)
|
||||
}
|
||||
|
||||
return tmpUser, nil
|
||||
}
|
||||
|
||||
func UseOrgFromContextParams(c *contextmodel.ReqContext) (int64, error) {
|
||||
orgID, err := strconv.ParseInt(web.Params(c.Req)[":orgId"], 10, 64)
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements"
|
||||
@ -87,7 +88,7 @@ func ProvideTeamPermissions(
|
||||
case "Member":
|
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, 0)
|
||||
case "Admin":
|
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, dashboards.PERMISSION_ADMIN)
|
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, dashboardaccess.PERMISSION_ADMIN)
|
||||
case "":
|
||||
return teamimpl.RemoveTeamMemberHook(session, &team.RemoveTeamMemberCommand{
|
||||
OrgID: orgID,
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
alertmodels "github.com/grafana/grafana/pkg/services/alerting/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/tag"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -167,7 +167,7 @@ func (ss *sqlStore) HandleAlertsQuery(ctx context.Context, query *alertmodels.Ge
|
||||
builder.Write(")")
|
||||
}
|
||||
|
||||
builder.WriteDashboardPermissionFilter(query.User, dashboards.PERMISSION_VIEW, "")
|
||||
builder.WriteDashboardPermissionFilter(query.User, dashboardaccess.PERMISSION_VIEW, "")
|
||||
|
||||
builder.Write(" ORDER BY name ASC")
|
||||
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
||||
@ -74,7 +74,7 @@ func (authz *AuthService) userVisibleDashboards(ctx context.Context, user identi
|
||||
}
|
||||
|
||||
filters := []any{
|
||||
permissions.NewAccessControlDashboardPermissionFilter(user, dashboards.PERMISSION_VIEW, searchstore.TypeDashboard, authz.features, recursiveQueriesSupported),
|
||||
permissions.NewAccessControlDashboardPermissionFilter(user, dashboardaccess.PERMISSION_VIEW, searchstore.TypeDashboard, authz.features, recursiveQueriesSupported),
|
||||
searchstore.OrgFilter{OrgId: orgID},
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package dashboards
|
||||
package dashboardaccess
|
||||
|
||||
import (
|
||||
"errors"
|
@ -1,4 +1,4 @@
|
||||
package dashboards
|
||||
package dashboardaccess
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/kinds/dashboard"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
@ -419,7 +420,7 @@ type DashboardACL struct {
|
||||
UserID int64 `xorm:"user_id"`
|
||||
TeamID int64 `xorm:"team_id"`
|
||||
Role *org.RoleType // pointer to be nullable
|
||||
Permission PermissionType
|
||||
Permission dashboardaccess.PermissionType
|
||||
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
@ -446,7 +447,7 @@ type DashboardACLInfoDTO struct {
|
||||
TeamAvatarURL string `json:"teamAvatarUrl" xorm:"team_avatar_url"`
|
||||
Team string `json:"team"`
|
||||
Role *org.RoleType `json:"role,omitempty"`
|
||||
Permission PermissionType `json:"permission"`
|
||||
Permission dashboardaccess.PermissionType `json:"permission"`
|
||||
PermissionName string `json:"permissionName"`
|
||||
UID string `json:"uid" xorm:"uid"`
|
||||
Title string `json:"title"`
|
||||
@ -490,7 +491,7 @@ type FindPersistedDashboardsQuery struct {
|
||||
Tags []string
|
||||
Limit int64
|
||||
Page int64
|
||||
Permission PermissionType
|
||||
Permission dashboardaccess.PermissionType
|
||||
Sort model.SortOption
|
||||
|
||||
Filters []any
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
@ -502,15 +503,15 @@ func (dr *DashboardServiceImpl) setDefaultPermissions(ctx context.Context, dto *
|
||||
dr.log.Error("Could not make user admin", "dashboard", dash.Title, "namespaceID", namespaceID, "userID", userID, "error", err)
|
||||
} else if namespaceID == identity.NamespaceUser && userID > 0 {
|
||||
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
|
||||
UserID: userID, Permission: dashboards.PERMISSION_ADMIN.String(),
|
||||
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if !inFolder {
|
||||
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
@ -288,7 +289,7 @@ func (l *LibraryElementService) getLibraryElements(c context.Context, store db.D
|
||||
builder.Write(getFromLibraryElementDTOWithMeta(store.GetDialect()))
|
||||
builder.Write(" INNER JOIN dashboard AS dashboard on le.folder_id = dashboard.id AND le.folder_id <> 0")
|
||||
writeParamSelectorSQL(&builder, params...)
|
||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboards.PERMISSION_VIEW, "")
|
||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboardaccess.PERMISSION_VIEW, "")
|
||||
builder.Write(` OR dashboard.id=0`)
|
||||
if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElements); err != nil {
|
||||
return err
|
||||
@ -421,7 +422,7 @@ func (l *LibraryElementService) getAllLibraryElements(c context.Context, signedI
|
||||
return err
|
||||
}
|
||||
if !signedInUser.HasRole(org.RoleAdmin) {
|
||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboards.PERMISSION_VIEW, "")
|
||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboardaccess.PERMISSION_VIEW, "")
|
||||
}
|
||||
if query.SortDirection == search.SortAlphaDesc.Name {
|
||||
builder.Write(" ORDER BY 1 DESC")
|
||||
@ -665,7 +666,7 @@ func (l *LibraryElementService) getConnections(c context.Context, signedInUser i
|
||||
builder.Write(" INNER JOIN dashboard AS dashboard on lec.connection_id = dashboard.id")
|
||||
builder.Write(` WHERE lec.element_id=?`, element.ID)
|
||||
if signedInUser.GetOrgRole() != org.RoleAdmin {
|
||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboards.PERMISSION_VIEW, "")
|
||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboardaccess.PERMISSION_VIEW, "")
|
||||
}
|
||||
if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElementConnections); err != nil {
|
||||
return err
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
migmodels "github.com/grafana/grafana/pkg/services/ngalert/migration/models"
|
||||
@ -42,12 +43,12 @@ var (
|
||||
// generalAlertingFolderTitle is the title of the general alerting folder. This is used for dashboard alerts in the general folder.
|
||||
generalAlertingFolderTitle = "General Alerting"
|
||||
|
||||
// permissionMap maps the "friendly" permission name for a ResourcePermissions actions to the dashboards.PermissionType.
|
||||
// permissionMap maps the "friendly" permission name for a ResourcePermissions actions to the dashboardaccess.PermissionType.
|
||||
// A sort of reverse accesscontrol Service.MapActions similar to api.dashboardPermissionMap.
|
||||
permissionMap = map[string]dashboards.PermissionType{
|
||||
"View": dashboards.PERMISSION_VIEW,
|
||||
"Edit": dashboards.PERMISSION_EDIT,
|
||||
"Admin": dashboards.PERMISSION_ADMIN,
|
||||
permissionMap = map[string]dashboardaccess.PermissionType{
|
||||
"View": dashboardaccess.PERMISSION_VIEW,
|
||||
"Edit": dashboardaccess.PERMISSION_EDIT,
|
||||
"Admin": dashboardaccess.PERMISSION_ADMIN,
|
||||
}
|
||||
)
|
||||
|
||||
@ -186,11 +187,11 @@ func isBasic(roleName string) bool {
|
||||
// There are two role types that we consider:
|
||||
// - managed (ex. managed:users:1:permissions, managed:builtins:editor:permissions, managed:teams:1:permissions):
|
||||
// These are the only roles that exist in OSS. For each of these roles, we add the actions of the highest
|
||||
// dashboards.PermissionType between the folder and the dashboard. Permissions from the folder are inherited.
|
||||
// dashboardaccess.PermissionType between the folder and the dashboard. Permissions from the folder are inherited.
|
||||
// The added actions should have scope=folder:uid:xxxxxx, where xxxxxx is the new folder uid.
|
||||
// - basic (ex. basic:admin, basic:editor):
|
||||
// These are roles used in enterprise. Every user should have one of these roles. They should be considered
|
||||
// equivalent to managed:builtins. The highest dashboards.PermissionType between the two should be used.
|
||||
// equivalent to managed:builtins. The highest dashboardaccess.PermissionType between the two should be used.
|
||||
//
|
||||
// There are two role types that we do not consider:
|
||||
// - fixed: (ex. fixed:dashboards:reader, fixed:dashboards:writer):
|
||||
@ -205,7 +206,7 @@ func isBasic(roleName string) bool {
|
||||
// For now, we choose the simpler approach of handling managed and basic roles. Fixed and custom roles will not
|
||||
// be taken into account, but we will log a warning if they had the potential to override the folder permissions.
|
||||
func (om *OrgMigration) convertResourcePerms(rperms []accesscontrol.ResourcePermission) ([]accesscontrol.SetResourcePermissionCommand, []accesscontrol.ResourcePermission) {
|
||||
keep := make(map[accesscontrol.SetResourcePermissionCommand]dashboards.PermissionType)
|
||||
keep := make(map[accesscontrol.SetResourcePermissionCommand]dashboardaccess.PermissionType)
|
||||
unusedPerms := make([]accesscontrol.ResourcePermission, 0)
|
||||
for _, p := range rperms {
|
||||
if p.IsManaged || p.IsInherited || isBasic(p.RoleName) {
|
||||
@ -254,8 +255,8 @@ func (om *OrgMigration) convertResourcePerms(rperms []accesscontrol.ResourcePerm
|
||||
|
||||
// potentialOverrides returns a map of roles from unusedOldPerms that have dashboard permissions that could potentially
|
||||
// override the given folder permissions in newPerms. These overrides are always to increase permissions not decrease them.
|
||||
func potentialOverrides(unusedOldPerms []accesscontrol.ResourcePermission, newPerms []accesscontrol.SetResourcePermissionCommand) map[string]dashboards.PermissionType {
|
||||
var lowestPermission dashboards.PermissionType
|
||||
func potentialOverrides(unusedOldPerms []accesscontrol.ResourcePermission, newPerms []accesscontrol.SetResourcePermissionCommand) map[string]dashboardaccess.PermissionType {
|
||||
var lowestPermission dashboardaccess.PermissionType
|
||||
for _, p := range newPerms {
|
||||
if p.BuiltinRole == string(org.RoleEditor) || p.BuiltinRole == string(org.RoleViewer) {
|
||||
pType := permissionMap[p.Permission]
|
||||
@ -265,18 +266,18 @@ func potentialOverrides(unusedOldPerms []accesscontrol.ResourcePermission, newPe
|
||||
}
|
||||
}
|
||||
|
||||
nonManagedPermissionTypes := make(map[string]dashboards.PermissionType)
|
||||
nonManagedPermissionTypes := make(map[string]dashboardaccess.PermissionType)
|
||||
for _, p := range unusedOldPerms {
|
||||
existing, ok := nonManagedPermissionTypes[p.RoleName]
|
||||
if ok && existing == dashboards.PERMISSION_EDIT {
|
||||
if ok && existing == dashboardaccess.PERMISSION_EDIT {
|
||||
// We've already handled the highest permission we care about, no need to check this role anymore.
|
||||
continue
|
||||
}
|
||||
|
||||
if p.Contains([]string{dashboards.ActionDashboardsWrite}) {
|
||||
existing = dashboards.PERMISSION_EDIT
|
||||
existing = dashboardaccess.PERMISSION_EDIT
|
||||
} else if p.Contains([]string{dashboards.ActionDashboardsRead}) {
|
||||
existing = dashboards.PERMISSION_VIEW
|
||||
existing = dashboardaccess.PERMISSION_VIEW
|
||||
}
|
||||
|
||||
if existing > lowestPermission && existing > nonManagedPermissionTypes[p.RoleName] {
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/alerting/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
ngModels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
@ -245,8 +246,8 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
basicFolder := genFolder(t, 1, "f_1")
|
||||
basicDashboard := genDashboard(t, 2, "d_1", basicFolder.ID)
|
||||
defaultPerms := genPerms(
|
||||
accesscontrol.SetResourcePermissionCommand{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
accesscontrol.SetResourcePermissionCommand{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
accesscontrol.SetResourcePermissionCommand{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
accesscontrol.SetResourcePermissionCommand{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
)
|
||||
|
||||
basicAlert1 := genLegacyAlert("alert1", basicDashboard.ID, func(a *models.Alert) { a.PanelID = 1 })
|
||||
@ -304,8 +305,8 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
dashboards: []*dashboards.Dashboard{basicDashboard},
|
||||
dashboardPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
basicDashboard.UID: {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_VIEW.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_VIEW.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
},
|
||||
alerts: []*models.Alert{basicAlert1},
|
||||
@ -314,8 +315,8 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert(basicAlert1.Name, basicFolder.UID, basicDashboard.UID),
|
||||
Folder: basicFolder,
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -333,24 +334,24 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
},
|
||||
dashboardPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
"d_1": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_EDIT.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Change.
|
||||
},
|
||||
"d_2": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
},
|
||||
"d_3": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_EDIT.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Change.
|
||||
},
|
||||
"d_4": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
"d_5": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
},
|
||||
},
|
||||
alerts: []*models.Alert{genLegacyAlert("alert1", 2), genLegacyAlert("alert2", 3), genLegacyAlert("alert3", 4), genLegacyAlert("alert4", 5), genLegacyAlert("alert5", 6)},
|
||||
@ -359,40 +360,40 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert("alert1", "", "d_1"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_1 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_EDIT.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Change.
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert2", "", "d_2"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_1 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert3", "", "d_3"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_1 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_EDIT.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Change.
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert4", "", "d_4"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_1 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert5", "", "d_5"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_1 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Change.
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -402,12 +403,12 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
folders: []*dashboards.Dashboard{genFolder(t, 1, "f_1"), genFolder(t, 2, "f_2")},
|
||||
folderPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
"f_1": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()},
|
||||
},
|
||||
"f_2": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
},
|
||||
dashboards: []*dashboards.Dashboard{
|
||||
@ -418,16 +419,16 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
},
|
||||
dashboardPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
"d_1": {
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
"d_2": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
},
|
||||
"d_3": {
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
"d_4": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
},
|
||||
},
|
||||
alerts: []*models.Alert{genLegacyAlert("alert1", 3), genLegacyAlert("alert2", 4), genLegacyAlert("alert3", 5), genLegacyAlert("alert4", 6)},
|
||||
@ -436,32 +437,32 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert("alert1", "f_1", "d_1"),
|
||||
Folder: genFolder(t, 1, "f_1"), // Original folder since the perms didn't change.
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()}, // Overrides from Folder.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Overrides from Folder.
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert2", "f_1", "d_2"),
|
||||
Folder: genFolder(t, 1, "f_1"), // Original folder since the perms didn't change.
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_ADMIN.String()}, // Overrides from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_ADMIN.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Overrides from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // Inherits from Folder.
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert3", "f_2", "d_3"),
|
||||
Folder: genFolder(t, 2, "f_2"), // Original folder since the perms didn't change.
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_VIEW.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_VIEW.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Alert: genAlert("alert4", "", "d_4"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_2 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()}, // Inherits from Folder.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()}, // Inherits from Folder.
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -471,13 +472,13 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
folders: []*dashboards.Dashboard{basicFolder},
|
||||
folderPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
basicFolder.UID: {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
},
|
||||
},
|
||||
dashboards: []*dashboards.Dashboard{basicDashboard},
|
||||
dashboardPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
basicDashboard.UID: {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_VIEW.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
},
|
||||
},
|
||||
alerts: []*models.Alert{basicAlert1},
|
||||
@ -486,7 +487,7 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert(basicAlert1.Name, basicFolder.UID, basicDashboard.UID),
|
||||
Folder: basicFolder,
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -505,8 +506,8 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert("alert1", "f_1", "d_1"),
|
||||
Folder: genCreatedFolder(t, "General Alerting Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()}, // From Dashboard.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()}, // From Dashboard.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // From Dashboard.
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()}, // From Dashboard.
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -516,7 +517,7 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
dashboards: []*dashboards.Dashboard{genDashboard(t, 1, "d_1", 0)}, // Dashboard in general folder.
|
||||
dashboardPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
"d_1": { // Missing viewer.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
},
|
||||
},
|
||||
alerts: []*models.Alert{genLegacyAlert("alert1", 1)},
|
||||
@ -525,7 +526,7 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert("alert1", "f_1", "d_1"),
|
||||
Folder: genCreatedFolder(t, "General Alerting Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()}, // From Dashboard.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // From Dashboard.
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -555,8 +556,8 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
},
|
||||
dashboardPerms: map[string][]accesscontrol.SetResourcePermissionCommand{
|
||||
"d_1": {
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_EDIT.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Change.
|
||||
},
|
||||
},
|
||||
alerts: []*models.Alert{genLegacyAlert("alert1", 2)},
|
||||
@ -565,9 +566,9 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
Alert: genAlert("alert1", "", "d_1"),
|
||||
Folder: genCreatedFolder(t, "Original Folder f_1 Alerts - %s"),
|
||||
Perms: []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleAdmin), Permission: dashboards.PERMISSION_ADMIN.String()}, // From basic:admin.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_EDIT.String()}, // Change.
|
||||
{BuiltinRole: string(org.RoleAdmin), Permission: dashboardaccess.PERMISSION_ADMIN.String()}, // From basic:admin.
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_EDIT.String()}, // Change.
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -699,7 +700,7 @@ func TestDashAlertPermissionMigration(t *testing.T) {
|
||||
expected.Alert.NamespaceUID = ""
|
||||
}
|
||||
|
||||
keep := make(map[accesscontrol.SetResourcePermissionCommand]dashboards.PermissionType)
|
||||
keep := make(map[accesscontrol.SetResourcePermissionCommand]dashboardaccess.PermissionType)
|
||||
for _, p := range rperms {
|
||||
if permission := service.migrationStore.MapActions(p); permission != "" {
|
||||
sp := accesscontrol.SetResourcePermissionCommand{
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/search/model"
|
||||
@ -433,7 +434,7 @@ func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, use
|
||||
SignedInUser: user,
|
||||
Type: searchstore.TypeAlertFolder,
|
||||
Limit: -1,
|
||||
Permission: dashboards.PERMISSION_VIEW,
|
||||
Permission: dashboardaccess.PERMISSION_VIEW,
|
||||
Sort: model.SortOption{},
|
||||
Filters: []any{
|
||||
searchstore.FolderWithAlertsFilter{},
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
@ -59,7 +60,7 @@ func (d *PublicDashboardStoreImpl) FindAllWithPagination(ctx context.Context, qu
|
||||
pubdashBuilder.Write(" JOIN dashboard ON dashboard.uid = dashboard_public.dashboard_uid AND dashboard.org_id = dashboard_public.org_id")
|
||||
pubdashBuilder.Write(` WHERE dashboard_public.org_id = ?`, query.OrgID)
|
||||
if query.User.OrgRole != org.RoleAdmin {
|
||||
pubdashBuilder.WriteDashboardPermissionFilter(query.User, dashboards.PERMISSION_VIEW, searchstore.TypeDashboard)
|
||||
pubdashBuilder.WriteDashboardPermissionFilter(query.User, dashboardaccess.PERMISSION_VIEW, searchstore.TypeDashboard)
|
||||
}
|
||||
pubdashBuilder.Write(" ORDER BY dashboard.title")
|
||||
pubdashBuilder.Write(d.sqlStore.GetDialect().LimitOffset(int64(query.Limit), int64(query.Offset)))
|
||||
@ -70,7 +71,7 @@ func (d *PublicDashboardStoreImpl) FindAllWithPagination(ctx context.Context, qu
|
||||
counterBuilder.Write(" JOIN dashboard ON dashboard.uid = dashboard_public.dashboard_uid AND dashboard.org_id = dashboard_public.org_id")
|
||||
counterBuilder.Write(` WHERE dashboard_public.org_id = ?`, query.OrgID)
|
||||
if query.User.OrgRole != org.RoleAdmin {
|
||||
counterBuilder.WriteDashboardPermissionFilter(query.User, dashboards.PERMISSION_VIEW, searchstore.TypeDashboard)
|
||||
counterBuilder.WriteDashboardPermissionFilter(query.User, dashboardaccess.PERMISSION_VIEW, searchstore.TypeDashboard)
|
||||
}
|
||||
|
||||
err = d.sqlStore.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/search/model"
|
||||
"github.com/grafana/grafana/pkg/services/star"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@ -40,7 +41,7 @@ type Query struct {
|
||||
// Deprecated: use FolderUID instead
|
||||
FolderIds []int64
|
||||
FolderUIDs []string
|
||||
Permission dashboards.PermissionType
|
||||
Permission dashboardaccess.PermissionType
|
||||
Sort string
|
||||
}
|
||||
|
||||
|
@ -10,19 +10,20 @@ import (
|
||||
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
)
|
||||
|
||||
var dashboardPermissionTranslation = map[dashboards.PermissionType][]string{
|
||||
dashboards.PERMISSION_VIEW: {
|
||||
var dashboardPermissionTranslation = map[dashboardaccess.PermissionType][]string{
|
||||
dashboardaccess.PERMISSION_VIEW: {
|
||||
dashboards.ActionDashboardsRead,
|
||||
},
|
||||
dashboards.PERMISSION_EDIT: {
|
||||
dashboardaccess.PERMISSION_EDIT: {
|
||||
dashboards.ActionDashboardsRead,
|
||||
dashboards.ActionDashboardsWrite,
|
||||
dashboards.ActionDashboardsDelete,
|
||||
},
|
||||
dashboards.PERMISSION_ADMIN: {
|
||||
dashboardaccess.PERMISSION_ADMIN: {
|
||||
dashboards.ActionDashboardsRead,
|
||||
dashboards.ActionDashboardsWrite,
|
||||
dashboards.ActionDashboardsCreate,
|
||||
@ -32,17 +33,17 @@ var dashboardPermissionTranslation = map[dashboards.PermissionType][]string{
|
||||
},
|
||||
}
|
||||
|
||||
var folderPermissionTranslation = map[dashboards.PermissionType][]string{
|
||||
dashboards.PERMISSION_VIEW: append(dashboardPermissionTranslation[dashboards.PERMISSION_VIEW], []string{
|
||||
var folderPermissionTranslation = map[dashboardaccess.PermissionType][]string{
|
||||
dashboardaccess.PERMISSION_VIEW: append(dashboardPermissionTranslation[dashboardaccess.PERMISSION_VIEW], []string{
|
||||
dashboards.ActionFoldersRead,
|
||||
}...),
|
||||
dashboards.PERMISSION_EDIT: append(dashboardPermissionTranslation[dashboards.PERMISSION_EDIT], []string{
|
||||
dashboardaccess.PERMISSION_EDIT: append(dashboardPermissionTranslation[dashboardaccess.PERMISSION_EDIT], []string{
|
||||
dashboards.ActionDashboardsCreate,
|
||||
dashboards.ActionFoldersRead,
|
||||
dashboards.ActionFoldersWrite,
|
||||
dashboards.ActionFoldersDelete,
|
||||
}...),
|
||||
dashboards.PERMISSION_ADMIN: append(dashboardPermissionTranslation[dashboards.PERMISSION_ADMIN], []string{
|
||||
dashboardaccess.PERMISSION_ADMIN: append(dashboardPermissionTranslation[dashboardaccess.PERMISSION_ADMIN], []string{
|
||||
dashboards.ActionFoldersRead,
|
||||
dashboards.ActionFoldersWrite,
|
||||
dashboards.ActionFoldersDelete,
|
||||
@ -111,11 +112,11 @@ func (m dashboardPermissionsMigrator) migratePermissions(dashes []dashboard, acl
|
||||
if (d.IsFolder || d.FolderID == 0) && len(acls) == 0 && !d.HasAcl {
|
||||
permissionMap[d.OrgID]["managed:builtins:editor:permissions"] = append(
|
||||
permissionMap[d.OrgID]["managed:builtins:editor:permissions"],
|
||||
m.mapPermission(d.ID, dashboards.PERMISSION_EDIT, d.IsFolder)...,
|
||||
m.mapPermission(d.ID, dashboardaccess.PERMISSION_EDIT, d.IsFolder)...,
|
||||
)
|
||||
permissionMap[d.OrgID]["managed:builtins:viewer:permissions"] = append(
|
||||
permissionMap[d.OrgID]["managed:builtins:viewer:permissions"],
|
||||
m.mapPermission(d.ID, dashboards.PERMISSION_VIEW, d.IsFolder)...,
|
||||
m.mapPermission(d.ID, dashboardaccess.PERMISSION_VIEW, d.IsFolder)...,
|
||||
)
|
||||
} else {
|
||||
for _, a := range deduplicateAcl(acls) {
|
||||
@ -192,7 +193,7 @@ func (m dashboardPermissionsMigrator) setPermissions(allRoles []*ac.Role, permis
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m dashboardPermissionsMigrator) mapPermission(id int64, p dashboards.PermissionType, isFolder bool) []*ac.Permission {
|
||||
func (m dashboardPermissionsMigrator) mapPermission(id int64, p dashboardaccess.PermissionType, isFolder bool) []*ac.Permission {
|
||||
if isFolder {
|
||||
actions := folderPermissionTranslation[p]
|
||||
scope := dashboards.ScopeFoldersProvider.GetResourceScope(strconv.FormatInt(id, 10))
|
||||
@ -661,15 +662,15 @@ func (m *managedFolderLibraryPanelActionsMigrator) Exec(sess *xorm.Session, mg *
|
||||
}
|
||||
|
||||
func hasFolderAdmin(permissions []ac.Permission) bool {
|
||||
return hasActions(folderPermissionTranslation[dashboards.PERMISSION_ADMIN], permissions)
|
||||
return hasActions(folderPermissionTranslation[dashboardaccess.PERMISSION_ADMIN], permissions)
|
||||
}
|
||||
|
||||
func hasFolderEdit(permissions []ac.Permission) bool {
|
||||
return hasActions(folderPermissionTranslation[dashboards.PERMISSION_EDIT], permissions)
|
||||
return hasActions(folderPermissionTranslation[dashboardaccess.PERMISSION_EDIT], permissions)
|
||||
}
|
||||
|
||||
func hasFolderView(permissions []ac.Permission) bool {
|
||||
return hasActions(folderPermissionTranslation[dashboards.PERMISSION_VIEW], permissions)
|
||||
return hasActions(folderPermissionTranslation[dashboardaccess.PERMISSION_VIEW], permissions)
|
||||
}
|
||||
|
||||
func hasActions(actions []string, permissions []ac.Permission) bool {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"xorm.io/xorm"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
@ -64,12 +64,12 @@ func (p *teamPermissionMigrator) setRolePermissions(roleID int64, permissions []
|
||||
}
|
||||
|
||||
// mapPermissionToRBAC translates the legacy membership (Member or Admin) into RBAC permissions
|
||||
func (p *teamPermissionMigrator) mapPermissionToRBAC(permission dashboards.PermissionType, teamID int64) []accesscontrol.Permission {
|
||||
func (p *teamPermissionMigrator) mapPermissionToRBAC(permission dashboardaccess.PermissionType, teamID int64) []accesscontrol.Permission {
|
||||
teamIDScope := accesscontrol.Scope("teams", "id", strconv.FormatInt(teamID, 10))
|
||||
switch permission {
|
||||
case 0:
|
||||
return []accesscontrol.Permission{{Action: "teams:read", Scope: teamIDScope}}
|
||||
case dashboards.PERMISSION_ADMIN:
|
||||
case dashboardaccess.PERMISSION_ADMIN:
|
||||
return []accesscontrol.Permission{
|
||||
{Action: "teams:delete", Scope: teamIDScope},
|
||||
{Action: "teams:read", Scope: teamIDScope},
|
||||
@ -210,7 +210,7 @@ func (p *teamPermissionMigrator) generateAssociatedPermissions(teamMemberships [
|
||||
// Downgrade team permissions if needed:
|
||||
// only admins or editors (when editorsCanAdmin option is enabled)
|
||||
// can access team administration endpoints
|
||||
if m.Permission == dashboards.PERMISSION_ADMIN {
|
||||
if m.Permission == dashboardaccess.PERMISSION_ADMIN {
|
||||
if userRolesByOrg[m.OrgID][m.UserID] == string(org.RoleViewer) || (userRolesByOrg[m.OrgID][m.UserID] == string(org.RoleEditor) && !p.editorsCanAdmin) {
|
||||
m.Permission = 0
|
||||
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrations"
|
||||
@ -358,7 +358,7 @@ func setupTeams(t *testing.T, x *xorm.Engine) {
|
||||
TeamID: 1,
|
||||
UserID: 2,
|
||||
External: false,
|
||||
Permission: dashboards.PERMISSION_ADMIN,
|
||||
Permission: dashboardaccess.PERMISSION_ADMIN,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
},
|
||||
@ -368,7 +368,7 @@ func setupTeams(t *testing.T, x *xorm.Engine) {
|
||||
TeamID: 1,
|
||||
UserID: 3,
|
||||
External: false,
|
||||
Permission: dashboards.PERMISSION_ADMIN,
|
||||
Permission: dashboardaccess.PERMISSION_ADMIN,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
},
|
||||
@ -378,7 +378,7 @@ func setupTeams(t *testing.T, x *xorm.Engine) {
|
||||
TeamID: 1,
|
||||
UserID: 4,
|
||||
External: false,
|
||||
Permission: dashboards.PERMISSION_ADMIN,
|
||||
Permission: dashboardaccess.PERMISSION_ADMIN,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
},
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
@ -44,11 +45,11 @@ type PermissionsFilter interface {
|
||||
nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, rightTableCol string, orgID int64) (string, []any)
|
||||
}
|
||||
|
||||
// NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the dashboards.PermissionType and query type
|
||||
// NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the dashboardaccess.PermissionType and query type
|
||||
// The filter is configured to use the new permissions filter (without subqueries) if the feature flag is enabled
|
||||
// The filter is configured to use the old permissions filter (with subqueries) if the feature flag is disabled
|
||||
func NewAccessControlDashboardPermissionFilter(user identity.Requester, permissionLevel dashboards.PermissionType, queryType string, features featuremgmt.FeatureToggles, recursiveQueriesAreSupported bool) PermissionsFilter {
|
||||
needEdit := permissionLevel > dashboards.PERMISSION_VIEW
|
||||
func NewAccessControlDashboardPermissionFilter(user identity.Requester, permissionLevel dashboardaccess.PermissionType, queryType string, features featuremgmt.FeatureToggles, recursiveQueriesAreSupported bool) PermissionsFilter {
|
||||
needEdit := permissionLevel > dashboardaccess.PERMISSION_VIEW
|
||||
|
||||
var folderActions []string
|
||||
var dashboardActions []string
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
@ -40,7 +41,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
type testCase struct {
|
||||
desc string
|
||||
queryType string
|
||||
permission dashboards.PermissionType
|
||||
permission dashboardaccess.PermissionType
|
||||
permissions []accesscontrol.Permission
|
||||
expectedResult int
|
||||
}
|
||||
@ -48,7 +49,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
tests := []testCase{
|
||||
{
|
||||
desc: "Should be able to view all dashboards with wildcard scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeDashboardsAll},
|
||||
},
|
||||
@ -56,7 +57,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view all dashboards with folder wildcard scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersAll},
|
||||
},
|
||||
@ -64,7 +65,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view dashboards under the root with folders:uid:general scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
},
|
||||
@ -72,7 +73,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view editable dashboards under the root with folders:uid:general scope if missing write action",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
},
|
||||
@ -80,7 +81,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view editable dashboards under the root with folders:uid:general scope if has write action",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
{Action: dashboards.ActionDashboardsWrite, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
@ -89,7 +90,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view a subset of dashboards with dashboard scopes",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:110"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:40"},
|
||||
@ -102,7 +103,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view a subset of dashboards with dashboard action and folder scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:8"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:10"},
|
||||
@ -111,7 +112,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view all folders with folder wildcard",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:*"},
|
||||
},
|
||||
@ -119,7 +120,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view a subset folders",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:6"},
|
||||
@ -129,7 +130,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should return folders and dashboard with 'edit' permission",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionDashboardsCreate, Scope: "folders:uid:3"},
|
||||
@ -140,7 +141,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should return the dashboards that the User has dashboards:write permission on in case of 'edit' permission",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:31"},
|
||||
@ -152,7 +153,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should return the folders that the User has dashboards:create permission on in case of 'edit' permission",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionDashboardsCreate, Scope: "folders:uid:3"},
|
||||
@ -164,7 +165,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should return folders that users can read alerts from",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
queryType: searchstore.TypeAlertFolder,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
@ -176,7 +177,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should return folders that users can read alerts when user has read wildcard",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
queryType: searchstore.TypeAlertFolder,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "*"},
|
||||
@ -232,7 +233,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
type testCase struct {
|
||||
desc string
|
||||
queryType string
|
||||
permission dashboards.PermissionType
|
||||
permission dashboardaccess.PermissionType
|
||||
signedInUserPermissions []accesscontrol.Permission
|
||||
expectedResult int
|
||||
}
|
||||
@ -240,7 +241,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
tests := []testCase{
|
||||
{
|
||||
desc: "Should be able to view all dashboards with wildcard scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeDashboardsAll},
|
||||
},
|
||||
@ -248,7 +249,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view all dashboards with folder wildcard scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersAll},
|
||||
},
|
||||
@ -256,13 +257,13 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view any dashboards or folders without any permissions",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{},
|
||||
expectedResult: 0,
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view a subset of dashboards with dashboard scopes",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:110"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:40"},
|
||||
@ -275,7 +276,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view a subset of dashboards with dashboard action and folder scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:8"},
|
||||
@ -285,7 +286,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view dashboards under the root with folders:uid:general scope",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
},
|
||||
@ -293,7 +294,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view editable dashboards under the root with folders:uid:general scope if missing write action",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
},
|
||||
@ -301,7 +302,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view editable dashboards under the root with folders:uid:general scope if has write action",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
{Action: dashboards.ActionDashboardsWrite, Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)},
|
||||
@ -310,7 +311,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view all folders with folder wildcard",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:*"},
|
||||
},
|
||||
@ -318,7 +319,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view a subset folders",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:6"},
|
||||
@ -328,7 +329,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should return folders and dashboard with 'edit' permission",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionDashboardsCreate, Scope: "folders:uid:3"},
|
||||
@ -339,7 +340,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should return the dashboards that the User has dashboards:write permission on in case of 'edit' permission",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:31"},
|
||||
@ -351,7 +352,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should return the folders that the User has dashboards:create permission on in case of 'edit' permission",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
{Action: dashboards.ActionDashboardsCreate, Scope: "folders:uid:3"},
|
||||
@ -363,7 +364,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should return folders that users can read alerts from",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
queryType: searchstore.TypeAlertFolder,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:3"},
|
||||
@ -375,7 +376,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t
|
||||
},
|
||||
{
|
||||
desc: "Should return folders that users can read alerts when user has read wildcard",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
queryType: searchstore.TypeAlertFolder,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "*"},
|
||||
@ -427,7 +428,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
queryType string
|
||||
permission dashboards.PermissionType
|
||||
permission dashboardaccess.PermissionType
|
||||
permissions []accesscontrol.Permission
|
||||
expectedResult []string
|
||||
features []any
|
||||
@ -435,7 +436,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should not be able to view dashboards under inherited folders with no permissions if nested folders are enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: nil,
|
||||
features: []any{featuremgmt.FlagNestedFolders},
|
||||
expectedResult: nil,
|
||||
@ -443,14 +444,14 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should not be able to view inherited folders with no permissions if nested folders are enabled",
|
||||
queryType: searchstore.TypeFolder,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: nil,
|
||||
features: []any{featuremgmt.FlagNestedFolders},
|
||||
expectedResult: nil,
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view inherited dashboards and folders with no permissions if nested folders are enabled",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: nil,
|
||||
features: []any{featuremgmt.FlagNestedFolders},
|
||||
expectedResult: nil,
|
||||
@ -458,7 +459,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should be able to view dashboards under inherited folders with wildcard scope if nested folders are enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersAll},
|
||||
},
|
||||
@ -468,7 +469,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should be able to view dashboards under inherited folders if nested folders are enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -478,7 +479,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should not be able to view dashboards under inherited folders if nested folders are not enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -488,7 +489,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should be able to view inherited folders if nested folders are enabled",
|
||||
queryType: searchstore.TypeFolder,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -498,7 +499,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
{
|
||||
desc: "Should not be able to view inherited folders if nested folders are not enabled",
|
||||
queryType: searchstore.TypeFolder,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -507,7 +508,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view inherited dashboards and folders if nested folders are enabled",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
@ -517,7 +518,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view inherited dashboards and folders if nested folders are not enabled",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
@ -580,7 +581,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
testCases := []struct {
|
||||
desc string
|
||||
queryType string
|
||||
permission dashboards.PermissionType
|
||||
permission dashboardaccess.PermissionType
|
||||
signedInUserPermissions []accesscontrol.Permission
|
||||
expectedResult []string
|
||||
features []any
|
||||
@ -588,7 +589,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should not be able to view dashboards under inherited folders with no permissions if nested folders are enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: nil,
|
||||
features: []any{featuremgmt.FlagNestedFolders},
|
||||
expectedResult: nil,
|
||||
@ -596,14 +597,14 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should not be able to view inherited folders with no permissions if nested folders are enabled",
|
||||
queryType: searchstore.TypeFolder,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: nil,
|
||||
features: []any{featuremgmt.FlagNestedFolders},
|
||||
expectedResult: nil,
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view inherited dashboards and folders with no permissions if nested folders are enabled",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: nil,
|
||||
features: []any{featuremgmt.FlagNestedFolders},
|
||||
expectedResult: nil,
|
||||
@ -611,7 +612,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should be able to view dashboards under inherited folders with wildcard scope if nested folders are enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: dashboards.ScopeFoldersAll},
|
||||
},
|
||||
@ -621,7 +622,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should be able to view dashboards under inherited folders if nested folders are enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -631,7 +632,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should not be able to view dashboards under inherited folders if nested folders are not enabled",
|
||||
queryType: searchstore.TypeDashboard,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -641,7 +642,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should be able to view inherited folders if nested folders are enabled",
|
||||
queryType: searchstore.TypeFolder,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -651,7 +652,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
{
|
||||
desc: "Should not be able to view inherited folders if nested folders are not enabled",
|
||||
queryType: searchstore.TypeFolder,
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
},
|
||||
@ -660,7 +661,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
},
|
||||
{
|
||||
desc: "Should be able to view inherited dashboards and folders if nested folders are enabled",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
@ -670,7 +671,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
},
|
||||
{
|
||||
desc: "Should not be able to view inherited dashboards and folders if nested folders are not enabled",
|
||||
permission: dashboards.PERMISSION_VIEW,
|
||||
permission: dashboardaccess.PERMISSION_VIEW,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"},
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"},
|
||||
@ -680,7 +681,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission
|
||||
},
|
||||
{
|
||||
desc: "Should be able to edit inherited dashboards and folders if nested folders are enabled",
|
||||
permission: dashboards.PERMISSION_EDIT,
|
||||
permission: dashboardaccess.PERMISSION_EDIT,
|
||||
signedInUserPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionFoldersRead, Scope: "folders:uid:subfolder"},
|
||||
{Action: dashboards.ActionDashboardsCreate, Scope: "folders:uid:subfolder"},
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
@ -56,7 +57,7 @@ func benchmarkDashboardPermissionFilter(b *testing.B, numUsers, numDashboards, n
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(&usr, dashboards.PERMISSION_VIEW, "", features, recursiveQueriesAreSupported)
|
||||
filter := permissions.NewAccessControlDashboardPermissionFilter(&usr, dashboardaccess.PERMISSION_VIEW, "", features, recursiveQueriesAreSupported)
|
||||
var result int
|
||||
err := store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
q, params := filter.Where()
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
|
||||
@ -299,7 +300,7 @@ func TestBuilder_RBAC(t *testing.T) {
|
||||
user.Permissions = map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tc.userPermissions)}
|
||||
}
|
||||
|
||||
level := dashboards.PERMISSION_EDIT
|
||||
level := dashboardaccess.PERMISSION_EDIT
|
||||
|
||||
builder := &searchstore.Builder{
|
||||
Filters: []any{
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
@ -109,10 +109,10 @@ func (ss *sqlStatsService) GetSystemStats(ctx context.Context, query *stats.GetS
|
||||
WHERE d.is_folder = ?
|
||||
) AS folder_permissions,`, dialect.BooleanStr(true))
|
||||
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "dashboards_viewers_can_edit", false, dashboards.PERMISSION_EDIT))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "dashboards_viewers_can_admin", false, dashboards.PERMISSION_ADMIN))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "folders_viewers_can_edit", true, dashboards.PERMISSION_EDIT))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "folders_viewers_can_admin", true, dashboards.PERMISSION_ADMIN))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "dashboards_viewers_can_edit", false, dashboardaccess.PERMISSION_EDIT))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "dashboards_viewers_can_admin", false, dashboardaccess.PERMISSION_ADMIN))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "folders_viewers_can_edit", true, dashboardaccess.PERMISSION_EDIT))
|
||||
sb.Write(viewersPermissionsCounterSQL(ss.db, "folders_viewers_can_admin", true, dashboardaccess.PERMISSION_ADMIN))
|
||||
|
||||
sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("dashboard_provisioning") + `) AS provisioned_dashboards,`)
|
||||
sb.Write(`(SELECT COUNT(id) FROM ` + dialect.Quote("dashboard_snapshot") + `) AS snapshots,`)
|
||||
@ -166,7 +166,7 @@ func (ss *sqlStatsService) roleCounterSQL(ctx context.Context) string {
|
||||
return sqlQuery
|
||||
}
|
||||
|
||||
func viewersPermissionsCounterSQL(db db.DB, statName string, isFolder bool, permission dashboards.PermissionType) string {
|
||||
func viewersPermissionsCounterSQL(db db.DB, statName string, isFolder bool, permission dashboardaccess.PermissionType) string {
|
||||
dialect := db.GetDialect()
|
||||
return `(
|
||||
SELECT COUNT(*)
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/kinds/team"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/search/model"
|
||||
)
|
||||
|
||||
@ -110,7 +110,7 @@ type TeamDTO struct {
|
||||
Email string `json:"email"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
MemberCount int64 `json:"memberCount"`
|
||||
Permission dashboards.PermissionType `json:"permission"`
|
||||
Permission dashboardaccess.PermissionType `json:"permission"`
|
||||
AccessControl map[string]bool `json:"accessControl"`
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ type TeamMember struct {
|
||||
TeamID int64 `xorm:"team_id"`
|
||||
UserID int64 `xorm:"user_id"`
|
||||
External bool // Signals that the membership has been created by an external systems, such as LDAP
|
||||
Permission dashboards.PermissionType
|
||||
Permission dashboardaccess.PermissionType
|
||||
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
@ -142,14 +142,14 @@ type AddTeamMemberCommand struct {
|
||||
OrgID int64 `json:"-"`
|
||||
TeamID int64 `json:"-"`
|
||||
External bool `json:"-"`
|
||||
Permission dashboards.PermissionType `json:"-"`
|
||||
Permission dashboardaccess.PermissionType `json:"-"`
|
||||
}
|
||||
|
||||
type UpdateTeamMemberCommand struct {
|
||||
UserID int64 `json:"-"`
|
||||
OrgID int64 `json:"-"`
|
||||
TeamID int64 `json:"-"`
|
||||
Permission dashboards.PermissionType `json:"permission"`
|
||||
Permission dashboardaccess.PermissionType `json:"permission"`
|
||||
}
|
||||
|
||||
type RemoveTeamMemberCommand struct {
|
||||
@ -185,5 +185,5 @@ type TeamMemberDTO struct {
|
||||
Login string `json:"login"`
|
||||
AvatarURL string `json:"avatarUrl" xorm:"avatar_url"`
|
||||
Labels []string `json:"labels"`
|
||||
Permission dashboards.PermissionType `json:"permission"`
|
||||
Permission dashboardaccess.PermissionType `json:"permission"`
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package team
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
@ -14,7 +14,7 @@ type Service interface {
|
||||
GetTeamByID(ctx context.Context, query *GetTeamByIDQuery) (*TeamDTO, error)
|
||||
GetTeamsByUser(ctx context.Context, query *GetTeamsByUserQuery) ([]*TeamDTO, error)
|
||||
GetTeamIDsByUser(ctx context.Context, query *GetTeamIDsByUserQuery) ([]int64, error)
|
||||
AddTeamMember(userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error
|
||||
AddTeamMember(userID, orgID, teamID int64, isExternal bool, permission dashboardaccess.PermissionType) error
|
||||
UpdateTeamMember(ctx context.Context, cmd *UpdateTeamMemberCommand) error
|
||||
IsTeamMember(orgId int64, teamId int64, userId int64) (bool, error)
|
||||
RemoveTeamMember(ctx context.Context, cmd *RemoveTeamMemberCommand) error
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/preference/prefapi"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/services/team/sortopts"
|
||||
@ -58,7 +58,7 @@ func (tapi *TeamAPI) createTeam(c *contextmodel.ReqContext) response.Response {
|
||||
break
|
||||
}
|
||||
if err := addOrUpdateTeamMember(c.Req.Context(), tapi.teamPermissionsService, userID, c.SignedInUser.GetOrgID(),
|
||||
t.ID, dashboards.PERMISSION_ADMIN.String()); err != nil {
|
||||
t.ID, dashboardaccess.PERMISSION_ADMIN.String()); err != nil {
|
||||
c.Logger.Error("Could not add creator to team", "error", err)
|
||||
}
|
||||
default:
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -141,7 +141,7 @@ func (tapi *TeamAPI) updateTeamMember(c *contextmodel.ReqContext) response.Respo
|
||||
return response.Success("Team member updated")
|
||||
}
|
||||
|
||||
func getPermissionName(permission dashboards.PermissionType) string {
|
||||
func getPermissionName(permission dashboardaccess.PermissionType) string {
|
||||
permissionName := permission.String()
|
||||
// Team member permission is 0, which maps to an empty string.
|
||||
// However, we want the team permission service to display "Member" for team members. This is a hack to make it work.
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -25,7 +25,7 @@ type store interface {
|
||||
GetByUser(ctx context.Context, query *team.GetTeamsByUserQuery) ([]*team.TeamDTO, error)
|
||||
GetIDsByUser(ctx context.Context, query *team.GetTeamIDsByUserQuery) ([]int64, error)
|
||||
RemoveUsersMemberships(ctx context.Context, userID int64) error
|
||||
AddMember(userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error
|
||||
AddMember(userID, orgID, teamID int64, isExternal bool, permission dashboardaccess.PermissionType) error
|
||||
UpdateMember(ctx context.Context, cmd *team.UpdateTeamMemberCommand) error
|
||||
IsMember(orgId int64, teamId int64, userId int64) (bool, error)
|
||||
RemoveMember(ctx context.Context, cmd *team.RemoveTeamMemberCommand) error
|
||||
@ -354,7 +354,7 @@ WHERE tm.user_id=? AND tm.org_id=?;`, query.UserID, query.OrgID).Find(&queryResu
|
||||
}
|
||||
|
||||
// AddTeamMember adds a user to a team
|
||||
func (ss *xormStore) AddMember(userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error {
|
||||
func (ss *xormStore) AddMember(userID, orgID, teamID int64, isExternal bool, permission dashboardaccess.PermissionType) error {
|
||||
return ss.db.WithTransactionalDbSession(context.Background(), func(sess *db.Session) error {
|
||||
if isMember, err := isTeamMember(sess, orgID, teamID, userID); err != nil {
|
||||
return err
|
||||
@ -412,7 +412,7 @@ func isTeamMember(sess *db.Session, orgId int64, teamId int64, userId int64) (bo
|
||||
|
||||
// AddOrUpdateTeamMemberHook is called from team resource permission service
|
||||
// it adds user to a team or updates user permissions in a team within the given transaction session
|
||||
func AddOrUpdateTeamMemberHook(sess *db.Session, userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error {
|
||||
func AddOrUpdateTeamMemberHook(sess *db.Session, userID, orgID, teamID int64, isExternal bool, permission dashboardaccess.PermissionType) error {
|
||||
isMember, err := isTeamMember(sess, orgID, teamID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -427,7 +427,7 @@ func AddOrUpdateTeamMemberHook(sess *db.Session, userID, orgID, teamID int64, is
|
||||
return err
|
||||
}
|
||||
|
||||
func addTeamMember(sess *db.Session, orgID, teamID, userID int64, isExternal bool, permission dashboards.PermissionType) error {
|
||||
func addTeamMember(sess *db.Session, orgID, teamID, userID int64, isExternal bool, permission dashboardaccess.PermissionType) error {
|
||||
if _, err := teamExists(orgID, teamID, sess); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -446,13 +446,13 @@ func addTeamMember(sess *db.Session, orgID, teamID, userID int64, isExternal boo
|
||||
return err
|
||||
}
|
||||
|
||||
func updateTeamMember(sess *db.Session, orgID, teamID, userID int64, permission dashboards.PermissionType) error {
|
||||
func updateTeamMember(sess *db.Session, orgID, teamID, userID int64, permission dashboardaccess.PermissionType) error {
|
||||
member, err := getTeamMember(sess, orgID, teamID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if permission != dashboards.PERMISSION_ADMIN {
|
||||
if permission != dashboardaccess.PERMISSION_ADMIN {
|
||||
permission = 0 // make sure we don't get invalid permission levels in store
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgimpl"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
@ -174,7 +174,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
UserID: userId,
|
||||
OrgID: testOrgID,
|
||||
TeamID: team1.ID,
|
||||
Permission: dashboards.PERMISSION_ADMIN,
|
||||
Permission: dashboardaccess.PERMISSION_ADMIN,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
@ -182,7 +182,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
qAfterUpdate := &team.GetTeamMembersQuery{OrgID: testOrgID, TeamID: team1.ID, SignedInUser: testUser}
|
||||
qAfterUpdateResult, err := teamSvc.GetTeamMembers(context.Background(), qAfterUpdate)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, qAfterUpdateResult[0].Permission, dashboards.PERMISSION_ADMIN)
|
||||
require.Equal(t, qAfterUpdateResult[0].Permission, dashboardaccess.PERMISSION_ADMIN)
|
||||
})
|
||||
|
||||
t.Run("Should default to member permission level when updating a user with invalid permission level", func(t *testing.T) {
|
||||
@ -197,7 +197,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, qBeforeUpdateResult[0].Permission, 0)
|
||||
|
||||
invalidPermissionLevel := dashboards.PERMISSION_EDIT
|
||||
invalidPermissionLevel := dashboardaccess.PERMISSION_EDIT
|
||||
err = teamSvc.UpdateTeamMember(context.Background(), &team.UpdateTeamMemberCommand{
|
||||
UserID: userID,
|
||||
OrgID: testOrgID,
|
||||
@ -220,7 +220,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
UserID: 1,
|
||||
OrgID: testOrgID,
|
||||
TeamID: team1.ID,
|
||||
Permission: dashboards.PERMISSION_ADMIN,
|
||||
Permission: dashboardaccess.PERMISSION_ADMIN,
|
||||
})
|
||||
|
||||
require.Error(t, err, team.ErrTeamMemberNotFound)
|
||||
@ -330,7 +330,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Should have empty teams", func(t *testing.T) {
|
||||
err = teamSvc.AddTeamMember(userIds[0], testOrgID, team1.ID, false, dashboards.PERMISSION_ADMIN)
|
||||
err = teamSvc.AddTeamMember(userIds[0], testOrgID, team1.ID, false, dashboardaccess.PERMISSION_ADMIN)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("A user should be able to remove the admin permission for the last admin", func(t *testing.T) {
|
||||
@ -347,10 +347,10 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
sqlStore = db.InitTestDB(t)
|
||||
setup()
|
||||
|
||||
err = teamSvc.AddTeamMember(userIds[0], testOrgID, team1.ID, false, dashboards.PERMISSION_ADMIN)
|
||||
err = teamSvc.AddTeamMember(userIds[0], testOrgID, team1.ID, false, dashboardaccess.PERMISSION_ADMIN)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = teamSvc.AddTeamMember(userIds[1], testOrgID, team1.ID, false, dashboards.PERMISSION_ADMIN)
|
||||
err = teamSvc.AddTeamMember(userIds[1], testOrgID, team1.ID, false, dashboardaccess.PERMISSION_ADMIN)
|
||||
require.NoError(t, err)
|
||||
err = teamSvc.UpdateTeamMember(context.Background(), &team.UpdateTeamMemberCommand{OrgID: testOrgID, TeamID: team1.ID, UserID: userIds[0], Permission: 0})
|
||||
require.NoError(t, err)
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
@ -45,7 +45,7 @@ func (s *Service) GetTeamIDsByUser(ctx context.Context, query *team.GetTeamIDsBy
|
||||
return s.store.GetIDsByUser(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) AddTeamMember(userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error {
|
||||
func (s *Service) AddTeamMember(userID, orgID, teamID int64, isExternal bool, permission dashboardaccess.PermissionType) error {
|
||||
return s.store.AddMember(userID, orgID, teamID, isExternal, permission)
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package teamtest
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
)
|
||||
|
||||
@ -45,7 +45,7 @@ func (s *FakeService) GetTeamsByUser(ctx context.Context, query *team.GetTeamsBy
|
||||
return s.ExpectedTeamsByUser, s.ExpectedError
|
||||
}
|
||||
|
||||
func (s *FakeService) AddTeamMember(userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error {
|
||||
func (s *FakeService) AddTeamMember(userID, orgID, teamID int64, isExternal bool, permission dashboardaccess.PermissionType) error {
|
||||
return s.ExpectedError
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user