RBAC: Add an endpoint to list all user permissions (#57644)

* RBAC: Add an endpoint to see all user permissions

Co-authored-by: Joey Orlando <joey.orlando@grafana.com>

* Fix mock

* Add feature flag

* Fix merging

* Return normal permissions instead of simplified ones

* Fix test

* Fix tests

* Fix tests

* Create benchtests

* Split function to get basic roles

* Comments

* Reorg

* Add two more tests to the bench

* bench comment

* Re-ran the test

* Rename GetUsersPermissions to SearchUsersPermissions and prepare search options

* Remove from model unused struct

* Start adding option to get permissions by Action+Scope

* Wrong import

* Action and Scope

* slightly tweak users permissions actionPrefix query param validation logic

* Fix xor check

* Lint

* Account for suggeston

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

* Add search

* Remove comment on global scope

* use union all and update test to make it run on all dbs

* Fix MySQL needs a space

* Account for suggestion.

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

Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
Co-authored-by: Joey Orlando <joseph.t.orlando@gmail.com>
Co-authored-by: ievaVasiljeva <ieva.vasiljeva@grafana.com>
This commit is contained in:
Gabriel MABILLE
2022-11-30 15:38:49 +01:00
committed by GitHub
co-authored by Joey Orlando ievaVasiljeva Joey Orlando
parent fee50be1bb
commit bf49c20050
14 changed files with 1003 additions and 22 deletions
+39 -1
View File
@@ -8,25 +8,36 @@ import (
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
)
func NewAccessControlAPI(router routing.RouteRegister, service ac.Service) *AccessControlAPI {
func NewAccessControlAPI(router routing.RouteRegister, accesscontrol ac.AccessControl, service ac.Service,
features *featuremgmt.FeatureManager) *AccessControlAPI {
return &AccessControlAPI{
RouteRegister: router,
Service: service,
AccessControl: accesscontrol,
features: features,
}
}
type AccessControlAPI struct {
Service ac.Service
AccessControl ac.AccessControl
RouteRegister routing.RouteRegister
features *featuremgmt.FeatureManager
}
func (api *AccessControlAPI) RegisterAPIEndpoints() {
authorize := ac.Middleware(api.AccessControl)
// Users
api.RouteRegister.Group("/api/access-control", func(rr routing.RouteRegister) {
rr.Get("/user/actions", middleware.ReqSignedIn, routing.Wrap(api.getUserActions))
rr.Get("/user/permissions", middleware.ReqSignedIn, routing.Wrap(api.getUserPermissions))
if api.features.IsEnabled(featuremgmt.FlagAccessControlOnCall) {
rr.Get("/users/permissions/search", authorize(middleware.ReqSignedIn,
ac.EvalPermission(ac.ActionUsersPermissionsRead)), routing.Wrap(api.SearchUsersPermissions))
}
})
}
@@ -53,3 +64,30 @@ func (api *AccessControlAPI) getUserPermissions(c *models.ReqContext) response.R
return response.JSON(http.StatusOK, ac.GroupScopesByAction(permissions))
}
// GET /api/access-control/users/permissions
func (api *AccessControlAPI) SearchUsersPermissions(c *models.ReqContext) response.Response {
searchOptions := ac.SearchOptions{
ActionPrefix: c.Query("actionPrefix"),
Action: c.Query("action"),
Scope: c.Query("scope"),
}
// Validate inputs
if (searchOptions.ActionPrefix != "") == (searchOptions.Action != "") {
return response.JSON(http.StatusBadRequest, "provide one of 'action' or 'actionPrefix'")
}
// Compute metadata
permissions, err := api.Service.SearchUsersPermissions(c.Req.Context(), c.SignedInUser, c.OrgID, searchOptions)
if err != nil {
return response.Error(http.StatusInternalServerError, "could not get org user permissions", err)
}
permsByAction := map[int64]map[string][]string{}
for userID, userPerms := range permissions {
permsByAction[userID] = ac.GroupScopesByAction(userPerms)
}
return response.JSON(http.StatusOK, permsByAction)
}