* 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:
co-authored by
Gabriel MABILLE
parent
ee54923bdd
commit
6909246a7a
+3
-2
@@ -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)
|
||||
|
||||
@@ -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
@@ -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",
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user