Access control: Support uids for resource permissions (#45226)
* add middleware to solve uid -> id for requests
This commit is contained in:
@@ -3,6 +3,7 @@ package resourcepermissions
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
@@ -152,20 +154,7 @@ func TestApi_getPermissions(t *testing.T) {
|
||||
service, sql := setupTestEnvironment(t, tt.permissions, testOptions)
|
||||
server := setupTestServer(t, &models.SignedInUser{OrgId: 1}, service)
|
||||
|
||||
// seed team 1 with "Edit" permission on dashboard 1
|
||||
team, err := sql.CreateTeam("test", "test@test.com", 1)
|
||||
require.NoError(t, err)
|
||||
_, err = service.SetTeamPermission(context.Background(), team.OrgId, team.Id, tt.resourceID, "Edit")
|
||||
require.NoError(t, err)
|
||||
// seed user 1 with "View" permission on dashboard 1
|
||||
u, err := sql.CreateUser(context.Background(), models.CreateUserCommand{Login: "test", OrgId: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = service.SetUserPermission(context.Background(), u.OrgId, accesscontrol.User{ID: u.Id}, tt.resourceID, "View")
|
||||
require.NoError(t, err)
|
||||
|
||||
// seed built in role Admin with "Edit" permission on dashboard 1
|
||||
_, err = service.SetBuiltInRolePermission(context.Background(), 1, "Admin", tt.resourceID, "Edit")
|
||||
require.NoError(t, err)
|
||||
seedPermissions(t, tt.resourceID, sql, service)
|
||||
|
||||
permissions, recorder := getPermission(t, server, testOptions.Resource, tt.resourceID)
|
||||
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
||||
@@ -418,6 +407,62 @@ func TestApi_setUserPermission(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type uidSolverTestCase struct {
|
||||
desc string
|
||||
uid string
|
||||
resourceID string
|
||||
expectedStatus int
|
||||
}
|
||||
|
||||
func TestApi_UidSolver(t *testing.T) {
|
||||
tests := []uidSolverTestCase{
|
||||
{
|
||||
desc: "expect uid to be mapped to id",
|
||||
uid: "resourceUID",
|
||||
resourceID: "1",
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "expect 404 when uid is not mapped to an id",
|
||||
uid: "notfound",
|
||||
resourceID: "1",
|
||||
expectedStatus: http.StatusNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
userPermissions := []*accesscontrol.Permission{{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"}}
|
||||
service, sql := setupTestEnvironment(t, userPermissions, withSolver(testOptions, testSolver))
|
||||
server := setupTestServer(t, &models.SignedInUser{OrgId: 1}, service)
|
||||
seedPermissions(t, tt.resourceID, sql, service)
|
||||
|
||||
permissions, recorder := getPermission(t, server, testOptions.Resource, tt.uid)
|
||||
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
||||
|
||||
if tt.expectedStatus == http.StatusOK {
|
||||
assert.Len(t, permissions, 3, "expected three assignments: user, team, builtin")
|
||||
for _, p := range permissions {
|
||||
if p.UserID != 0 {
|
||||
assert.Equal(t, "View", p.Permission)
|
||||
} else if p.TeamID != 0 {
|
||||
assert.Equal(t, "Edit", p.Permission)
|
||||
} else {
|
||||
assert.Equal(t, "Edit", p.Permission)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func withSolver(options Options, solver uidSolver) Options {
|
||||
options.UidSolver = solver
|
||||
return options
|
||||
}
|
||||
|
||||
func setupTestServer(t *testing.T, user *models.SignedInUser, service *Service) *web.Mux {
|
||||
server := web.New()
|
||||
server.UseMiddleware(web.Renderer(path.Join(setting.StaticRootPath, "views"), "[[", "]]"))
|
||||
@@ -457,6 +502,13 @@ var testOptions = Options{
|
||||
},
|
||||
}
|
||||
|
||||
var testSolver = func(ctx context.Context, orgID int64, uid string) (int64, error) {
|
||||
if uid == "resourceUID" {
|
||||
return 1, nil
|
||||
}
|
||||
return 0, errors.New("not found")
|
||||
}
|
||||
|
||||
func getPermission(t *testing.T, server *web.Mux, resource, resourceID string) ([]resourcePermissionDTO, *httptest.ResponseRecorder) {
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/api/access-control/%s/%s", resource, resourceID), nil)
|
||||
require.NoError(t, err)
|
||||
@@ -480,3 +532,20 @@ func setPermission(t *testing.T, server *web.Mux, resource, resourceID, permissi
|
||||
|
||||
return recorder
|
||||
}
|
||||
|
||||
func seedPermissions(t *testing.T, resourceID string, sql *sqlstore.SQLStore, service *Service) {
|
||||
t.Helper()
|
||||
// seed team 1 with "Edit" permission on dashboard 1
|
||||
team, err := sql.CreateTeam("test", "test@test.com", 1)
|
||||
require.NoError(t, err)
|
||||
_, err = service.SetTeamPermission(context.Background(), team.OrgId, team.Id, resourceID, "Edit")
|
||||
require.NoError(t, err)
|
||||
// seed user 1 with "View" permission on dashboard 1
|
||||
u, err := sql.CreateUser(context.Background(), models.CreateUserCommand{Login: "test", OrgId: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = service.SetUserPermission(context.Background(), u.OrgId, accesscontrol.User{ID: u.Id}, resourceID, "View")
|
||||
require.NoError(t, err)
|
||||
// seed built in role Admin with "Edit" permission on dashboard 1
|
||||
_, err = service.SetBuiltInRolePermission(context.Background(), 1, "Admin", resourceID, "Edit")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user