mirror of
https://github.com/grafana/grafana.git
synced 2024-12-01 21:19:28 -06:00
846eadff63
* Add namespace ID * Refactor and add tests * Rename maxOneOption -> atMostOneOption * Add ToDo * Remove UserLogin & UserID for NamespaceID Co-authored-by: jguer <joao.guerreiro@grafana.com> * Remove unecessary import of the userSvc * Update pkg/services/accesscontrol/acimpl/service.go * fix 1 -> userID * Update pkg/services/accesscontrol/accesscontrol.go --------- Co-authored-by: jguer <joao.guerreiro@grafana.com>
198 lines
6.3 KiB
Go
198 lines
6.3 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/api/routing"
|
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
|
"github.com/grafana/grafana/pkg/services/datasources"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
"github.com/grafana/grafana/pkg/web/webtest"
|
|
)
|
|
|
|
func TestAPI_getUserActions(t *testing.T) {
|
|
type testCase struct {
|
|
desc string
|
|
permissions []ac.Permission
|
|
expectedOutput util.DynMap
|
|
expectedCode int
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
desc: "Should be able to get actions",
|
|
permissions: []ac.Permission{
|
|
{Action: datasources.ActionRead, Scope: datasources.ScopeAll},
|
|
{Action: datasources.ActionRead, Scope: datasources.ScopeProvider.GetResourceScope("aabbccdd")},
|
|
},
|
|
expectedOutput: util.DynMap{datasources.ActionRead: true},
|
|
expectedCode: http.StatusOK,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
acSvc := actest.FakeService{ExpectedPermissions: tt.permissions}
|
|
api := NewAccessControlAPI(routing.NewRouteRegister(), actest.FakeAccessControl{}, acSvc, featuremgmt.WithFeatures())
|
|
api.RegisterAPIEndpoints()
|
|
|
|
server := webtest.NewServer(t, api.RouteRegister)
|
|
url := "/api/access-control/user/actions"
|
|
|
|
req := server.NewGetRequest(url)
|
|
webtest.RequestWithSignedInUser(req, &user.SignedInUser{
|
|
OrgID: 1,
|
|
Permissions: map[int64]map[string][]string{},
|
|
})
|
|
res, err := server.Send(req)
|
|
defer func() { require.NoError(t, res.Body.Close()) }()
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedCode, res.StatusCode)
|
|
|
|
if tt.expectedCode == http.StatusOK {
|
|
var output util.DynMap
|
|
err := json.NewDecoder(res.Body).Decode(&output)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedOutput, output)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAPI_getUserPermissions(t *testing.T) {
|
|
type testCase struct {
|
|
desc string
|
|
permissions []ac.Permission
|
|
expectedOutput util.DynMap
|
|
expectedCode int
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
desc: "Should be able to get permissions with scope",
|
|
permissions: []ac.Permission{
|
|
{Action: datasources.ActionRead, Scope: datasources.ScopeAll},
|
|
{Action: datasources.ActionRead, Scope: datasources.ScopeProvider.GetResourceScope("aabbccdd")},
|
|
},
|
|
expectedOutput: util.DynMap{
|
|
datasources.ActionRead: []any{
|
|
datasources.ScopeAll,
|
|
datasources.ScopeProvider.GetResourceScope("aabbccdd"),
|
|
}},
|
|
expectedCode: http.StatusOK,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
acSvc := actest.FakeService{ExpectedPermissions: tt.permissions}
|
|
api := NewAccessControlAPI(routing.NewRouteRegister(), actest.FakeAccessControl{}, acSvc, featuremgmt.WithFeatures())
|
|
api.RegisterAPIEndpoints()
|
|
|
|
server := webtest.NewServer(t, api.RouteRegister)
|
|
url := "/api/access-control/user/permissions"
|
|
|
|
req := server.NewGetRequest(url)
|
|
webtest.RequestWithSignedInUser(req, &user.SignedInUser{
|
|
OrgID: 1,
|
|
Permissions: map[int64]map[string][]string{},
|
|
})
|
|
res, err := server.Send(req)
|
|
defer func() { require.NoError(t, res.Body.Close()) }()
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedCode, res.StatusCode)
|
|
|
|
if tt.expectedCode == http.StatusOK {
|
|
var output util.DynMap
|
|
err := json.NewDecoder(res.Body).Decode(&output)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedOutput, output)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAccessControlAPI_searchUsersPermissions(t *testing.T) {
|
|
type testCase struct {
|
|
desc string
|
|
permissions map[int64][]ac.Permission
|
|
filters string
|
|
expectedOutput map[int64]map[string][]string
|
|
expectedCode int
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
desc: "Should reject if no filter is provided",
|
|
expectedCode: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "Should reject if conflicting action filters are provided",
|
|
filters: "?actionPrefix=grafana-test-app&action=grafana-test-app.projects:read",
|
|
expectedCode: http.StatusBadRequest,
|
|
},
|
|
{
|
|
desc: "Should work with valid namespacedId filter provided",
|
|
filters: "?namespacedId=service-account:2",
|
|
permissions: map[int64][]ac.Permission{2: {{Action: "users:read", Scope: "users:*"}}},
|
|
expectedCode: http.StatusOK,
|
|
expectedOutput: map[int64]map[string][]string{2: {"users:read": {"users:*"}}},
|
|
},
|
|
{
|
|
desc: "Should reduce permissions",
|
|
filters: "?namespacedId=service-account:2",
|
|
permissions: map[int64][]ac.Permission{2: {{Action: "users:read", Scope: "users:id:1"}, {Action: "users:read", Scope: "users:*"}}},
|
|
expectedCode: http.StatusOK,
|
|
expectedOutput: map[int64]map[string][]string{2: {"users:read": {"users:*"}}},
|
|
},
|
|
{
|
|
desc: "Should work with valid action prefix filter",
|
|
filters: "?actionPrefix=users:",
|
|
permissions: map[int64][]ac.Permission{
|
|
1: {{Action: "users:write", Scope: "users:id:1"}},
|
|
2: {{Action: "users:read", Scope: "users:id:2"}},
|
|
},
|
|
expectedCode: http.StatusOK,
|
|
expectedOutput: map[int64]map[string][]string{
|
|
1: {"users:write": {"users:id:1"}},
|
|
2: {"users:read": {"users:id:2"}},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
acSvc := actest.FakeService{ExpectedUsersPermissions: tt.permissions}
|
|
accessControl := actest.FakeAccessControl{ExpectedEvaluate: true} // Always allow access to the endpoint
|
|
api := NewAccessControlAPI(routing.NewRouteRegister(), accessControl, acSvc, featuremgmt.WithFeatures(featuremgmt.FlagAccessControlOnCall))
|
|
api.RegisterAPIEndpoints()
|
|
|
|
server := webtest.NewServer(t, api.RouteRegister)
|
|
url := "/api/access-control/users/permissions/search" + tt.filters
|
|
|
|
req := server.NewGetRequest(url)
|
|
webtest.RequestWithSignedInUser(req, &user.SignedInUser{
|
|
OrgID: 1,
|
|
Permissions: map[int64]map[string][]string{},
|
|
})
|
|
res, err := server.Send(req)
|
|
defer func() { require.NoError(t, res.Body.Close()) }()
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedCode, res.StatusCode)
|
|
|
|
if tt.expectedCode == http.StatusOK {
|
|
var output map[int64]map[string][]string
|
|
err := json.NewDecoder(res.Body).Decode(&output)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expectedOutput, output)
|
|
}
|
|
})
|
|
}
|
|
}
|