Access control: role checks before updates (#51449) (#51457)

* add role checks

* linting

(cherry picked from commit 0c0cf36ab8)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
Grot (@grafanabot)
2022-06-28 06:23:17 -04:00
committed by GitHub
co-authored by Ieva
parent ddfdc9ee7a
commit f7d9c401c2
3 changed files with 124 additions and 9 deletions
+106
View File
@@ -571,6 +571,112 @@ func TestPostOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
}
}
func TestOrgUsersAPIEndpointWithSetPerms_AccessControl(t *testing.T) {
type accessControlTestCase2 struct {
expectedCode int
desc string
url string
method string
permissions []*accesscontrol.Permission
input string
}
tests := []accessControlTestCase2{
{
expectedCode: http.StatusOK,
desc: "org viewer with the correct permissions can add a user as a viewer to his org",
url: "/api/org/users",
method: http.MethodPost,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersAdd, Scope: accesscontrol.ScopeUsersAll}},
input: `{"loginOrEmail": "` + testAdminOrg2.Login + `", "role": "` + string(models.ROLE_VIEWER) + `"}`,
},
{
expectedCode: http.StatusForbidden,
desc: "org viewer with the correct permissions cannot add a user as an editor to his org",
url: "/api/org/users",
method: http.MethodPost,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersAdd, Scope: accesscontrol.ScopeUsersAll}},
input: `{"loginOrEmail": "` + testAdminOrg2.Login + `", "role": "` + string(models.ROLE_EDITOR) + `"}`,
},
{
expectedCode: http.StatusOK,
desc: "org viewer with the correct permissions can add a user as a viewer to his org",
url: "/api/orgs/1/users",
method: http.MethodPost,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersAdd, Scope: accesscontrol.ScopeUsersAll}},
input: `{"loginOrEmail": "` + testAdminOrg2.Login + `", "role": "` + string(models.ROLE_VIEWER) + `"}`,
},
{
expectedCode: http.StatusForbidden,
desc: "org viewer with the correct permissions cannot add a user as an editor to his org",
url: "/api/orgs/1/users",
method: http.MethodPost,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersAdd, Scope: accesscontrol.ScopeUsersAll}},
input: `{"loginOrEmail": "` + testAdminOrg2.Login + `", "role": "` + string(models.ROLE_EDITOR) + `"}`,
},
{
expectedCode: http.StatusOK,
desc: "org viewer with the correct permissions can update a user's role to a viewer in his org",
url: fmt.Sprintf("/api/org/users/%d", testEditorOrg1.UserId),
method: http.MethodPatch,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersRoleUpdate, Scope: accesscontrol.ScopeUsersAll}},
input: `{"role": "` + string(models.ROLE_VIEWER) + `"}`,
},
{
expectedCode: http.StatusForbidden,
desc: "org viewer with the correct permissions cannot update a user's role to a viewer in his org",
url: fmt.Sprintf("/api/org/users/%d", testEditorOrg1.UserId),
method: http.MethodPatch,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersRoleUpdate, Scope: accesscontrol.ScopeUsersAll}},
input: `{"role": "` + string(models.ROLE_EDITOR) + `"}`,
},
{
expectedCode: http.StatusOK,
desc: "org viewer with the correct permissions can update a user's role to a viewer in his org",
url: fmt.Sprintf("/api/orgs/1/users/%d", testEditorOrg1.UserId),
method: http.MethodPatch,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersRoleUpdate, Scope: accesscontrol.ScopeUsersAll}},
input: `{"role": "` + string(models.ROLE_VIEWER) + `"}`,
},
{
expectedCode: http.StatusForbidden,
desc: "org viewer with the correct permissions cannot update a user's role to a viewer in his org",
url: fmt.Sprintf("/api/orgs/1/users/%d", testEditorOrg1.UserId),
method: http.MethodPatch,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionOrgUsersRoleUpdate, Scope: accesscontrol.ScopeUsersAll}},
input: `{"role": "` + string(models.ROLE_EDITOR) + `"}`,
},
{
expectedCode: http.StatusOK,
desc: "org viewer with the correct permissions can invite a user as a viewer in his org",
url: "/api/org/invites",
method: http.MethodPost,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionUsersCreate}},
input: `{"loginOrEmail": "newUserEmail@test.com", "sendEmail": false, "role": "` + string(models.ROLE_VIEWER) + `"}`,
},
{
expectedCode: http.StatusForbidden,
desc: "org viewer with the correct permissions cannot invite a user as an editor in his org",
url: "/api/org/invites",
method: http.MethodPost,
permissions: []*accesscontrol.Permission{{Action: accesscontrol.ActionUsersCreate}},
input: `{"loginOrEmail": "newUserEmail@test.com", "sendEmail": false, "role": "` + string(models.ROLE_EDITOR) + `"}`,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
sc := setupHTTPServer(t, true, true)
setInitCtxSignedInViewer(sc.initCtx)
setupOrgUsersDBForAccessControlTests(t, sc.db)
setAccessControlPermissions(sc.acmock, test.permissions, sc.initCtx.OrgId)
input := strings.NewReader(test.input)
response := callAPI(sc.server, test.method, test.url, input, t)
assert.Equal(t, test.expectedCode, response.Code)
})
}
}
func TestPatchOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
url := "/api/orgs/%v/users/%v"
type testCase struct {