AccessControl: Change teams permissions page when accesscontrol is enabled (#43971) (#44864)

* AccessControl: Change teams permissions page when frontend is hit

* Implement frontend changes for group sync

* Changing the org/teams/edit permissions

Co-authored-by: ievaVasiljeva <ieva.vasiljeva@grafana.com>

* Fixing routes

Co-authored-by: ievaVasiljeva <ieva.vasiljeva@grafana.com>

* Use props straight away no need to go through the state

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Update public/app/features/teams/TeamPages.tsx

Co-authored-by: ievaVasiljeva <ieva.vasiljeva@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
(cherry picked from commit 8217d6d206)

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
Grot (@grafanabot)
2022-02-03 18:00:38 +01:00
committed by GitHub
co-authored by Gabriel MABILLE
parent ee54923bdd
commit 6909246a7a
23 changed files with 270 additions and 56 deletions
+3 -2
View File
@@ -58,8 +58,9 @@ func (hs *HTTPServer) registerRoutes() {
r.Get("/org/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), hs.Index)
r.Get("/org/users/new", reqOrgAdmin, hs.Index)
r.Get("/org/users/invite", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), hs.Index)
r.Get("/org/teams", reqCanAccessTeams, hs.Index)
r.Get("/org/teams/*", reqCanAccessTeams, hs.Index)
r.Get("/org/teams", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsRead)), hs.Index)
r.Get("/org/teams/edit/*", authorize(reqCanAccessTeams, teamsEditAccessEvaluator), hs.Index)
r.Get("/org/teams/new", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsCreate)), hs.Index)
r.Get("/org/serviceaccounts", middleware.ReqOrgAdmin, hs.Index)
r.Get("/org/serviceaccounts/:serviceAccountId", middleware.ReqOrgAdmin, hs.Index)
r.Get("/org/apikeys/", reqOrgAdmin, hs.Index)
+4 -3
View File
@@ -309,9 +309,10 @@ func setupSimpleHTTPServer(features *featuremgmt.FeatureManager) *HTTPServer {
cfg.IsFeatureToggleEnabled = features.IsEnabled
return &HTTPServer{
Cfg: cfg,
Features: features,
Bus: bus.GetBus(),
Cfg: cfg,
Features: features,
Bus: bus.GetBus(),
AccessControl: accesscontrolmock.New().WithDisabled(),
}
}
+2 -2
View File
@@ -148,7 +148,7 @@ func enableServiceAccount(hs *HTTPServer, c *models.ReqContext) bool {
hs.Features.IsEnabled(featuremgmt.FlagServiceAccounts)
}
func enableTeams(hs *HTTPServer, c *models.ReqContext) bool {
func (hs *HTTPServer) ReqCanAdminTeams(c *models.ReqContext) bool {
return c.OrgRole == models.ROLE_ADMIN || (hs.Cfg.EditorsCanAdmin && c.OrgRole == models.ROLE_EDITOR)
}
@@ -263,7 +263,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
})
}
if enableTeams(hs, c) {
if hasAccess(hs.ReqCanAdminTeams, teamsAccessEvaluator) {
configNodes = append(configNodes, &dtos.NavLink{
Text: "Teams",
Id: "teams",
+19
View File
@@ -298,3 +298,22 @@ var orgsCreateAccessEvaluator = accesscontrol.EvalAll(
accesscontrol.EvalPermission(ActionOrgsRead),
accesscontrol.EvalPermission(ActionOrgsCreate),
)
// teamsAccessEvaluator is used to protect the "Configuration > Teams" page access
var teamsAccessEvaluator = accesscontrol.EvalAll(
accesscontrol.EvalPermission(accesscontrol.ActionTeamsRead),
accesscontrol.EvalAny(
accesscontrol.EvalPermission(accesscontrol.ActionTeamsCreate),
accesscontrol.EvalPermission(accesscontrol.ActionTeamsWrite),
accesscontrol.EvalPermission(accesscontrol.ActionTeamsPermissionsWrite),
),
)
// teamsEditAccessEvaluator is used to protect the "Configuration > Teams > edit" page access
var teamsEditAccessEvaluator = accesscontrol.EvalAll(
accesscontrol.EvalPermission(accesscontrol.ActionTeamsRead),
accesscontrol.EvalAny(
accesscontrol.EvalPermission(accesscontrol.ActionTeamsWrite),
accesscontrol.EvalPermission(accesscontrol.ActionTeamsPermissionsWrite),
),
)
+45
View File
@@ -2,12 +2,14 @@ package api
import (
"errors"
"fmt"
"net/http"
"strconv"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/util"
@@ -105,6 +107,20 @@ func (hs *HTTPServer) DeleteTeamByID(c *models.ReqContext) response.Response {
return response.Success("Team deleted")
}
func (hs *HTTPServer) getTeamsAccessControlMetadata(c *models.ReqContext, teamIDs map[string]bool) (map[string]accesscontrol.Metadata, error) {
if hs.AccessControl.IsDisabled() || !c.QueryBool("accesscontrol") {
return nil, nil
}
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
if err != nil || len(userPermissions) == 0 {
hs.log.Warn("could not fetch accesscontrol metadata for teams", "error", err)
return nil, err
}
return accesscontrol.GetResourcesMetadata(c.Req.Context(), userPermissions, "teams", teamIDs), nil
}
// GET /api/teams/search
func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
perPage := c.QueryInt("perpage")
@@ -136,8 +152,17 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
return response.Error(500, "Failed to search Teams", err)
}
teamIDs := map[string]bool{}
for _, team := range query.Result.Teams {
team.AvatarUrl = dtos.GetGravatarUrlWithDefault(team.Email, team.Name)
teamIDs[strconv.FormatInt(team.Id, 10)] = true
}
metadata, err := hs.getTeamsAccessControlMetadata(c, teamIDs)
if err == nil && len(metadata) != 0 {
for _, team := range query.Result.Teams {
team.AccessControl = metadata[strconv.FormatInt(team.Id, 10)]
}
}
query.Result.Page = page
@@ -146,6 +171,23 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
return response.JSON(200, query.Result)
}
func (hs *HTTPServer) getTeamAccessControlMetadata(c *models.ReqContext, teamID int64) (accesscontrol.Metadata, error) {
if hs.AccessControl.IsDisabled() || !c.QueryBool("accesscontrol") {
return nil, nil
}
userPermissions, err := hs.AccessControl.GetUserPermissions(c.Req.Context(), c.SignedInUser)
if err != nil || len(userPermissions) == 0 {
hs.log.Warn("could not fetch accesscontrol metadata", "team", teamID, "error", err)
return nil, err
}
key := fmt.Sprintf("%d", teamID)
teamIDs := map[string]bool{key: true}
return accesscontrol.GetResourcesMetadata(c.Req.Context(), userPermissions, "teams", teamIDs)[key], nil
}
// GET /api/teams/:teamId
func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) response.Response {
teamId, err := strconv.ParseInt(web.Params(c.Req)[":teamId"], 10, 64)
@@ -167,6 +209,9 @@ func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) response.Response {
return response.Error(500, "Failed to get Team", err)
}
metadata, _ := hs.getTeamAccessControlMetadata(c, query.Result.Id)
query.Result.AccessControl = metadata
query.Result.AvatarUrl = dtos.GetGravatarUrlWithDefault(query.Result.Email, query.Result.Name)
return response.JSON(200, &query.Result)
}