Access control: Build navigation links with access control (#33024)

* Build nav links with access control

* Break up getNavTree (reduce cyclomatic complexity)

* Fix tests

* Use only ActionUsersRead permissions

* Remove unused permissions definitions

* Chore: remove unused fallbacks

* Fix linter error
This commit is contained in:
Alexander Zobnin 2021-04-19 12:23:29 +03:00 committed by GitHub
parent 381e4a51cd
commit 41f6af96c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 15 deletions

View File

@ -8,7 +8,7 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/setting"
)
@ -299,20 +299,9 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
})
}
if c.IsGrafanaAdmin {
adminNavLinks := []*dtos.NavLink{
{Text: "Users", Id: "global-users", Url: hs.Cfg.AppSubURL + "/admin/users", Icon: "user"},
{Text: "Orgs", Id: "global-orgs", Url: hs.Cfg.AppSubURL + "/admin/orgs", Icon: "building"},
{Text: "Settings", Id: "server-settings", Url: hs.Cfg.AppSubURL + "/admin/settings", Icon: "sliders-v-alt"},
{Text: "Stats", Id: "server-stats", Url: hs.Cfg.AppSubURL + "/admin/stats", Icon: "graph-bar"},
}
if hs.Cfg.LDAPEnabled {
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
Text: "LDAP", Id: "ldap", Url: hs.Cfg.AppSubURL + "/admin/ldap", Icon: "book",
})
}
adminNavLinks := hs.buildAdminNavLinks(c)
if len(adminNavLinks) > 0 {
navTree = append(navTree, &dtos.NavLink{
Text: "Server Admin",
SubTitle: "Manage all users and orgs",
@ -344,6 +333,36 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
return navTree, nil
}
func (hs *HTTPServer) buildAdminNavLinks(c *models.ReqContext) []*dtos.NavLink {
hasAccess := ac.HasAccess(hs.AccessControl, c)
adminNavLinks := []*dtos.NavLink{}
if hasAccess(ac.ReqGrafanaAdmin, ac.ActionUsersRead, ac.ScopeUsersAll) {
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
Text: "Users", Id: "global-users", Url: hs.Cfg.AppSubURL + "/admin/users", Icon: "user",
})
}
if c.IsGrafanaAdmin {
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
Text: "Orgs", Id: "global-orgs", Url: hs.Cfg.AppSubURL + "/admin/orgs", Icon: "building",
})
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
Text: "Settings", Id: "server-settings", Url: hs.Cfg.AppSubURL + "/admin/settings", Icon: "sliders-v-alt",
})
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
Text: "Stats", Id: "server-stats", Url: hs.Cfg.AppSubURL + "/admin/stats", Icon: "graph-bar",
})
if hs.Cfg.LDAPEnabled {
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
Text: "LDAP", Id: "ldap", Url: hs.Cfg.AppSubURL + "/admin/ldap", Icon: "book",
})
}
}
return adminNavLinks
}
func (hs *HTTPServer) setIndexViewData(c *models.ReqContext) (*dtos.IndexViewData, error) {
hasEditPermissionInFoldersQuery := models.HasEditPermissionInFoldersQuery{SignedInUser: c.SignedInUser}
if err := bus.Dispatch(&hasEditPermissionInFoldersQuery); err != nil {
@ -434,7 +453,7 @@ func (hs *HTTPServer) setIndexViewData(c *models.ReqContext) (*dtos.IndexViewDat
return nil, err
}
data.User.Permissions = accesscontrol.BuildPermissionsMap(userPermissions)
data.User.Permissions = ac.BuildPermissionsMap(userPermissions)
}
if setting.DisableGravatar {

View File

@ -17,6 +17,26 @@ type AccessControl interface {
IsDisabled() bool
}
func HasAccess(ac AccessControl, c *models.ReqContext) func(fallback func(*models.ReqContext) bool, permission string, scopes ...string) bool {
return func(fallback func(*models.ReqContext) bool, permission string, scopes ...string) bool {
if ac.IsDisabled() {
return fallback(c)
}
hasAccess, err := ac.Evaluate(c.Req.Context(), c.SignedInUser, permission, scopes...)
if err != nil {
c.Logger.Error("Error from access control system", "error", err)
return false
}
return hasAccess
}
}
var ReqGrafanaAdmin = func(c *models.ReqContext) bool {
return c.IsGrafanaAdmin
}
func BuildPermissionsMap(permissions []*Permission) map[string]map[string]string {
permissionsMap := make(map[string]map[string]string)
for _, p := range permissions {