2021-12-20 02:52:24 -06:00
|
|
|
package resourcepermissions
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"path"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
|
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
2022-05-20 11:45:18 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
2022-12-07 10:03:22 -06:00
|
|
|
"github.com/grafana/grafana/pkg/services/org/orgimpl"
|
|
|
|
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
2022-02-10 10:47:48 -06:00
|
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
2022-09-22 12:16:21 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/team/teamimpl"
|
2022-06-28 07:32:25 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/user"
|
2022-12-07 10:03:22 -06:00
|
|
|
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
2021-12-20 02:52:24 -06:00
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
|
|
"github.com/grafana/grafana/pkg/web"
|
|
|
|
)
|
|
|
|
|
|
|
|
type getDescriptionTestCase struct {
|
|
|
|
desc string
|
|
|
|
options Options
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions []accesscontrol.Permission
|
2021-12-20 02:52:24 -06:00
|
|
|
expected Description
|
|
|
|
expectedStatus int
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestApi_getDescription(t *testing.T) {
|
|
|
|
tests := []getDescriptionTestCase{
|
|
|
|
{
|
|
|
|
desc: "should return description",
|
|
|
|
options: Options{
|
2022-03-21 11:58:18 -05:00
|
|
|
Resource: "dashboards",
|
|
|
|
ResourceAttribute: "uid",
|
2021-12-20 02:52:24 -06:00
|
|
|
Assignments: Assignments{
|
|
|
|
Users: true,
|
|
|
|
Teams: true,
|
|
|
|
BuiltInRoles: true,
|
|
|
|
},
|
|
|
|
PermissionsToActions: map[string][]string{
|
|
|
|
"View": {"dashboards:read"},
|
|
|
|
"Edit": {"dashboards:read", "dashboards:write", "dashboards:delete"},
|
|
|
|
"Admin": {"dashboards:read", "dashboards:write", "dashboards:delete", "dashboards.permissions:read", "dashboards:permissions:write"},
|
|
|
|
},
|
|
|
|
},
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read"},
|
|
|
|
},
|
|
|
|
expected: Description{
|
|
|
|
Assignments: Assignments{
|
|
|
|
Users: true,
|
|
|
|
Teams: true,
|
|
|
|
BuiltInRoles: true,
|
|
|
|
},
|
|
|
|
Permissions: []string{"View", "Edit", "Admin"},
|
|
|
|
},
|
|
|
|
expectedStatus: http.StatusOK,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should only return user assignment",
|
|
|
|
options: Options{
|
2022-03-21 11:58:18 -05:00
|
|
|
Resource: "dashboards",
|
|
|
|
ResourceAttribute: "uid",
|
2021-12-20 02:52:24 -06:00
|
|
|
Assignments: Assignments{
|
|
|
|
Users: true,
|
|
|
|
Teams: false,
|
|
|
|
BuiltInRoles: false,
|
|
|
|
},
|
|
|
|
PermissionsToActions: map[string][]string{
|
|
|
|
"View": {"dashboards:read"},
|
|
|
|
},
|
|
|
|
},
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read"},
|
|
|
|
},
|
|
|
|
expected: Description{
|
|
|
|
Assignments: Assignments{
|
|
|
|
Users: true,
|
|
|
|
Teams: false,
|
|
|
|
BuiltInRoles: false,
|
|
|
|
},
|
|
|
|
Permissions: []string{"View"},
|
|
|
|
},
|
|
|
|
expectedStatus: http.StatusOK,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should return 403 when missing read permission",
|
|
|
|
options: Options{
|
2022-03-21 11:58:18 -05:00
|
|
|
Resource: "dashboards",
|
|
|
|
ResourceAttribute: "uid",
|
2021-12-20 02:52:24 -06:00
|
|
|
Assignments: Assignments{
|
|
|
|
Users: true,
|
|
|
|
Teams: false,
|
|
|
|
BuiltInRoles: false,
|
|
|
|
},
|
|
|
|
PermissionsToActions: map[string][]string{
|
|
|
|
"View": {"dashboards:read"},
|
|
|
|
},
|
|
|
|
},
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{},
|
2021-12-20 02:52:24 -06:00
|
|
|
expected: Description{},
|
|
|
|
expectedStatus: http.StatusForbidden,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.desc, func(t *testing.T) {
|
2022-09-22 12:16:21 -05:00
|
|
|
service, _, _ := setupTestEnvironment(t, tt.permissions, tt.options)
|
2022-08-11 06:28:55 -05:00
|
|
|
server := setupTestServer(t, &user.SignedInUser{OrgID: 1}, service)
|
2021-12-23 03:10:06 -06:00
|
|
|
|
2021-12-20 02:52:24 -06:00
|
|
|
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/api/access-control/%s/description", tt.options.Resource), nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
server.ServeHTTP(recorder, req)
|
|
|
|
|
|
|
|
got := Description{}
|
|
|
|
require.NoError(t, json.NewDecoder(recorder.Body).Decode(&got))
|
|
|
|
assert.Equal(t, tt.expected, got)
|
|
|
|
if tt.expectedStatus == http.StatusOK {
|
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type getPermissionsTestCase struct {
|
|
|
|
desc string
|
|
|
|
resourceID string
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions []accesscontrol.Permission
|
2021-12-20 02:52:24 -06:00
|
|
|
expectedStatus int
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestApi_getPermissions(t *testing.T) {
|
|
|
|
tests := []getPermissionsTestCase{
|
|
|
|
{
|
2022-03-01 03:58:41 -06:00
|
|
|
desc: "expect permissions for resource with id 1",
|
|
|
|
resourceID: "1",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
|
|
|
},
|
2021-12-20 02:52:24 -06:00
|
|
|
expectedStatus: 200,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "expect http status 403 when missing permission",
|
|
|
|
resourceID: "1",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{},
|
2021-12-20 02:52:24 -06:00
|
|
|
expectedStatus: 403,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.desc, func(t *testing.T) {
|
2022-09-22 12:16:21 -05:00
|
|
|
service, sql, _ := setupTestEnvironment(t, tt.permissions, testOptions)
|
2022-08-11 06:28:55 -05:00
|
|
|
server := setupTestServer(t, &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}}, service)
|
2021-12-20 02:52:24 -06:00
|
|
|
|
2022-02-10 10:47:48 -06:00
|
|
|
seedPermissions(t, tt.resourceID, sql, service)
|
2021-12-20 02:52:24 -06:00
|
|
|
|
2022-07-26 03:43:29 -05:00
|
|
|
permissions, recorder := getPermission(t, server, testOptions.Resource, tt.resourceID)
|
2021-12-20 02:52:24 -06:00
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
|
|
|
|
if tt.expectedStatus == http.StatusOK {
|
2022-04-05 07:28:23 -05:00
|
|
|
checkSeededPermissions(t, permissions)
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type setBuiltinPermissionTestCase struct {
|
|
|
|
desc string
|
|
|
|
resourceID string
|
|
|
|
builtInRole string
|
|
|
|
expectedStatus int
|
|
|
|
permission string
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions []accesscontrol.Permission
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestApi_setBuiltinRolePermission(t *testing.T) {
|
|
|
|
tests := []setBuiltinPermissionTestCase{
|
|
|
|
{
|
|
|
|
desc: "should set Edit permission for Viewer",
|
|
|
|
resourceID: "1",
|
|
|
|
builtInRole: "Viewer",
|
|
|
|
expectedStatus: 200,
|
|
|
|
permission: "Edit",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set View permission for Admin",
|
|
|
|
resourceID: "1",
|
|
|
|
builtInRole: "Admin",
|
|
|
|
expectedStatus: 200,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should return http 400 for invalid built in role",
|
|
|
|
resourceID: "1",
|
|
|
|
builtInRole: "Invalid",
|
|
|
|
expectedStatus: http.StatusBadRequest,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set return http 403 when missing permissions",
|
|
|
|
resourceID: "1",
|
|
|
|
builtInRole: "Invalid",
|
|
|
|
expectedStatus: http.StatusForbidden,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.desc, func(t *testing.T) {
|
2022-09-22 12:16:21 -05:00
|
|
|
service, _, _ := setupTestEnvironment(t, tt.permissions, testOptions)
|
2022-08-11 06:28:55 -05:00
|
|
|
server := setupTestServer(t, &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}}, service)
|
2021-12-20 02:52:24 -06:00
|
|
|
|
2022-07-26 03:43:29 -05:00
|
|
|
recorder := setPermission(t, server, testOptions.Resource, tt.resourceID, tt.permission, "builtInRoles", tt.builtInRole)
|
2021-12-20 02:52:24 -06:00
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
|
|
|
|
if tt.expectedStatus == http.StatusOK {
|
2022-07-26 03:43:29 -05:00
|
|
|
permissions, _ := getPermission(t, server, testOptions.Resource, tt.resourceID)
|
2021-12-20 02:52:24 -06:00
|
|
|
require.Len(t, permissions, 1)
|
|
|
|
assert.Equal(t, tt.permission, permissions[0].Permission)
|
|
|
|
assert.Equal(t, tt.builtInRole, permissions[0].BuiltInRole)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type setTeamPermissionTestCase struct {
|
|
|
|
desc string
|
|
|
|
teamID int64
|
|
|
|
resourceID string
|
|
|
|
expectedStatus int
|
|
|
|
permission string
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions []accesscontrol.Permission
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestApi_setTeamPermission(t *testing.T) {
|
|
|
|
tests := []setTeamPermissionTestCase{
|
|
|
|
{
|
|
|
|
desc: "should set Edit permission for team 1",
|
|
|
|
teamID: 1,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: 200,
|
|
|
|
permission: "Edit",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set View permission for team 1",
|
|
|
|
teamID: 1,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: 200,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set return http 400 when team does not exist",
|
|
|
|
teamID: 2,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: http.StatusBadRequest,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set return http 403 when missing permissions",
|
|
|
|
teamID: 2,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: http.StatusForbidden,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.desc, func(t *testing.T) {
|
2022-09-22 12:16:21 -05:00
|
|
|
service, _, teamSvc := setupTestEnvironment(t, tt.permissions, testOptions)
|
2022-08-11 06:28:55 -05:00
|
|
|
server := setupTestServer(t, &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}}, service)
|
2021-12-20 02:52:24 -06:00
|
|
|
|
|
|
|
// seed team
|
2022-09-22 12:16:21 -05:00
|
|
|
_, err := teamSvc.CreateTeam("test", "test@test.com", 1)
|
2021-12-20 02:52:24 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-07-26 03:43:29 -05:00
|
|
|
recorder := setPermission(t, server, testOptions.Resource, tt.resourceID, tt.permission, "teams", strconv.Itoa(int(tt.teamID)))
|
2021-12-20 02:52:24 -06:00
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
|
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
if tt.expectedStatus == http.StatusOK {
|
2022-07-26 03:43:29 -05:00
|
|
|
permissions, _ := getPermission(t, server, testOptions.Resource, tt.resourceID)
|
2021-12-20 02:52:24 -06:00
|
|
|
require.Len(t, permissions, 1)
|
|
|
|
assert.Equal(t, tt.permission, permissions[0].Permission)
|
|
|
|
assert.Equal(t, tt.teamID, permissions[0].TeamID)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type setUserPermissionTestCase struct {
|
|
|
|
desc string
|
|
|
|
userID int64
|
|
|
|
resourceID string
|
|
|
|
expectedStatus int
|
|
|
|
permission string
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions []accesscontrol.Permission
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestApi_setUserPermission(t *testing.T) {
|
|
|
|
tests := []setUserPermissionTestCase{
|
|
|
|
{
|
|
|
|
desc: "should set Edit permission for user 1",
|
|
|
|
userID: 1,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: 200,
|
|
|
|
permission: "Edit",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set View permission for user 1",
|
|
|
|
userID: 1,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: 200,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
2022-03-01 03:58:41 -06:00
|
|
|
{Action: accesscontrol.ActionTeamsRead, Scope: accesscontrol.ScopeTeamsAll},
|
|
|
|
{Action: accesscontrol.ActionOrgUsersRead, Scope: accesscontrol.ScopeUsersAll},
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set return http 400 when user does not exist",
|
|
|
|
userID: 2,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: http.StatusBadRequest,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
{Action: "dashboards.permissions:write", Scope: "dashboards:id:1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "should set return http 403 when missing permissions",
|
|
|
|
userID: 2,
|
|
|
|
resourceID: "1",
|
|
|
|
expectedStatus: http.StatusForbidden,
|
|
|
|
permission: "View",
|
2022-06-14 03:17:48 -05:00
|
|
|
permissions: []accesscontrol.Permission{
|
2021-12-20 02:52:24 -06:00
|
|
|
{Action: "dashboards.permissions:read", Scope: "dashboards:id:1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.desc, func(t *testing.T) {
|
2022-09-22 12:16:21 -05:00
|
|
|
service, sql, _ := setupTestEnvironment(t, tt.permissions, testOptions)
|
2022-12-07 10:03:22 -06:00
|
|
|
server := setupTestServer(t, &user.SignedInUser{
|
|
|
|
OrgID: 1,
|
|
|
|
Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)},
|
|
|
|
}, service)
|
2021-12-20 02:52:24 -06:00
|
|
|
|
2021-12-23 03:10:06 -06:00
|
|
|
// seed user
|
2022-12-07 10:03:22 -06:00
|
|
|
orgSvc, err := orgimpl.ProvideService(sql, sql.Cfg, quotatest.New(false, nil))
|
|
|
|
require.NoError(t, err)
|
|
|
|
usrSvc, err := userimpl.ProvideService(sql, orgSvc, sql.Cfg, nil, nil, "atest.FakeQuotaService{})
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "test", OrgID: 1})
|
2021-12-20 02:52:24 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-07-26 03:43:29 -05:00
|
|
|
recorder := setPermission(t, server, testOptions.Resource, tt.resourceID, tt.permission, "users", strconv.Itoa(int(tt.userID)))
|
2021-12-20 02:52:24 -06:00
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
|
2022-07-06 04:34:36 -05:00
|
|
|
assert.Equal(t, tt.expectedStatus, recorder.Code)
|
|
|
|
if tt.expectedStatus == http.StatusOK {
|
2022-07-26 03:43:29 -05:00
|
|
|
permissions, _ := getPermission(t, server, testOptions.Resource, tt.resourceID)
|
2022-07-06 04:34:36 -05:00
|
|
|
require.Len(t, permissions, 1)
|
|
|
|
assert.Equal(t, tt.permission, permissions[0].Permission)
|
2022-07-26 03:43:29 -05:00
|
|
|
assert.Equal(t, tt.userID, permissions[0].UserID)
|
2022-07-06 04:34:36 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-10 04:56:48 -05:00
|
|
|
func setupTestServer(t *testing.T, user *user.SignedInUser, service *Service) *web.Mux {
|
2021-12-20 02:52:24 -06:00
|
|
|
server := web.New()
|
|
|
|
server.UseMiddleware(web.Renderer(path.Join(setting.StaticRootPath, "views"), "[[", "]]"))
|
|
|
|
server.Use(contextProvider(&testContext{user}))
|
|
|
|
service.api.router.Register(server)
|
2021-12-23 03:10:06 -06:00
|
|
|
return server
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type testContext struct {
|
2022-08-10 04:56:48 -05:00
|
|
|
user *user.SignedInUser
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func contextProvider(tc *testContext) web.Handler {
|
|
|
|
return func(c *web.Context) {
|
|
|
|
signedIn := tc.user != nil
|
|
|
|
reqCtx := &models.ReqContext{
|
|
|
|
Context: c,
|
|
|
|
SignedInUser: tc.user,
|
|
|
|
IsSignedIn: signedIn,
|
|
|
|
SkipCache: true,
|
|
|
|
Logger: log.New("test"),
|
|
|
|
}
|
2022-05-20 11:45:18 -05:00
|
|
|
c.Req = c.Req.WithContext(ctxkey.Set(c.Req.Context(), reqCtx))
|
2021-12-20 02:52:24 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-26 03:43:29 -05:00
|
|
|
var testOptions = Options{
|
2022-03-21 11:58:18 -05:00
|
|
|
Resource: "dashboards",
|
|
|
|
ResourceAttribute: "id",
|
2021-12-20 02:52:24 -06:00
|
|
|
Assignments: Assignments{
|
2022-07-26 03:43:29 -05:00
|
|
|
Users: true,
|
|
|
|
Teams: true,
|
|
|
|
BuiltInRoles: true,
|
2021-12-20 02:52:24 -06:00
|
|
|
},
|
|
|
|
PermissionsToActions: map[string][]string{
|
|
|
|
"View": {"dashboards:read"},
|
|
|
|
"Edit": {"dashboards:read", "dashboards:write", "dashboards:delete"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
server.ServeHTTP(recorder, req)
|
|
|
|
|
|
|
|
var permissions []resourcePermissionDTO
|
|
|
|
if recorder.Code == http.StatusOK {
|
|
|
|
require.NoError(t, json.NewDecoder(recorder.Body).Decode(&permissions))
|
|
|
|
}
|
|
|
|
return permissions, recorder
|
|
|
|
}
|
|
|
|
|
|
|
|
func setPermission(t *testing.T, server *web.Mux, resource, resourceID, permission, assignment, assignTo string) *httptest.ResponseRecorder {
|
|
|
|
body := strings.NewReader(fmt.Sprintf(`{"permission": "%s"}`, permission))
|
|
|
|
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("/api/access-control/%s/%s/%s/%s", resource, resourceID, assignment, assignTo), body)
|
|
|
|
require.NoError(t, err)
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
server.ServeHTTP(recorder, req)
|
|
|
|
|
|
|
|
return recorder
|
|
|
|
}
|
2022-02-10 10:47:48 -06:00
|
|
|
|
2022-04-05 07:28:23 -05:00
|
|
|
func checkSeededPermissions(t *testing.T, permissions []resourcePermissionDTO) {
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-10 10:47:48 -06:00
|
|
|
func seedPermissions(t *testing.T, resourceID string, sql *sqlstore.SQLStore, service *Service) {
|
|
|
|
t.Helper()
|
|
|
|
// seed team 1 with "Edit" permission on dashboard 1
|
2022-09-22 12:16:21 -05:00
|
|
|
teamSvc := teamimpl.ProvideService(sql, sql.Cfg)
|
|
|
|
team, err := teamSvc.CreateTeam("test", "test@test.com", 1)
|
2022-02-10 10:47:48 -06:00
|
|
|
require.NoError(t, err)
|
2023-01-11 07:20:09 -06:00
|
|
|
_, err = service.SetTeamPermission(context.Background(), team.OrgID, team.ID, resourceID, "Edit")
|
2022-02-10 10:47:48 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
// seed user 1 with "View" permission on dashboard 1
|
2022-12-07 10:03:22 -06:00
|
|
|
orgSvc, err := orgimpl.ProvideService(sql, sql.Cfg, quotatest.New(false, nil))
|
|
|
|
require.NoError(t, err)
|
|
|
|
usrSvc, err := userimpl.ProvideService(sql, orgSvc, sql.Cfg, nil, nil, "atest.FakeQuotaService{})
|
|
|
|
require.NoError(t, err)
|
|
|
|
u, err := usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "test", OrgID: 1})
|
2022-02-10 10:47:48 -06:00
|
|
|
require.NoError(t, err)
|
2022-06-28 07:32:25 -05:00
|
|
|
_, err = service.SetUserPermission(context.Background(), u.OrgID, accesscontrol.User{ID: u.ID}, resourceID, "View")
|
2022-02-10 10:47:48 -06:00
|
|
|
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)
|
|
|
|
}
|