merge (#45335)
Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
@@ -276,12 +276,13 @@ type accessControlScenarioContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setAccessControlPermissions(acmock *accesscontrolmock.Mock, perms []*accesscontrol.Permission, org int64) {
|
func setAccessControlPermissions(acmock *accesscontrolmock.Mock, perms []*accesscontrol.Permission, org int64) {
|
||||||
acmock.GetUserPermissionsFunc = func(_ context.Context, u *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
acmock.GetUserPermissionsFunc =
|
||||||
if u.OrgId == org {
|
func(_ context.Context, u *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
return perms, nil
|
if u.OrgId == org {
|
||||||
|
return perms, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setInitCtxSignedInUser sets a copy of the user in initCtx
|
// setInitCtxSignedInUser sets a copy of the user in initCtx
|
||||||
@@ -367,7 +368,8 @@ func setupHTTPServerWithCfg(t *testing.T, useFakeAccessControl, enableAccessCont
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
hs.TeamPermissionsService = teamPermissionService
|
hs.TeamPermissionsService = teamPermissionService
|
||||||
} else {
|
} else {
|
||||||
ac := ossaccesscontrol.ProvideService(hs.Features, &usagestats.UsageStatsMock{T: t}, database.ProvideService(db))
|
ac := ossaccesscontrol.ProvideService(hs.Features, &usagestats.UsageStatsMock{T: t},
|
||||||
|
database.ProvideService(db), routing.NewRouteRegister())
|
||||||
hs.AccessControl = ac
|
hs.AccessControl = ac
|
||||||
// Perform role registration
|
// Perform role registration
|
||||||
err := hs.declareFixedRoles()
|
err := hs.declareFixedRoles()
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ func (hs *HTTPServer) getDataSourceAccessControlMetadata(c *models.ReqContext, d
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser,
|
||||||
|
accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil || len(userPermissions) == 0 {
|
if err != nil || len(userPermissions) == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -625,7 +625,7 @@ func (hs *HTTPServer) setIndexViewData(c *models.ReqContext) (*dtos.IndexViewDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hs.Features.IsEnabled(featuremgmt.FlagAccesscontrol) {
|
if hs.Features.IsEnabled(featuremgmt.FlagAccesscontrol) {
|
||||||
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser, ac.Options{ReloadCache: false})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ func (hs *HTTPServer) getUserAccessControlMetadata(c *models.ReqContext, resourc
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser, accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil || len(userPermissions) == 0 {
|
if err != nil || len(userPermissions) == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -112,7 +112,7 @@ func (hs *HTTPServer) getTeamsAccessControlMetadata(c *models.ReqContext, teamID
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser, accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil || len(userPermissions) == 0 {
|
if err != nil || len(userPermissions) == 0 {
|
||||||
hs.log.Warn("could not fetch accesscontrol metadata for teams", "error", err)
|
hs.log.Warn("could not fetch accesscontrol metadata for teams", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -177,7 +177,7 @@ func (hs *HTTPServer) getTeamAccessControlMetadata(c *models.ReqContext, teamID
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser, accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil || len(userPermissions) == 0 {
|
if err != nil || len(userPermissions) == 0 {
|
||||||
hs.log.Warn("could not fetch accesscontrol metadata", "team", teamID, "error", err)
|
hs.log.Warn("could not fetch accesscontrol metadata", "team", teamID, "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ func (hs *HTTPServer) getGlobalUserAccessControlMetadata(c *models.ReqContext, u
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser, accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil || len(userPermissions) == 0 {
|
if err != nil || len(userPermissions) == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
ReloadCache bool
|
||||||
|
}
|
||||||
|
|
||||||
type AccessControl interface {
|
type AccessControl interface {
|
||||||
// Evaluate evaluates access to the given resources.
|
// Evaluate evaluates access to the given resources.
|
||||||
Evaluate(ctx context.Context, user *models.SignedInUser, evaluator Evaluator) (bool, error)
|
Evaluate(ctx context.Context, user *models.SignedInUser, evaluator Evaluator) (bool, error)
|
||||||
|
|
||||||
// GetUserPermissions returns user permissions.
|
// GetUserPermissions returns user permissions.
|
||||||
GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*Permission, error)
|
GetUserPermissions(ctx context.Context, user *models.SignedInUser, options Options) ([]*Permission, error)
|
||||||
|
|
||||||
// GetUserRoles returns user roles.
|
// GetUserRoles returns user roles.
|
||||||
GetUserRoles(ctx context.Context, user *models.SignedInUser) ([]*RoleDTO, error)
|
GetUserRoles(ctx context.Context, user *models.SignedInUser) ([]*RoleDTO, error)
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/api/response"
|
||||||
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
|
"github.com/grafana/grafana/pkg/models"
|
||||||
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccessControlAPI struct {
|
||||||
|
RouteRegister routing.RouteRegister
|
||||||
|
AccessControl ac.AccessControl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *AccessControlAPI) RegisterAPIEndpoints() {
|
||||||
|
// Users
|
||||||
|
api.RouteRegister.Get("/api/access-control/user/permissions",
|
||||||
|
middleware.ReqSignedIn, routing.Wrap(api.getUsersPermissions))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/access-control/user/permissions
|
||||||
|
func (api *AccessControlAPI) getUsersPermissions(c *models.ReqContext) response.Response {
|
||||||
|
reloadCache := c.QueryBool("reloadcache")
|
||||||
|
permissions, err := api.AccessControl.GetUserPermissions(c.Req.Context(),
|
||||||
|
c.SignedInUser, ac.Options{ReloadCache: reloadCache})
|
||||||
|
if err != nil {
|
||||||
|
response.JSON(http.StatusInternalServerError, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.JSON(http.StatusOK, ac.BuildPermissionsMap(permissions))
|
||||||
|
}
|
||||||
@@ -156,7 +156,8 @@ func LoadPermissionsMiddleware(ac accesscontrol.AccessControl) web.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions, err := ac.GetUserPermissions(c.Req.Context(), c.SignedInUser)
|
permissions, err := ac.GetUserPermissions(c.Req.Context(), c.SignedInUser,
|
||||||
|
accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JsonApiErr(http.StatusForbidden, "", err)
|
c.JsonApiErr(http.StatusForbidden, "", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ type Mock struct {
|
|||||||
|
|
||||||
// Override functions
|
// Override functions
|
||||||
EvaluateFunc func(context.Context, *models.SignedInUser, accesscontrol.Evaluator) (bool, error)
|
EvaluateFunc func(context.Context, *models.SignedInUser, accesscontrol.Evaluator) (bool, error)
|
||||||
GetUserPermissionsFunc func(context.Context, *models.SignedInUser) ([]*accesscontrol.Permission, error)
|
GetUserPermissionsFunc func(context.Context, *models.SignedInUser, accesscontrol.Options) ([]*accesscontrol.Permission, error)
|
||||||
GetUserRolesFunc func(context.Context, *models.SignedInUser) ([]*accesscontrol.RoleDTO, error)
|
GetUserRolesFunc func(context.Context, *models.SignedInUser) ([]*accesscontrol.RoleDTO, error)
|
||||||
IsDisabledFunc func() bool
|
IsDisabledFunc func() bool
|
||||||
DeclareFixedRolesFunc func(...accesscontrol.RoleRegistration) error
|
DeclareFixedRolesFunc func(...accesscontrol.RoleRegistration) error
|
||||||
@@ -86,7 +86,7 @@ func (m *Mock) Evaluate(ctx context.Context, user *models.SignedInUser, evaluato
|
|||||||
return m.EvaluateFunc(ctx, user, evaluator)
|
return m.EvaluateFunc(ctx, user, evaluator)
|
||||||
}
|
}
|
||||||
// Otherwise perform an actual evaluation of the permissions
|
// Otherwise perform an actual evaluation of the permissions
|
||||||
permissions, err := m.GetUserPermissions(ctx, user)
|
permissions, err := m.GetUserPermissions(ctx, user, accesscontrol.Options{ReloadCache: false})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -95,11 +95,12 @@ func (m *Mock) Evaluate(ctx context.Context, user *models.SignedInUser, evaluato
|
|||||||
|
|
||||||
// GetUserPermissions returns user permissions.
|
// GetUserPermissions returns user permissions.
|
||||||
// This mock return m.permissions unless an override is provided.
|
// This mock return m.permissions unless an override is provided.
|
||||||
func (m *Mock) GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func (m *Mock) GetUserPermissions(ctx context.Context, user *models.SignedInUser,
|
||||||
m.Calls.GetUserPermissions = append(m.Calls.GetUserPermissions, []interface{}{ctx, user})
|
opts accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
|
m.Calls.GetUserPermissions = append(m.Calls.GetUserPermissions, []interface{}{ctx, user, opts})
|
||||||
// Use override if provided
|
// Use override if provided
|
||||||
if m.GetUserPermissionsFunc != nil {
|
if m.GetUserPermissionsFunc != nil {
|
||||||
return m.GetUserPermissionsFunc(ctx, user)
|
return m.GetUserPermissionsFunc(ctx, user, opts)
|
||||||
}
|
}
|
||||||
// Otherwise return the Permissions list
|
// Otherwise return the Permissions list
|
||||||
return m.permissions, nil
|
return m.permissions, nil
|
||||||
|
|||||||
@@ -4,19 +4,29 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol/api"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourceservices"
|
"github.com/grafana/grafana/pkg/services/accesscontrol/resourceservices"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideService(features featuremgmt.FeatureToggles, usageStats usagestats.Service, provider accesscontrol.PermissionsProvider) *OSSAccessControlService {
|
func ProvideService(features featuremgmt.FeatureToggles, usageStats usagestats.Service,
|
||||||
|
provider accesscontrol.PermissionsProvider, routeRegister routing.RouteRegister) *OSSAccessControlService {
|
||||||
s := ProvideOSSAccessControl(features, usageStats, provider)
|
s := ProvideOSSAccessControl(features, usageStats, provider)
|
||||||
s.registerUsageMetrics()
|
s.registerUsageMetrics()
|
||||||
|
if !s.IsDisabled() {
|
||||||
|
api := api.AccessControlAPI{
|
||||||
|
RouteRegister: routeRegister,
|
||||||
|
AccessControl: s,
|
||||||
|
}
|
||||||
|
api.RegisterAPIEndpoints()
|
||||||
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +85,7 @@ func (ac *OSSAccessControlService) Evaluate(ctx context.Context, user *models.Si
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := user.Permissions[user.OrgId]; !ok {
|
if _, ok := user.Permissions[user.OrgId]; !ok {
|
||||||
permissions, err := ac.GetUserPermissions(ctx, user)
|
permissions, err := ac.GetUserPermissions(ctx, user, accesscontrol.Options{ReloadCache: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -96,7 +106,7 @@ func (ac *OSSAccessControlService) GetUserRoles(ctx context.Context, user *model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserPermissions returns user permissions based on built-in roles
|
// GetUserPermissions returns user permissions based on built-in roles
|
||||||
func (ac *OSSAccessControlService) GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func (ac *OSSAccessControlService) GetUserPermissions(ctx context.Context, user *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
|
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
|
||||||
defer timer.ObserveDuration()
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
@@ -152,6 +153,7 @@ func TestUsageMetrics(t *testing.T) {
|
|||||||
featuremgmt.WithFeatures("accesscontrol", tt.enabled),
|
featuremgmt.WithFeatures("accesscontrol", tt.enabled),
|
||||||
&usagestats.UsageStatsMock{T: t},
|
&usagestats.UsageStatsMock{T: t},
|
||||||
database.ProvideService(sqlstore.InitTestDB(t)),
|
database.ProvideService(sqlstore.InitTestDB(t)),
|
||||||
|
routing.NewRouteRegister(),
|
||||||
)
|
)
|
||||||
report, err := s.usageStats.GetUsageReport(context.Background())
|
report, err := s.usageStats.GetUsageReport(context.Background())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
@@ -543,7 +545,7 @@ func TestOSSAccessControlService_GetUserPermissions(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
userPerms, err := ac.GetUserPermissions(context.Background(), &tt.user)
|
userPerms, err := ac.GetUserPermissions(context.Background(), &tt.user, accesscontrol.Options{})
|
||||||
if tt.wantErr {
|
if tt.wantErr {
|
||||||
assert.Error(t, err, "Expected an error with GetUserPermissions.")
|
assert.Error(t, err, "Expected an error with GetUserPermissions.")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
|
|||||||
user: tests.TestUser{Login: "servicetest1@admin", IsServiceAccount: true},
|
user: tests.TestUser{Login: "servicetest1@admin", IsServiceAccount: true},
|
||||||
acmock: tests.SetupMockAccesscontrol(
|
acmock: tests.SetupMockAccesscontrol(
|
||||||
t,
|
t,
|
||||||
func(c context.Context, siu *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func(c context.Context, siu *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
return []*accesscontrol.Permission{{Action: serviceaccounts.ActionDelete, Scope: serviceaccounts.ScopeAll}}, nil
|
return []*accesscontrol.Permission{{Action: serviceaccounts.ActionDelete, Scope: serviceaccounts.ScopeAll}}, nil
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -74,7 +74,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
|
|||||||
user: tests.TestUser{Login: "servicetest2@admin", IsServiceAccount: true},
|
user: tests.TestUser{Login: "servicetest2@admin", IsServiceAccount: true},
|
||||||
acmock: tests.SetupMockAccesscontrol(
|
acmock: tests.SetupMockAccesscontrol(
|
||||||
t,
|
t,
|
||||||
func(c context.Context, siu *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func(c context.Context, siu *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
return []*accesscontrol.Permission{}, nil
|
return []*accesscontrol.Permission{}, nil
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -134,7 +134,7 @@ func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
|
|||||||
user: &tests.TestUser{Login: "servicetest1@admin", IsServiceAccount: true},
|
user: &tests.TestUser{Login: "servicetest1@admin", IsServiceAccount: true},
|
||||||
acmock: tests.SetupMockAccesscontrol(
|
acmock: tests.SetupMockAccesscontrol(
|
||||||
t,
|
t,
|
||||||
func(c context.Context, siu *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func(c context.Context, siu *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
return []*accesscontrol.Permission{{Action: serviceaccounts.ActionRead, Scope: serviceaccounts.ScopeAll}}, nil
|
return []*accesscontrol.Permission{{Action: serviceaccounts.ActionRead, Scope: serviceaccounts.ScopeAll}}, nil
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -146,7 +146,7 @@ func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
|
|||||||
user: &tests.TestUser{Login: "servicetest2@admin", IsServiceAccount: true},
|
user: &tests.TestUser{Login: "servicetest2@admin", IsServiceAccount: true},
|
||||||
acmock: tests.SetupMockAccesscontrol(
|
acmock: tests.SetupMockAccesscontrol(
|
||||||
t,
|
t,
|
||||||
func(c context.Context, siu *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func(c context.Context, siu *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
return []*accesscontrol.Permission{}, nil
|
return []*accesscontrol.Permission{}, nil
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@@ -159,7 +159,7 @@ func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
|
|||||||
userID: 12,
|
userID: 12,
|
||||||
acmock: tests.SetupMockAccesscontrol(
|
acmock: tests.SetupMockAccesscontrol(
|
||||||
t,
|
t,
|
||||||
func(c context.Context, siu *models.SignedInUser) ([]*accesscontrol.Permission, error) {
|
func(c context.Context, siu *models.SignedInUser, _ accesscontrol.Options) ([]*accesscontrol.Permission, error) {
|
||||||
return []*accesscontrol.Permission{{Action: serviceaccounts.ActionRead, Scope: serviceaccounts.ScopeAll}}, nil
|
return []*accesscontrol.Permission{{Action: serviceaccounts.ActionRead, Scope: serviceaccounts.ScopeAll}}, nil
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ func (s *ServiceAccountMock) Migrated(ctx context.Context, orgID int64) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupMockAccesscontrol(t *testing.T, userpermissionsfunc func(c context.Context, siu *models.SignedInUser) ([]*accesscontrol.Permission, error), disableAccessControl bool) *accesscontrolmock.Mock {
|
func SetupMockAccesscontrol(t *testing.T,
|
||||||
|
userpermissionsfunc func(c context.Context, siu *models.SignedInUser, opt accesscontrol.Options) ([]*accesscontrol.Permission, error),
|
||||||
|
disableAccessControl bool) *accesscontrolmock.Mock {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
acmock := accesscontrolmock.New()
|
acmock := accesscontrolmock.New()
|
||||||
if disableAccessControl {
|
if disableAccessControl {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import config from '../../core/config';
|
|||||||
import { extend } from 'lodash';
|
import { extend } from 'lodash';
|
||||||
import { rangeUtil, WithAccessControlMetadata } from '@grafana/data';
|
import { rangeUtil, WithAccessControlMetadata } from '@grafana/data';
|
||||||
import { AccessControlAction, UserPermission } from 'app/types';
|
import { AccessControlAction, UserPermission } from 'app/types';
|
||||||
import { featureEnabled } from '@grafana/runtime';
|
import { featureEnabled, getBackendSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -66,6 +66,18 @@ export class ContextSrv {
|
|||||||
this.minRefreshInterval = config.minRefreshInterval;
|
this.minRefreshInterval = config.minRefreshInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchUserPermissions() {
|
||||||
|
try {
|
||||||
|
if (this.accessControlEnabled()) {
|
||||||
|
this.user.permissions = await getBackendSrv().get('/api/access-control/user/permissions', {
|
||||||
|
reloadcache: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate the user has been logged out
|
* Indicate the user has been logged out
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { getBackendSrv, locationService } from '@grafana/runtime';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { getNavModel } from 'app/core/selectors/navModel';
|
import { getNavModel } from 'app/core/selectors/navModel';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
|
import { contextSrv } from 'app/core/core';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
navModel: NavModel;
|
navModel: NavModel;
|
||||||
@@ -20,6 +21,7 @@ export class CreateTeam extends PureComponent<Props> {
|
|||||||
create = async (formModel: TeamDTO) => {
|
create = async (formModel: TeamDTO) => {
|
||||||
const result = await getBackendSrv().post('/api/teams', formModel);
|
const result = await getBackendSrv().post('/api/teams', formModel);
|
||||||
if (result.teamId) {
|
if (result.teamId) {
|
||||||
|
await contextSrv.fetchUserPermissions();
|
||||||
locationService.push(`/org/teams/edit/${result.teamId}`);
|
locationService.push(`/org/teams/edit/${result.teamId}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export function getAppRoutes(): RouteDescriptor[] {
|
|||||||
roles: () =>
|
roles: () =>
|
||||||
contextSrv.evaluatePermission(
|
contextSrv.evaluatePermission(
|
||||||
() => (config.editorsCanAdmin ? ['Editor', 'Admin'] : ['Admin']),
|
() => (config.editorsCanAdmin ? ['Editor', 'Admin'] : ['Admin']),
|
||||||
[AccessControlAction.ActionTeamsRead]
|
[AccessControlAction.ActionTeamsRead, AccessControlAction.ActionTeamsCreate]
|
||||||
),
|
),
|
||||||
component: SafeDynamicImport(() => import(/* webpackChunkName: "TeamPages" */ 'app/features/teams/TeamPages')),
|
component: SafeDynamicImport(() => import(/* webpackChunkName: "TeamPages" */ 'app/features/teams/TeamPages')),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user