mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Auth: Add SignedIn user interface NamespacedID (#72944)
* wip * scope active user to 1 org * remove TODOs * add render auth namespace * import cycle fix * make condition more readable * convert Evaluate to user Requester * only use active OrgID for SearchUserPermissions * add cache key to interface definition * change final SignedInUsers to interface * fix api key managed roles fetch * fix anon auth id parsing * Update pkg/services/accesscontrol/acimpl/accesscontrol.go Co-authored-by: Ieva <ieva.vasiljeva@grafana.com> --------- Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
parent
144e4887ee
commit
bd1a856d33
@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@ -14,7 +15,7 @@ import (
|
||||
|
||||
type AccessControl interface {
|
||||
// Evaluate evaluates access to the given resources.
|
||||
Evaluate(ctx context.Context, user *user.SignedInUser, evaluator Evaluator) (bool, error)
|
||||
Evaluate(ctx context.Context, user identity.Requester, evaluator Evaluator) (bool, error)
|
||||
// RegisterScopeAttributeResolver allows the caller to register a scope resolver for a
|
||||
// specific scope prefix (ex: datasources:name:)
|
||||
RegisterScopeAttributeResolver(prefix string, resolver ScopeAttributeResolver)
|
||||
@ -25,11 +26,11 @@ type AccessControl interface {
|
||||
type Service interface {
|
||||
registry.ProvidesUsageStats
|
||||
// GetUserPermissions returns user permissions with only action and scope fields set.
|
||||
GetUserPermissions(ctx context.Context, user *user.SignedInUser, options Options) ([]Permission, error)
|
||||
GetUserPermissions(ctx context.Context, user identity.Requester, options Options) ([]Permission, error)
|
||||
// SearchUsersPermissions returns all users' permissions filtered by an action prefix
|
||||
SearchUsersPermissions(ctx context.Context, user *user.SignedInUser, orgID int64, options SearchOptions) (map[int64][]Permission, error)
|
||||
SearchUsersPermissions(ctx context.Context, user identity.Requester, options SearchOptions) (map[int64][]Permission, error)
|
||||
// ClearUserPermissionCache removes the permission cache entry for the given user
|
||||
ClearUserPermissionCache(user *user.SignedInUser)
|
||||
ClearUserPermissionCache(user identity.Requester)
|
||||
// SearchUserPermissions returns single user's permissions filtered by an action prefix or an action
|
||||
SearchUserPermissions(ctx context.Context, orgID int64, filterOptions SearchOptions) ([]Permission, error)
|
||||
// DeleteUserPermissions removes all permissions user has in org and all permission to that user
|
||||
@ -375,10 +376,10 @@ func IsDisabled(cfg *setting.Cfg) bool {
|
||||
}
|
||||
|
||||
// GetOrgRoles returns legacy org roles for a user
|
||||
func GetOrgRoles(user *user.SignedInUser) []string {
|
||||
roles := []string{string(user.OrgRole)}
|
||||
func GetOrgRoles(user identity.Requester) []string {
|
||||
roles := []string{string(user.GetOrgRole())}
|
||||
|
||||
if user.IsGrafanaAdmin {
|
||||
if user.GetIsGrafanaAdmin() {
|
||||
roles = append(roles, RoleGrafanaAdmin)
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@ -28,21 +28,28 @@ type AccessControl struct {
|
||||
resolvers accesscontrol.Resolvers
|
||||
}
|
||||
|
||||
func (a *AccessControl) Evaluate(ctx context.Context, user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
func (a *AccessControl) Evaluate(ctx context.Context, user identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
timer := prometheus.NewTimer(metrics.MAccessEvaluationsSummary)
|
||||
defer timer.ObserveDuration()
|
||||
metrics.MAccessEvaluationCount.Inc()
|
||||
|
||||
if !verifyPermissions(user) {
|
||||
a.log.Warn("no permissions set for user", "userID", user.UserID, "orgID", user.OrgID, "login", user.Login)
|
||||
if user == nil || user.IsNil() {
|
||||
a.log.Warn("no entity set for access control evaluation")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
namespace, identifier := user.GetNamespacedID()
|
||||
if len(user.GetPermissions()) == 0 {
|
||||
a.log.Warn("no permissions set for entity", "namespace", namespace, "id", identifier, "orgID", user.GetOrgID(), "login", user.GetLogin())
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Test evaluation without scope resolver first, this will prevent 403 for wildcard scopes when resource does not exist
|
||||
if evaluator.Evaluate(user.Permissions[user.OrgID]) {
|
||||
if evaluator.Evaluate(user.GetPermissions()) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
resolvedEvaluator, err := evaluator.MutateScopes(ctx, a.resolvers.GetScopeAttributeMutator(user.OrgID))
|
||||
resolvedEvaluator, err := evaluator.MutateScopes(ctx, a.resolvers.GetScopeAttributeMutator(user.GetOrgID()))
|
||||
if err != nil {
|
||||
if errors.Is(err, accesscontrol.ErrResolverNotFound) {
|
||||
return false, nil
|
||||
@ -50,7 +57,7 @@ func (a *AccessControl) Evaluate(ctx context.Context, user *user.SignedInUser, e
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resolvedEvaluator.Evaluate(user.Permissions[user.OrgID]), nil
|
||||
return resolvedEvaluator.Evaluate(user.GetPermissions()), nil
|
||||
}
|
||||
|
||||
func (a *AccessControl) RegisterScopeAttributeResolver(prefix string, resolver accesscontrol.ScopeAttributeResolver) {
|
||||
@ -60,7 +67,3 @@ func (a *AccessControl) RegisterScopeAttributeResolver(prefix string, resolver a
|
||||
func (a *AccessControl) IsDisabled() bool {
|
||||
return accesscontrol.IsDisabled(a.cfg)
|
||||
}
|
||||
|
||||
func verifyPermissions(u *user.SignedInUser) bool {
|
||||
return u.Permissions != nil || u.Permissions[u.OrgID] != nil
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/database"
|
||||
"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"
|
||||
@ -95,7 +97,7 @@ func (s *Service) GetUsageStats(_ context.Context) map[string]interface{} {
|
||||
}
|
||||
|
||||
// GetUserPermissions returns user permissions based on built-in roles
|
||||
func (s *Service) GetUserPermissions(ctx context.Context, user *user.SignedInUser, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
func (s *Service) GetUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
|
||||
defer timer.ObserveDuration()
|
||||
|
||||
@ -106,7 +108,7 @@ func (s *Service) GetUserPermissions(ctx context.Context, user *user.SignedInUse
|
||||
return s.getCachedUserPermissions(ctx, user, options)
|
||||
}
|
||||
|
||||
func (s *Service) getUserPermissions(ctx context.Context, user *user.SignedInUser, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
func (s *Service) getUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
permissions := make([]accesscontrol.Permission, 0)
|
||||
for _, builtin := range accesscontrol.GetOrgRoles(user) {
|
||||
if basicRole, ok := s.roles[builtin]; ok {
|
||||
@ -114,11 +116,23 @@ func (s *Service) getUserPermissions(ctx context.Context, user *user.SignedInUse
|
||||
}
|
||||
}
|
||||
|
||||
namespace, identifier := user.GetNamespacedID()
|
||||
|
||||
var userID int64
|
||||
switch namespace {
|
||||
case authn.NamespaceUser, authn.NamespaceServiceAccount, identity.NamespaceRenderService:
|
||||
var err error
|
||||
userID, err = strconv.ParseInt(identifier, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
dbPermissions, err := s.store.GetUserPermissions(ctx, accesscontrol.GetUserPermissionsQuery{
|
||||
OrgID: user.OrgID,
|
||||
UserID: user.UserID,
|
||||
OrgID: user.GetOrgID(),
|
||||
UserID: userID,
|
||||
Roles: accesscontrol.GetOrgRoles(user),
|
||||
TeamIDs: user.Teams,
|
||||
TeamIDs: user.GetTeams(),
|
||||
RolePrefixes: []string{accesscontrol.ManagedRolePrefix, accesscontrol.ExternalServiceRolePrefix},
|
||||
})
|
||||
if err != nil {
|
||||
@ -128,7 +142,7 @@ func (s *Service) getUserPermissions(ctx context.Context, user *user.SignedInUse
|
||||
return append(permissions, dbPermissions...), nil
|
||||
}
|
||||
|
||||
func (s *Service) getCachedUserPermissions(ctx context.Context, user *user.SignedInUser, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
func (s *Service) getCachedUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
key, err := permissionCacheKey(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -154,7 +168,7 @@ func (s *Service) getCachedUserPermissions(ctx context.Context, user *user.Signe
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func (s *Service) ClearUserPermissionCache(user *user.SignedInUser) {
|
||||
func (s *Service) ClearUserPermissionCache(user identity.Requester) {
|
||||
key, err := permissionCacheKey(user)
|
||||
if err != nil {
|
||||
return
|
||||
@ -209,7 +223,7 @@ func (s *Service) IsDisabled() bool {
|
||||
return accesscontrol.IsDisabled(s.cfg)
|
||||
}
|
||||
|
||||
func permissionCacheKey(user *user.SignedInUser) (string, error) {
|
||||
func permissionCacheKey(user identity.Requester) (string, error) {
|
||||
key, err := user.GetCacheKey()
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -248,7 +262,7 @@ func (s *Service) DeclarePluginRoles(_ context.Context, ID, name string, regs []
|
||||
}
|
||||
|
||||
// SearchUsersPermissions returns all users' permissions filtered by action prefixes
|
||||
func (s *Service) SearchUsersPermissions(ctx context.Context, user *user.SignedInUser, orgID int64,
|
||||
func (s *Service) SearchUsersPermissions(ctx context.Context, user identity.Requester,
|
||||
options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
|
||||
// Filter ram permissions
|
||||
basicPermissions := map[string][]accesscontrol.Permission{}
|
||||
@ -260,21 +274,21 @@ func (s *Service) SearchUsersPermissions(ctx context.Context, user *user.SignedI
|
||||
}
|
||||
}
|
||||
|
||||
usersRoles, err := s.store.GetUsersBasicRoles(ctx, nil, orgID)
|
||||
usersRoles, err := s.store.GetUsersBasicRoles(ctx, nil, user.GetOrgID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get managed permissions (DB)
|
||||
usersPermissions, err := s.store.SearchUsersPermissions(ctx, orgID, options)
|
||||
usersPermissions, err := s.store.SearchUsersPermissions(ctx, user.GetOrgID(), options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// helper to filter out permissions the signed in users cannot see
|
||||
canView := func() func(userID int64) bool {
|
||||
siuPermissions, ok := user.Permissions[orgID]
|
||||
if !ok {
|
||||
siuPermissions := user.GetPermissions()
|
||||
if len(siuPermissions) == 0 {
|
||||
return func(_ int64) bool { return false }
|
||||
}
|
||||
scopes, ok := siuPermissions[accesscontrol.ActionUsersPermissionsRead]
|
||||
|
@ -141,7 +141,7 @@ func benchSearchUsersPermissions(b *testing.B, usersCount, resourceCount int) {
|
||||
b.ResetTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
usersPermissions, err := acService.SearchUsersPermissions(context.Background(), siu, 1, accesscontrol.SearchOptions{ActionPrefix: "resources:"})
|
||||
usersPermissions, err := acService.SearchUsersPermissions(context.Background(), siu, accesscontrol.SearchOptions{ActionPrefix: "resources:"})
|
||||
require.NoError(b, err)
|
||||
require.Len(b, usersPermissions, usersCount)
|
||||
for _, permissions := range usersPermissions {
|
||||
@ -206,7 +206,7 @@ func benchSearchUsersWithPerm(b *testing.B, usersCount, resourceCount int) {
|
||||
b.ResetTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
usersPermissions, err := acService.SearchUsersPermissions(context.Background(), siu, 1,
|
||||
usersPermissions, err := acService.SearchUsersPermissions(context.Background(), siu,
|
||||
accesscontrol.SearchOptions{Action: "resources:action2", Scope: "resources:id:1"})
|
||||
require.NoError(b, err)
|
||||
require.Len(b, usersPermissions, usersCount)
|
||||
|
@ -523,7 +523,7 @@ func TestService_SearchUsersPermissions(t *testing.T) {
|
||||
}
|
||||
|
||||
siu := &user.SignedInUser{OrgID: 2, Permissions: map[int64]map[string][]string{2: tt.siuPermissions}}
|
||||
got, err := ac.SearchUsersPermissions(ctx, siu, 2, tt.searchOption)
|
||||
got, err := ac.SearchUsersPermissions(ctx, siu, tt.searchOption)
|
||||
if tt.wantErr {
|
||||
require.NotNil(t, err)
|
||||
return
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
@ -23,11 +24,11 @@ func (f FakeService) GetUsageStats(ctx context.Context) map[string]interface{} {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
func (f FakeService) GetUserPermissions(ctx context.Context, user *user.SignedInUser, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
func (f FakeService) GetUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
return f.ExpectedPermissions, f.ExpectedErr
|
||||
}
|
||||
|
||||
func (f FakeService) SearchUsersPermissions(ctx context.Context, user *user.SignedInUser, orgID int64, options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
|
||||
func (f FakeService) SearchUsersPermissions(ctx context.Context, user identity.Requester, options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
|
||||
return f.ExpectedUsersPermissions, f.ExpectedErr
|
||||
}
|
||||
|
||||
@ -35,7 +36,7 @@ func (f FakeService) SearchUserPermissions(ctx context.Context, orgID int64, sea
|
||||
return f.ExpectedFilteredUserPermissions, f.ExpectedErr
|
||||
}
|
||||
|
||||
func (f FakeService) ClearUserPermissionCache(user *user.SignedInUser) {}
|
||||
func (f FakeService) ClearUserPermissionCache(user identity.Requester) {}
|
||||
|
||||
func (f FakeService) DeleteUserPermissions(ctx context.Context, orgID, userID int64) error {
|
||||
return f.ExpectedErr
|
||||
@ -69,7 +70,7 @@ type FakeAccessControl struct {
|
||||
ExpectedEvaluate bool
|
||||
}
|
||||
|
||||
func (f FakeAccessControl) Evaluate(ctx context.Context, user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
func (f FakeAccessControl) Evaluate(ctx context.Context, user identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
return f.ExpectedEvaluate, f.ExpectedErr
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ func (api *AccessControlAPI) searchUsersPermissions(c *contextmodel.ReqContext)
|
||||
}
|
||||
|
||||
// Compute metadata
|
||||
permissions, err := api.Service.SearchUsersPermissions(c.Req.Context(), c.SignedInUser, c.OrgID, searchOptions)
|
||||
permissions, err := api.Service.SearchUsersPermissions(c.Req.Context(), c.SignedInUser, searchOptions)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "could not get org user permissions", err)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func Filter(user identity.Requester, sqlID, prefix string, actions ...string) (S
|
||||
wildcards := 0
|
||||
result := make(map[interface{}]int)
|
||||
for _, a := range actions {
|
||||
ids, hasWildcard := ParseScopes(prefix, user.GetPermissions(user.GetOrgID())[a])
|
||||
ids, hasWildcard := ParseScopes(prefix, user.GetPermissions()[a])
|
||||
if hasWildcard {
|
||||
wildcards += 1
|
||||
continue
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
@ -101,7 +102,8 @@ func (m *Mock) WithBuiltInRoles(builtInRoles []string) *Mock {
|
||||
|
||||
// Evaluate evaluates access to the given resource.
|
||||
// This mock uses GetUserPermissions to then call the evaluator Evaluate function.
|
||||
func (m *Mock) Evaluate(ctx context.Context, usr *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
func (m *Mock) Evaluate(ctx context.Context, us identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
usr := us.(*user.SignedInUser)
|
||||
m.Calls.Evaluate = append(m.Calls.Evaluate, []interface{}{ctx, usr, evaluator})
|
||||
// Use override if provided
|
||||
if m.EvaluateFunc != nil {
|
||||
@ -138,7 +140,8 @@ func (m *Mock) Evaluate(ctx context.Context, usr *user.SignedInUser, evaluator a
|
||||
|
||||
// GetUserPermissions returns user permissions.
|
||||
// This mock return m.permissions unless an override is provided.
|
||||
func (m *Mock) GetUserPermissions(ctx context.Context, user *user.SignedInUser, opts accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
func (m *Mock) GetUserPermissions(ctx context.Context, usr identity.Requester, opts accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
user := usr.(*user.SignedInUser)
|
||||
m.Calls.GetUserPermissions = append(m.Calls.GetUserPermissions, []interface{}{ctx, user, opts})
|
||||
// Use override if provided
|
||||
if m.GetUserPermissionsFunc != nil {
|
||||
@ -148,7 +151,8 @@ func (m *Mock) GetUserPermissions(ctx context.Context, user *user.SignedInUser,
|
||||
return m.permissions, nil
|
||||
}
|
||||
|
||||
func (m *Mock) ClearUserPermissionCache(user *user.SignedInUser) {
|
||||
func (m *Mock) ClearUserPermissionCache(usr identity.Requester) {
|
||||
user := usr.(*user.SignedInUser)
|
||||
m.Calls.ClearUserPermissionCache = append(m.Calls.ClearUserPermissionCache, []interface{}{user})
|
||||
// Use override if provided
|
||||
if m.ClearUserPermissionCacheFunc != nil {
|
||||
@ -222,11 +226,12 @@ func (m *Mock) DeleteUserPermissions(ctx context.Context, orgID, userID int64) e
|
||||
}
|
||||
|
||||
// SearchUsersPermissions returns all users' permissions filtered by an action prefix
|
||||
func (m *Mock) SearchUsersPermissions(ctx context.Context, user *user.SignedInUser, orgID int64, options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
|
||||
m.Calls.SearchUsersPermissions = append(m.Calls.SearchUsersPermissions, []interface{}{ctx, user, orgID, options})
|
||||
func (m *Mock) SearchUsersPermissions(ctx context.Context, usr identity.Requester, options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
|
||||
user := usr.(*user.SignedInUser)
|
||||
m.Calls.SearchUsersPermissions = append(m.Calls.SearchUsersPermissions, []interface{}{ctx, user, options})
|
||||
// Use override if provided
|
||||
if m.SearchUsersPermissionsFunc != nil {
|
||||
return m.SearchUsersPermissionsFunc(ctx, user, orgID, options)
|
||||
return m.SearchUsersPermissionsFunc(ctx, user, usr.GetOrgID(), options)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -1,9 +1,26 @@
|
||||
package identity
|
||||
|
||||
import "github.com/grafana/grafana/pkg/models/roletype"
|
||||
|
||||
const (
|
||||
NamespaceUser = "user"
|
||||
NamespaceAPIKey = "api-key"
|
||||
NamespaceServiceAccount = "service-account"
|
||||
NamespaceAnonymous = "anonymous"
|
||||
NamespaceRenderService = "render"
|
||||
)
|
||||
|
||||
type Requester interface {
|
||||
GetIsGrafanaAdmin() bool
|
||||
GetLogin() string
|
||||
GetOrgID() int64
|
||||
GetPermissions(orgID int64) map[string][]string
|
||||
GetPermissions() map[string][]string
|
||||
GetTeams() []int64
|
||||
GetOrgRole() roletype.RoleType
|
||||
GetNamespacedID() (string, string)
|
||||
IsNil() bool
|
||||
|
||||
// Legacy
|
||||
GetCacheKey() (string, error)
|
||||
HasUniqueId() bool
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/middleware/cookies"
|
||||
"github.com/grafana/grafana/pkg/models/usertoken"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@ -172,9 +173,9 @@ type Redirect struct {
|
||||
}
|
||||
|
||||
const (
|
||||
NamespaceUser = "user"
|
||||
NamespaceAPIKey = "api-key"
|
||||
NamespaceServiceAccount = "service-account"
|
||||
NamespaceUser = identity.NamespaceUser
|
||||
NamespaceAPIKey = identity.NamespaceAPIKey
|
||||
NamespaceServiceAccount = identity.NamespaceServiceAccount
|
||||
)
|
||||
|
||||
type Identity struct {
|
||||
|
@ -615,7 +615,7 @@ func TestIntegration_SQLStore_GetOrgUsers(t *testing.T) {
|
||||
|
||||
if !hasWildcardScope(tt.query.User, accesscontrol.ActionOrgUsersRead) {
|
||||
for _, u := range result.OrgUsers {
|
||||
assert.Contains(t, tt.query.User.GetPermissions(tt.query.User.GetOrgID())[accesscontrol.ActionOrgUsersRead], fmt.Sprintf("users:id:%d", u.UserID))
|
||||
assert.Contains(t, tt.query.User.GetPermissions()[accesscontrol.ActionOrgUsersRead], fmt.Sprintf("users:id:%d", u.UserID))
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -647,7 +647,7 @@ func seedOrgUsers(t *testing.T, orgUserStore store, store *sqlstore.SQLStore, nu
|
||||
}
|
||||
|
||||
func hasWildcardScope(user identity.Requester, action string) bool {
|
||||
for _, scope := range user.GetPermissions(user.GetOrgID())[action] {
|
||||
for _, scope := range user.GetPermissions()[action] {
|
||||
if strings.HasSuffix(scope, ":*") {
|
||||
return true
|
||||
}
|
||||
@ -792,7 +792,7 @@ func TestIntegration_SQLStore_SearchOrgUsers(t *testing.T) {
|
||||
|
||||
if !hasWildcardScope(tt.query.User, accesscontrol.ActionOrgUsersRead) {
|
||||
for _, u := range result.OrgUsers {
|
||||
assert.Contains(t, tt.query.User.GetPermissions(tt.query.User.GetOrgID())[accesscontrol.ActionOrgUsersRead], fmt.Sprintf("users:id:%d", u.UserID))
|
||||
assert.Contains(t, tt.query.User.GetPermissions()[accesscontrol.ActionOrgUsersRead], fmt.Sprintf("users:id:%d", u.UserID))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models/roletype"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
)
|
||||
|
||||
type SignedInUser struct {
|
||||
@ -105,12 +106,42 @@ func (u *SignedInUser) GetOrgID() int64 {
|
||||
return u.OrgID
|
||||
}
|
||||
|
||||
func (u *SignedInUser) GetPermissions(orgID int64) map[string][]string {
|
||||
func (u *SignedInUser) GetPermissions() map[string][]string {
|
||||
if u.Permissions == nil {
|
||||
return make(map[string][]string)
|
||||
}
|
||||
|
||||
return u.Permissions[orgID]
|
||||
if u.Permissions[u.GetOrgID()] == nil {
|
||||
return make(map[string][]string)
|
||||
}
|
||||
|
||||
return u.Permissions[u.GetOrgID()]
|
||||
}
|
||||
|
||||
func (u *SignedInUser) GetTeams() []int64 {
|
||||
return u.Teams
|
||||
}
|
||||
|
||||
func (u *SignedInUser) GetOrgRole() roletype.RoleType {
|
||||
return u.OrgRole
|
||||
}
|
||||
|
||||
func (u *SignedInUser) GetNamespacedID() (string, string) {
|
||||
switch {
|
||||
case u.ApiKeyID != 0:
|
||||
return identity.NamespaceAPIKey, fmt.Sprintf("%d", u.ApiKeyID)
|
||||
case u.IsServiceAccount:
|
||||
return identity.NamespaceServiceAccount, fmt.Sprintf("%d", u.UserID)
|
||||
case u.UserID != 0:
|
||||
return identity.NamespaceUser, fmt.Sprintf("%d", u.UserID)
|
||||
case u.IsAnonymous:
|
||||
return identity.NamespaceAnonymous, ""
|
||||
case u.AuthenticatedBy == "render": //import cycle render
|
||||
return identity.NamespaceRenderService, fmt.Sprintf("%d", u.UserID)
|
||||
}
|
||||
|
||||
// backwards compatibility
|
||||
return identity.NamespaceUser, fmt.Sprintf("%d", u.UserID)
|
||||
}
|
||||
|
||||
// FIXME: remove this method once all services are using an interface
|
||||
|
Loading…
Reference in New Issue
Block a user