2020-11-24 12:10:32 +01:00
package api
import (
2021-05-12 14:10:35 +02:00
"context"
2020-11-24 12:10:32 +01:00
"encoding/json"
2021-11-17 10:12:28 +01:00
"fmt"
2020-11-24 12:10:32 +01:00
"net/http"
2021-11-17 10:12:28 +01:00
"strings"
2020-11-24 12:10:32 +01:00
"testing"
2021-09-17 09:19:36 +02:00
"time"
2020-11-24 12:10:32 +01:00
2021-11-17 10:12:28 +01:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2021-09-29 12:51:49 +02:00
2020-11-24 12:10:32 +01:00
"github.com/grafana/grafana/pkg/api/dtos"
2021-09-17 09:19:36 +02:00
"github.com/grafana/grafana/pkg/components/simplejson"
2022-10-19 09:02:15 -04:00
"github.com/grafana/grafana/pkg/infra/db"
2022-10-04 12:17:55 +02:00
"github.com/grafana/grafana/pkg/infra/localcache"
2020-11-24 12:10:32 +01:00
"github.com/grafana/grafana/pkg/models"
2021-09-17 09:19:36 +02:00
"github.com/grafana/grafana/pkg/services/accesscontrol"
2022-01-26 09:44:20 -08:00
"github.com/grafana/grafana/pkg/services/featuremgmt"
2022-08-10 11:56:48 +02:00
"github.com/grafana/grafana/pkg/services/org"
2022-09-26 10:27:38 +02:00
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/org/orgtest"
2022-11-14 21:08:10 +02:00
"github.com/grafana/grafana/pkg/services/quota/quotatest"
2021-05-12 14:10:35 +02:00
"github.com/grafana/grafana/pkg/services/sqlstore"
2022-02-03 09:20:20 +01:00
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
2022-10-04 12:17:55 +02:00
"github.com/grafana/grafana/pkg/services/team/teamimpl"
2022-09-20 11:29:17 +02:00
"github.com/grafana/grafana/pkg/services/temp_user/tempuserimpl"
2022-06-28 14:32:25 +02:00
"github.com/grafana/grafana/pkg/services/user"
2022-08-16 16:08:59 +02:00
"github.com/grafana/grafana/pkg/services/user/userimpl"
2022-08-11 15:37:31 +02:00
"github.com/grafana/grafana/pkg/setting"
2021-11-17 10:12:28 +01:00
"github.com/grafana/grafana/pkg/util"
2020-11-24 12:10:32 +01:00
)
2021-05-12 14:10:35 +02:00
func setUpGetOrgUsersDB ( t * testing . T , sqlStore * sqlstore . SQLStore ) {
2022-06-07 09:49:18 -04:00
sqlStore . Cfg . AutoAssignOrg = true
sqlStore . Cfg . AutoAssignOrgId = int ( testOrgID )
2021-05-12 14:10:35 +02:00
2022-06-28 14:32:25 +02:00
_ , err := sqlStore . CreateUser ( context . Background (), user . CreateUserCommand { Email : "testUser@grafana.com" , Login : testUserLogin })
2021-05-12 14:10:35 +02:00
require . NoError ( t , err )
2022-06-28 14:32:25 +02:00
_ , err = sqlStore . CreateUser ( context . Background (), user . CreateUserCommand { Email : "user1@grafana.com" , Login : "user1" })
2021-05-12 14:10:35 +02:00
require . NoError ( t , err )
2022-06-28 14:32:25 +02:00
_ , err = sqlStore . CreateUser ( context . Background (), user . CreateUserCommand { Email : "user2@grafana.com" , Login : "user2" })
2021-05-12 14:10:35 +02:00
require . NoError ( t , err )
}
2020-11-24 12:10:32 +01:00
func TestOrgUsersAPIEndpoint_userLoggedIn ( t * testing . T ) {
2022-01-26 09:44:20 -08:00
hs := setupSimpleHTTPServer ( featuremgmt . WithFeatures ())
settings := hs . Cfg
2020-11-24 12:10:32 +01:00
2022-10-19 09:02:15 -04:00
sqlStore := db . InitTestDB ( t )
2022-01-13 14:40:32 +01:00
sqlStore . Cfg = settings
2021-09-27 16:43:16 +02:00
hs . SQLStore = sqlStore
2022-09-26 10:27:38 +02:00
orgService := orgtest . NewOrgServiceFake ()
2022-09-26 18:53:17 +02:00
orgService . ExpectedSearchOrgUsersResult = & org . SearchOrgUsersQueryResult {}
2022-09-26 10:27:38 +02:00
hs . orgService = orgService
2022-02-03 09:20:20 +01:00
mock := mockstore . NewSQLStoreMock ()
2022-01-14 17:55:57 +01:00
loggedInUserScenario ( t , "When calling GET on" , "api/org/users" , "api/org/users" , func ( sc * scenarioContext ) {
2021-09-17 09:19:36 +02:00
setUpGetOrgUsersDB ( t , sqlStore )
2022-09-26 10:27:38 +02:00
orgService . ExpectedOrgUsers = [] * org . OrgUserDTO {
{ Login : testUserLogin , Email : "testUser@grafana.com" },
{ Login : "user1" , Email : "user1@grafana.com" },
{ Login : "user2" , Email : "user2@grafana.com" },
}
2020-11-24 12:10:32 +01:00
sc . handlerFunc = hs . GetOrgUsersForCurrentOrg
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string {}). exec ()
require . Equal ( t , http . StatusOK , sc . resp . Code )
var resp [] models . OrgUserDTO
err := json . Unmarshal ( sc . resp . Body . Bytes (), & resp )
require . NoError ( t , err )
assert . Len ( t , resp , 3 )
2022-02-03 09:20:20 +01:00
}, mock )
2020-11-24 12:10:32 +01:00
2022-01-14 17:55:57 +01:00
loggedInUserScenario ( t , "When calling GET on" , "api/org/users/search" , "api/org/users/search" , func ( sc * scenarioContext ) {
2021-05-12 14:10:35 +02:00
setUpGetOrgUsersDB ( t , sqlStore )
2022-09-26 18:53:17 +02:00
orgService . ExpectedSearchOrgUsersResult = & org . SearchOrgUsersQueryResult {
OrgUsers : [] * org . OrgUserDTO {
{
Login : "user1" ,
},
{
Login : "user2" ,
},
{
Login : "user3" ,
},
},
TotalCount : 3 ,
PerPage : 1000 ,
Page : 1 ,
}
2021-11-29 10:18:01 +01:00
sc . handlerFunc = hs . SearchOrgUsersWithPaging
2021-05-12 14:10:35 +02:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string {}). exec ()
require . Equal ( t , http . StatusOK , sc . resp . Code )
2022-09-26 18:53:17 +02:00
var resp org . SearchOrgUsersQueryResult
2021-05-12 14:10:35 +02:00
err := json . Unmarshal ( sc . resp . Body . Bytes (), & resp )
require . NoError ( t , err )
assert . Len ( t , resp . OrgUsers , 3 )
assert . Equal ( t , int64 ( 3 ), resp . TotalCount )
assert . Equal ( t , 1000 , resp . PerPage )
assert . Equal ( t , 1 , resp . Page )
2022-02-03 09:20:20 +01:00
}, mock )
2021-05-12 14:10:35 +02:00
2022-01-14 17:55:57 +01:00
loggedInUserScenario ( t , "When calling GET with page and limit query parameters on" , "api/org/users/search" , "api/org/users/search" , func ( sc * scenarioContext ) {
2021-05-12 14:10:35 +02:00
setUpGetOrgUsersDB ( t , sqlStore )
2022-09-26 18:53:17 +02:00
orgService . ExpectedSearchOrgUsersResult = & org . SearchOrgUsersQueryResult {
OrgUsers : [] * org . OrgUserDTO {
{
Login : "user1" ,
},
},
TotalCount : 3 ,
PerPage : 2 ,
Page : 2 ,
}
2021-11-29 10:18:01 +01:00
sc . handlerFunc = hs . SearchOrgUsersWithPaging
2021-05-12 14:10:35 +02:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { "perpage" : "2" , "page" : "2" }). exec ()
require . Equal ( t , http . StatusOK , sc . resp . Code )
2022-09-26 18:53:17 +02:00
var resp org . SearchOrgUsersQueryResult
2021-05-12 14:10:35 +02:00
err := json . Unmarshal ( sc . resp . Body . Bytes (), & resp )
require . NoError ( t , err )
assert . Len ( t , resp . OrgUsers , 1 )
assert . Equal ( t , int64 ( 3 ), resp . TotalCount )
assert . Equal ( t , 2 , resp . PerPage )
assert . Equal ( t , 2 , resp . Page )
2022-02-03 09:20:20 +01:00
}, mock )
2021-05-12 14:10:35 +02:00
2021-09-17 09:19:36 +02:00
t . Run ( "Given there are two hidden users" , func ( t * testing . T ) {
2020-11-24 12:10:32 +01:00
settings . HiddenUsers = map [ string ] struct {}{
"user1" : {},
testUserLogin : {},
}
t . Cleanup ( func () { settings . HiddenUsers = make ( map [ string ] struct {}) })
2022-01-14 17:55:57 +01:00
loggedInUserScenario ( t , "When calling GET on" , "api/org/users" , "api/org/users" , func ( sc * scenarioContext ) {
2021-09-17 09:19:36 +02:00
setUpGetOrgUsersDB ( t , sqlStore )
2020-11-24 12:10:32 +01:00
sc . handlerFunc = hs . GetOrgUsersForCurrentOrg
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string {}). exec ()
require . Equal ( t , http . StatusOK , sc . resp . Code )
var resp [] models . OrgUserDTO
err := json . Unmarshal ( sc . resp . Body . Bytes (), & resp )
require . NoError ( t , err )
assert . Len ( t , resp , 2 )
assert . Equal ( t , testUserLogin , resp [ 0 ]. Login )
assert . Equal ( t , "user2" , resp [ 1 ]. Login )
2022-02-03 09:20:20 +01:00
}, mock )
2020-11-24 12:10:32 +01:00
loggedInUserScenarioWithRole ( t , "When calling GET as an admin on" , "GET" , "api/org/users/lookup" ,
2022-08-10 11:56:48 +02:00
"api/org/users/lookup" , org . RoleAdmin , func ( sc * scenarioContext ) {
2021-09-17 09:19:36 +02:00
setUpGetOrgUsersDB ( t , sqlStore )
2020-11-24 12:10:32 +01:00
sc . handlerFunc = hs . GetOrgUsersForCurrentOrgLookup
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string {}). exec ()
require . Equal ( t , http . StatusOK , sc . resp . Code )
var resp [] dtos . UserLookupDTO
err := json . Unmarshal ( sc . resp . Body . Bytes (), & resp )
require . NoError ( t , err )
assert . Len ( t , resp , 2 )
assert . Equal ( t , testUserLogin , resp [ 0 ]. Login )
assert . Equal ( t , "user2" , resp [ 1 ]. Login )
2022-02-03 09:20:20 +01:00
}, mock )
2020-11-24 12:10:32 +01:00
})
}
2021-09-17 09:19:36 +02:00
func TestOrgUsersAPIEndpoint_LegacyAccessControl_FolderAdmin ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = false
sc := setupHTTPServerWithCfg ( t , true , cfg )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInViewer ( sc . initCtx )
2021-09-17 09:19:36 +02:00
// Create a dashboard folder
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
FolderId : 1 ,
IsFolder : true ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface {}{
"id" : nil ,
"title" : "1 test dash folder" ,
"tags" : "prod" ,
}),
}
2022-09-21 14:04:01 +02:00
folder , err := sc . dashboardsStore . SaveDashboard ( context . Background (), cmd )
2021-09-17 09:19:36 +02:00
require . NoError ( t , err )
require . NotNil ( t , folder )
// Grant our test Viewer with permission to admin the folder
2022-07-18 15:14:58 +02:00
acls := [] * models . DashboardACL {
2021-09-17 09:19:36 +02:00
{
DashboardID : folder . Id ,
OrgID : testOrgID ,
UserID : testUserID ,
Permission : models . PERMISSION_ADMIN ,
Created : time . Now (),
Updated : time . Now (),
},
}
2022-02-16 14:15:44 +01:00
err = sc . dashboardsStore . UpdateDashboardACL ( context . Background (), folder . Id , acls )
2021-09-17 09:19:36 +02:00
require . NoError ( t , err )
2021-11-17 10:12:28 +01:00
response := callAPI ( sc . server , http . MethodGet , "/api/org/users/lookup" , nil , t )
assert . Equal ( t , http . StatusOK , response . Code )
2021-09-17 09:19:36 +02:00
}
func TestOrgUsersAPIEndpoint_LegacyAccessControl_TeamAdmin ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = false
sc := setupHTTPServerWithCfg ( t , true , cfg )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInViewer ( sc . initCtx )
2021-09-17 09:19:36 +02:00
// Setup store teams
2022-09-20 18:58:04 +02:00
team1 , err := sc . teamService . CreateTeam ( "testteam1" , "testteam1@example.org" , testOrgID )
2021-09-17 09:19:36 +02:00
require . NoError ( t , err )
2022-09-20 18:58:04 +02:00
err = sc . teamService . AddTeamMember ( testUserID , testOrgID , team1 . Id , false , models . PERMISSION_ADMIN )
2021-09-17 09:19:36 +02:00
require . NoError ( t , err )
2021-11-17 10:12:28 +01:00
response := callAPI ( sc . server , http . MethodGet , "/api/org/users/lookup" , nil , t )
assert . Equal ( t , http . StatusOK , response . Code )
2021-09-17 09:19:36 +02:00
}
func TestOrgUsersAPIEndpoint_LegacyAccessControl_Admin ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = false
sc := setupHTTPServerWithCfg ( t , true , cfg )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInOrgAdmin ( sc . initCtx )
2021-09-17 09:19:36 +02:00
2021-11-17 10:12:28 +01:00
response := callAPI ( sc . server , http . MethodGet , "/api/org/users/lookup" , nil , t )
assert . Equal ( t , http . StatusOK , response . Code )
2021-09-17 09:19:36 +02:00
}
func TestOrgUsersAPIEndpoint_LegacyAccessControl_Viewer ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = false
sc := setupHTTPServerWithCfg ( t , true , cfg )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInViewer ( sc . initCtx )
2021-09-17 09:19:36 +02:00
2021-11-17 10:12:28 +01:00
response := callAPI ( sc . server , http . MethodGet , "/api/org/users/lookup" , nil , t )
assert . Equal ( t , http . StatusForbidden , response . Code )
2021-09-17 09:19:36 +02:00
}
func TestOrgUsersAPIEndpoint_AccessControl ( t * testing . T ) {
tests := [] accessControlTestCase {
{
expectedCode : http . StatusOK ,
desc : "UsersLookupGet should return 200 for user with correct permissions" ,
url : "/api/org/users/lookup" ,
method : http . MethodGet ,
2022-06-14 10:17:48 +02:00
permissions : [] accesscontrol . Permission {{ Action : accesscontrol . ActionOrgUsersRead , Scope : accesscontrol . ScopeUsersAll }},
2021-09-17 09:19:36 +02:00
},
{
expectedCode : http . StatusForbidden ,
desc : "UsersLookupGet should return 403 for user without required permissions" ,
url : "/api/org/users/lookup" ,
method : http . MethodGet ,
2022-06-14 10:17:48 +02:00
permissions : [] accesscontrol . Permission {{ Action : "wrong" }},
2021-09-17 09:19:36 +02:00
},
}
for _ , test := range tests {
t . Run ( test . desc , func ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
sc := setupHTTPServer ( t , true )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInViewer ( sc . initCtx )
2022-08-11 13:28:55 +02:00
setAccessControlPermissions ( sc . acmock , test . permissions , sc . initCtx . OrgID )
2021-11-17 10:12:28 +01:00
response := callAPI ( sc . server , http . MethodGet , test . url , nil , t )
assert . Equal ( t , test . expectedCode , response . Code )
})
}
}
var (
2022-08-10 11:56:48 +02:00
testServerAdminViewer = user . SignedInUser {
2022-08-11 13:28:55 +02:00
UserID : 1 ,
OrgID : 1 ,
2021-11-17 10:12:28 +01:00
OrgName : "TestOrg1" ,
2022-08-10 11:56:48 +02:00
OrgRole : org . RoleViewer ,
2021-11-17 10:12:28 +01:00
Login : "testServerAdmin" ,
Name : "testServerAdmin" ,
Email : "testServerAdmin@example.org" ,
OrgCount : 2 ,
IsGrafanaAdmin : true ,
IsAnonymous : false ,
}
2022-08-10 11:56:48 +02:00
testAdminOrg2 = user . SignedInUser {
2022-08-11 13:28:55 +02:00
UserID : 2 ,
OrgID : 2 ,
2021-11-17 10:12:28 +01:00
OrgName : "TestOrg2" ,
2022-08-10 11:56:48 +02:00
OrgRole : org . RoleAdmin ,
2021-11-17 10:12:28 +01:00
Login : "testAdmin" ,
Name : "testAdmin" ,
Email : "testAdmin@example.org" ,
OrgCount : 1 ,
IsGrafanaAdmin : false ,
IsAnonymous : false ,
}
2022-08-10 11:56:48 +02:00
testEditorOrg1 = user . SignedInUser {
2022-08-11 13:28:55 +02:00
UserID : 3 ,
OrgID : 1 ,
2021-11-17 10:12:28 +01:00
OrgName : "TestOrg1" ,
2022-08-10 11:56:48 +02:00
OrgRole : org . RoleEditor ,
2021-11-17 10:12:28 +01:00
Login : "testEditor" ,
Name : "testEditor" ,
Email : "testEditor@example.org" ,
OrgCount : 1 ,
IsGrafanaAdmin : false ,
IsAnonymous : false ,
}
)
// setupOrgUsersDBForAccessControlTests creates three users placed in two orgs
// Org1: testServerAdminViewer, testEditorOrg1
// Org2: testServerAdminViewer, testAdminOrg2
2022-11-22 18:02:39 +01:00
func setupOrgUsersDBForAccessControlTests ( t * testing . T , db * sqlstore . SQLStore , orgService org . Service ) {
2021-11-17 10:12:28 +01:00
t . Helper ()
var err error
2022-06-28 14:32:25 +02:00
_ , err = db . CreateUser ( context . Background (), user . CreateUserCommand { Email : testServerAdminViewer . Email , SkipOrgSetup : true , Login : testServerAdminViewer . Login })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
2022-06-28 14:32:25 +02:00
_ , err = db . CreateUser ( context . Background (), user . CreateUserCommand { Email : testAdminOrg2 . Email , SkipOrgSetup : true , Login : testAdminOrg2 . Login })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
2022-06-28 14:32:25 +02:00
_ , err = db . CreateUser ( context . Background (), user . CreateUserCommand { Email : testEditorOrg1 . Email , SkipOrgSetup : true , Login : testEditorOrg1 . Login })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
// Create both orgs with server admin
2022-11-23 10:37:04 +01:00
err = db . CreateOrg ( context . Background (), & models . CreateOrgCommand { Name : testServerAdminViewer . OrgName , UserId : testServerAdminViewer . UserID })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
2022-11-23 10:37:04 +01:00
err = db . CreateOrg ( context . Background (), & models . CreateOrgCommand { Name : testAdminOrg2 . OrgName , UserId : testServerAdminViewer . UserID })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
2022-11-22 18:02:39 +01:00
err = orgService . AddOrgUser ( context . Background (), & org . AddOrgUserCommand { LoginOrEmail : testAdminOrg2 . Login , Role : testAdminOrg2 . OrgRole , OrgID : testAdminOrg2 . OrgID , UserID : testAdminOrg2 . UserID })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
2022-11-22 18:02:39 +01:00
err = orgService . AddOrgUser ( context . Background (), & org . AddOrgUserCommand { LoginOrEmail : testEditorOrg1 . Login , Role : testEditorOrg1 . OrgRole , OrgID : testEditorOrg1 . OrgID , UserID : testEditorOrg1 . UserID })
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
}
2021-12-22 17:46:33 +00:00
func TestGetOrgUsersAPIEndpoint_AccessControlMetadata ( t * testing . T ) {
url := "/api/orgs/%v/users?accesscontrol=true"
type testCase struct {
name string
enableAccessControl bool
expectedCode int
expectedMetadata map [ string ] bool
2022-08-10 11:56:48 +02:00
user user . SignedInUser
2021-12-22 17:46:33 +00:00
targetOrg int64
}
tests := [] testCase {
{
name : "access control metadata not requested" ,
enableAccessControl : false ,
expectedCode : http . StatusOK ,
expectedMetadata : nil ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetOrg : testServerAdminViewer . OrgID ,
2021-12-22 17:46:33 +00:00
},
{
name : "access control metadata requested" ,
enableAccessControl : true ,
expectedCode : http . StatusOK ,
expectedMetadata : map [ string ] bool {
2022-06-02 13:14:48 +01:00
"org.users:write" : true ,
"org.users:add" : true ,
"org.users:read" : true ,
"org.users:remove" : true },
2021-12-22 17:46:33 +00:00
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetOrg : testServerAdminViewer . OrgID ,
2021-12-22 17:46:33 +00:00
},
}
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = tc . enableAccessControl
2022-11-14 21:08:10 +02:00
var err error
2022-08-16 16:08:59 +02:00
sc := setupHTTPServerWithCfg ( t , false , cfg , func ( hs * HTTPServer ) {
2022-11-14 21:08:10 +02:00
hs . userService , err = userimpl . ProvideService (
hs . SQLStore , nil , cfg , teamimpl . ProvideService ( hs . SQLStore .( * sqlstore . SQLStore ), cfg ), localcache . ProvideService (), quotatest . New ( false , nil ))
require . NoError ( t , err )
hs . orgService , err = orgimpl . ProvideService ( hs . SQLStore , cfg , quotatest . New ( false , nil ))
require . NoError ( t , err )
2022-08-16 16:08:59 +02:00
})
2022-11-22 18:02:39 +01:00
setupOrgUsersDBForAccessControlTests ( t , sc . db , sc . hs . orgService )
2021-12-22 17:46:33 +00:00
setInitCtxSignedInUser ( sc . initCtx , tc . user )
// Perform test
response := callAPI ( sc . server , http . MethodGet , fmt . Sprintf ( url , tc . targetOrg ), nil , t )
require . Equal ( t , tc . expectedCode , response . Code )
var userList [] * models . OrgUserDTO
2022-11-14 21:08:10 +02:00
err = json . NewDecoder ( response . Body ). Decode ( & userList )
2021-12-22 17:46:33 +00:00
require . NoError ( t , err )
if tc . expectedMetadata != nil {
assert . Equal ( t , tc . expectedMetadata , userList [ 0 ]. AccessControl )
} else {
assert . Nil ( t , userList [ 0 ]. AccessControl )
}
})
}
}
2021-11-17 10:12:28 +01:00
func TestGetOrgUsersAPIEndpoint_AccessControl ( t * testing . T ) {
url := "/api/orgs/%v/users/"
type testCase struct {
name string
enableAccessControl bool
expectedCode int
expectedUserCount int
2022-08-10 11:56:48 +02:00
user user . SignedInUser
2021-11-17 10:12:28 +01:00
targetOrg int64
}
tests := [] testCase {
{
name : "server admin can get users in his org (legacy)" ,
enableAccessControl : false ,
expectedCode : http . StatusOK ,
expectedUserCount : 2 ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
},
{
name : "server admin can get users in another org (legacy)" ,
enableAccessControl : false ,
expectedCode : http . StatusOK ,
expectedUserCount : 2 ,
user : testServerAdminViewer ,
targetOrg : 2 ,
},
{
name : "org admin cannot get users in his org (legacy)" ,
enableAccessControl : false ,
expectedCode : http . StatusForbidden ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
},
{
name : "org admin cannot get users in another org (legacy)" ,
enableAccessControl : false ,
expectedCode : http . StatusForbidden ,
user : testAdminOrg2 ,
targetOrg : 1 ,
},
{
name : "server admin can get users in his org" ,
enableAccessControl : true ,
expectedCode : http . StatusOK ,
expectedUserCount : 2 ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
},
{
name : "server admin can get users in another org" ,
enableAccessControl : true ,
expectedCode : http . StatusOK ,
expectedUserCount : 2 ,
user : testServerAdminViewer ,
targetOrg : 2 ,
},
{
2022-10-04 12:17:55 +02:00
name : "org admin can get users in their org" ,
2021-11-17 10:12:28 +01:00
enableAccessControl : true ,
expectedCode : http . StatusOK ,
expectedUserCount : 2 ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
},
{
name : "org admin cannot get users in another org" ,
enableAccessControl : true ,
expectedCode : http . StatusForbidden ,
user : testAdminOrg2 ,
targetOrg : 1 ,
},
}
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = tc . enableAccessControl
2022-11-14 21:08:10 +02:00
var err error
2022-08-16 16:08:59 +02:00
sc := setupHTTPServerWithCfg ( t , false , cfg , func ( hs * HTTPServer ) {
2022-11-14 21:08:10 +02:00
quotaService := quotatest . New ( false , nil )
hs . userService , err = userimpl . ProvideService (
hs . SQLStore , nil , cfg , teamimpl . ProvideService ( hs . SQLStore .( * sqlstore . SQLStore ), cfg ), localcache . ProvideService (), quotaService )
require . NoError ( t , err )
hs . orgService , err = orgimpl . ProvideService ( hs . SQLStore , cfg , quotaService )
require . NoError ( t , err )
2022-08-16 16:08:59 +02:00
})
2021-11-17 10:12:28 +01:00
setInitCtxSignedInUser ( sc . initCtx , tc . user )
2022-11-22 18:02:39 +01:00
setupOrgUsersDBForAccessControlTests ( t , sc . db , sc . hs . orgService )
2021-11-17 10:12:28 +01:00
// Perform test
response := callAPI ( sc . server , http . MethodGet , fmt . Sprintf ( url , tc . targetOrg ), nil , t )
require . Equal ( t , tc . expectedCode , response . Code )
if tc . expectedCode != http . StatusForbidden {
var userList [] * models . OrgUserDTO
err := json . NewDecoder ( response . Body ). Decode ( & userList )
require . NoError ( t , err )
assert . Len ( t , userList , tc . expectedUserCount )
}
})
}
}
func TestPostOrgUsersAPIEndpoint_AccessControl ( t * testing . T ) {
url := "/api/orgs/%v/users/"
type testCase struct {
name string
enableAccessControl bool
2022-08-10 11:56:48 +02:00
user user . SignedInUser
2021-11-17 10:12:28 +01:00
targetOrg int64
input string
expectedCode int
}
tests := [] testCase {
{
name : "server admin can add users to his org (legacy)" ,
enableAccessControl : false ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( testAdminOrg2 . OrgRole ) + `"}` ,
expectedCode : http . StatusOK ,
},
{
name : "server admin can add users to another org (legacy)" ,
enableAccessControl : false ,
user : testServerAdminViewer ,
targetOrg : 2 ,
input : `{"loginOrEmail": "` + testEditorOrg1 . Login + `", "role": "` + string ( testEditorOrg1 . OrgRole ) + `"}` ,
expectedCode : http . StatusOK ,
},
{
name : "org admin cannot add users to his org (legacy)" ,
enableAccessControl : false ,
expectedCode : http . StatusForbidden ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"loginOrEmail": "` + testEditorOrg1 . Login + `", "role": "` + string ( testEditorOrg1 . OrgRole ) + `"}` ,
},
{
name : "org admin cannot add users to another org (legacy)" ,
enableAccessControl : false ,
expectedCode : http . StatusForbidden ,
user : testAdminOrg2 ,
targetOrg : 1 ,
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( testAdminOrg2 . OrgRole ) + `"}` ,
},
{
name : "server admin can add users to his org" ,
enableAccessControl : true ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( testAdminOrg2 . OrgRole ) + `"}` ,
expectedCode : http . StatusOK ,
},
{
name : "server admin can add users to another org" ,
enableAccessControl : true ,
user : testServerAdminViewer ,
targetOrg : 2 ,
input : `{"loginOrEmail": "` + testEditorOrg1 . Login + `", "role": "` + string ( testEditorOrg1 . OrgRole ) + `"}` ,
expectedCode : http . StatusOK ,
},
{
name : "org admin can add users to his org" ,
enableAccessControl : true ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"loginOrEmail": "` + testEditorOrg1 . Login + `", "role": "` + string ( testEditorOrg1 . OrgRole ) + `"}` ,
expectedCode : http . StatusOK ,
},
{
name : "org admin cannot add users to another org" ,
enableAccessControl : true ,
expectedCode : http . StatusForbidden ,
user : testAdminOrg2 ,
targetOrg : 1 ,
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( testAdminOrg2 . OrgRole ) + `"}` ,
},
}
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = tc . enableAccessControl
2022-11-14 21:08:10 +02:00
var err error
2022-08-16 16:08:59 +02:00
sc := setupHTTPServerWithCfg ( t , false , cfg , func ( hs * HTTPServer ) {
2022-11-22 18:02:39 +01:00
hs . orgService , err = orgimpl . ProvideService ( hs . SQLStore , cfg , quotatest . New ( false , nil ))
require . NoError ( t , err )
2022-11-14 21:08:10 +02:00
hs . userService , err = userimpl . ProvideService (
2022-11-22 18:02:39 +01:00
hs . SQLStore , hs . orgService , cfg , teamimpl . ProvideService ( hs . SQLStore .( * sqlstore . SQLStore ), cfg ), localcache . ProvideService (), quotatest . New ( false , nil ))
2022-11-14 21:08:10 +02:00
require . NoError ( t , err )
2022-08-16 16:08:59 +02:00
})
2022-09-27 07:58:49 -04:00
2022-11-22 18:02:39 +01:00
setupOrgUsersDBForAccessControlTests ( t , sc . db , sc . hs . orgService )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInUser ( sc . initCtx , tc . user )
// Perform request
input := strings . NewReader ( tc . input )
response := callAPI ( sc . server , http . MethodPost , fmt . Sprintf ( url , tc . targetOrg ), input , t )
assert . Equal ( t , tc . expectedCode , response . Code )
if tc . expectedCode != http . StatusForbidden {
// Check result
var message util . DynMap
err := json . NewDecoder ( response . Body ). Decode ( & message )
require . NoError ( t , err )
2021-09-17 09:19:36 +02:00
}
2021-11-17 10:12:28 +01:00
})
}
}
2021-09-17 09:19:36 +02:00
2022-06-27 19:40:12 +03:00
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 }},
2022-08-10 11:56:48 +02:00
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( org . RoleViewer ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
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 }},
2022-08-10 11:56:48 +02:00
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( org . RoleEditor ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
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 }},
2022-08-10 11:56:48 +02:00
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( org . RoleViewer ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
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 }},
2022-08-10 11:56:48 +02:00
input : `{"loginOrEmail": "` + testAdminOrg2 . Login + `", "role": "` + string ( org . RoleEditor ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
expectedCode : http . StatusOK ,
desc : "org viewer with the correct permissions can update a user's role to a viewer in his org" ,
2022-08-11 13:28:55 +02:00
url : fmt . Sprintf ( "/api/org/users/%d" , testEditorOrg1 . UserID ),
2022-06-27 19:40:12 +03:00
method : http . MethodPatch ,
permissions : [] accesscontrol . Permission {{ Action : accesscontrol . ActionOrgUsersWrite , Scope : accesscontrol . ScopeUsersAll }},
2022-08-10 11:56:48 +02:00
input : `{"role": "` + string ( org . RoleViewer ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
expectedCode : http . StatusForbidden ,
desc : "org viewer with the correct permissions cannot update a user's role to a viewer in his org" ,
2022-08-11 13:28:55 +02:00
url : fmt . Sprintf ( "/api/org/users/%d" , testEditorOrg1 . UserID ),
2022-06-27 19:40:12 +03:00
method : http . MethodPatch ,
permissions : [] accesscontrol . Permission {{ Action : accesscontrol . ActionOrgUsersWrite , Scope : accesscontrol . ScopeUsersAll }},
2022-08-10 11:56:48 +02:00
input : `{"role": "` + string ( org . RoleEditor ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
expectedCode : http . StatusOK ,
desc : "org viewer with the correct permissions can update a user's role to a viewer in his org" ,
2022-08-11 13:28:55 +02:00
url : fmt . Sprintf ( "/api/orgs/1/users/%d" , testEditorOrg1 . UserID ),
2022-06-27 19:40:12 +03:00
method : http . MethodPatch ,
permissions : [] accesscontrol . Permission {{ Action : accesscontrol . ActionOrgUsersWrite , Scope : accesscontrol . ScopeUsersAll }},
2022-08-10 11:56:48 +02:00
input : `{"role": "` + string ( org . RoleViewer ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
expectedCode : http . StatusForbidden ,
desc : "org viewer with the correct permissions cannot update a user's role to a viewer in his org" ,
2022-08-11 13:28:55 +02:00
url : fmt . Sprintf ( "/api/orgs/1/users/%d" , testEditorOrg1 . UserID ),
2022-06-27 19:40:12 +03:00
method : http . MethodPatch ,
permissions : [] accesscontrol . Permission {{ Action : accesscontrol . ActionOrgUsersWrite , Scope : accesscontrol . ScopeUsersAll }},
2022-08-10 11:56:48 +02:00
input : `{"role": "` + string ( org . RoleEditor ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
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 ,
2022-07-27 17:37:27 +01:00
permissions : [] accesscontrol . Permission {{ Action : accesscontrol . ActionOrgUsersAdd , Scope : accesscontrol . ScopeUsersAll }},
2022-08-10 11:56:48 +02:00
input : `{"loginOrEmail": "newUserEmail@test.com", "sendEmail": false, "role": "` + string ( org . RoleViewer ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
{
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 }},
2022-08-10 11:56:48 +02:00
input : `{"loginOrEmail": "newUserEmail@test.com", "sendEmail": false, "role": "` + string ( org . RoleEditor ) + `"}` ,
2022-06-27 19:40:12 +03:00
},
}
for _ , test := range tests {
t . Run ( test . desc , func ( t * testing . T ) {
2022-11-14 21:08:10 +02:00
var err error
2022-08-16 16:08:59 +02:00
sc := setupHTTPServer ( t , true , func ( hs * HTTPServer ) {
2022-09-20 11:29:17 +02:00
hs . tempUserService = tempuserimpl . ProvideService ( hs . SQLStore )
2022-11-14 21:08:10 +02:00
hs . userService , err = userimpl . ProvideService (
hs . SQLStore , nil , setting . NewCfg (), teamimpl . ProvideService ( hs . SQLStore .( * sqlstore . SQLStore ), setting . NewCfg ()), localcache . ProvideService (), quotatest . New ( false , nil ))
require . NoError ( t , err )
2022-08-16 16:08:59 +02:00
})
2022-06-27 19:40:12 +03:00
setInitCtxSignedInViewer ( sc . initCtx )
2022-11-22 18:02:39 +01:00
setupOrgUsersDBForAccessControlTests ( t , sc . db , sc . hs . orgService )
2022-08-11 13:28:55 +02:00
setAccessControlPermissions ( sc . acmock , test . permissions , sc . initCtx . OrgID )
2022-06-27 19:40:12 +03:00
input := strings . NewReader ( test . input )
response := callAPI ( sc . server , test . method , test . url , input , t )
assert . Equal ( t , test . expectedCode , response . Code )
})
}
}
2021-11-17 10:12:28 +01:00
func TestPatchOrgUsersAPIEndpoint_AccessControl ( t * testing . T ) {
url := "/api/orgs/%v/users/%v"
type testCase struct {
name string
enableAccessControl bool
2022-08-10 11:56:48 +02:00
user user . SignedInUser
2021-11-17 10:12:28 +01:00
targetUserId int64
targetOrg int64
input string
expectedCode int
expectedMessage util . DynMap
2022-08-10 11:56:48 +02:00
expectedUserRole org . RoleType
2021-11-17 10:12:28 +01:00
}
2021-09-17 09:19:36 +02:00
2021-11-17 10:12:28 +01:00
tests := [] testCase {
{
name : "server admin can update users in his org (legacy)" ,
enableAccessControl : false ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testEditorOrg1 . UserID ,
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"role": "Viewer"}` ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "Organization user updated" },
2022-08-10 11:56:48 +02:00
expectedUserRole : org . RoleViewer ,
2021-11-17 10:12:28 +01:00
},
{
name : "server admin can update users in another org (legacy)" ,
enableAccessControl : false ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 2 ,
input : `{"role": "Editor"}` ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "Organization user updated" },
2022-08-10 11:56:48 +02:00
expectedUserRole : org . RoleEditor ,
2021-11-17 10:12:28 +01:00
},
{
name : "org admin cannot update users in his org (legacy)" ,
enableAccessControl : false ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"role": "Editor"}` ,
expectedCode : http . StatusForbidden ,
},
{
name : "org admin cannot update users in another org (legacy)" ,
enableAccessControl : false ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 1 ,
input : `{"role": "Editor"}` ,
expectedCode : http . StatusForbidden ,
},
{
name : "server admin can update users in his org" ,
enableAccessControl : true ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testEditorOrg1 . UserID ,
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"role": "Viewer"}` ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "Organization user updated" },
2022-08-10 11:56:48 +02:00
expectedUserRole : org . RoleViewer ,
2021-11-17 10:12:28 +01:00
},
{
name : "server admin can update users in another org" ,
enableAccessControl : true ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 2 ,
input : `{"role": "Editor"}` ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "Organization user updated" },
2022-08-10 11:56:48 +02:00
expectedUserRole : org . RoleEditor ,
2021-11-17 10:12:28 +01:00
},
{
name : "org admin can update users in his org" ,
enableAccessControl : true ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
input : `{"role": "Editor"}` ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "Organization user updated" },
2022-08-10 11:56:48 +02:00
expectedUserRole : org . RoleEditor ,
2021-11-17 10:12:28 +01:00
},
{
name : "org admin cannot update users in another org" ,
enableAccessControl : true ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 1 ,
input : `{"role": "Editor"}` ,
expectedCode : http . StatusForbidden ,
},
}
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = tc . enableAccessControl
2022-11-14 21:08:10 +02:00
var err error
2022-08-16 16:08:59 +02:00
sc := setupHTTPServerWithCfg ( t , false , cfg , func ( hs * HTTPServer ) {
2022-11-14 21:08:10 +02:00
quotaService := quotatest . New ( false , nil )
hs . userService , err = userimpl . ProvideService (
hs . SQLStore , nil , cfg , teamimpl . ProvideService ( hs . SQLStore .( * sqlstore . SQLStore ), cfg ), localcache . ProvideService (), quotaService )
require . NoError ( t , err )
hs . orgService , err = orgimpl . ProvideService ( hs . SQLStore , cfg , quotaService )
require . NoError ( t , err )
2022-08-16 16:08:59 +02:00
})
2022-11-22 18:02:39 +01:00
setupOrgUsersDBForAccessControlTests ( t , sc . db , sc . hs . orgService )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInUser ( sc . initCtx , tc . user )
// Perform request
input := strings . NewReader ( tc . input )
setInitCtxSignedInUser ( sc . initCtx , tc . user )
response := callAPI ( sc . server , http . MethodPatch , fmt . Sprintf ( url , tc . targetOrg , tc . targetUserId ), input , t )
assert . Equal ( t , tc . expectedCode , response . Code )
if tc . expectedCode != http . StatusForbidden {
// Check result
var message util . DynMap
err := json . NewDecoder ( response . Body ). Decode ( & message )
require . NoError ( t , err )
assert . Equal ( t , tc . expectedMessage , message )
2021-09-17 09:19:36 +02:00
2022-09-27 07:58:49 -04:00
getUserQuery := user . GetSignedInUserQuery {
UserID : tc . targetUserId ,
OrgID : tc . targetOrg ,
2021-11-17 10:12:28 +01:00
}
2022-09-27 07:58:49 -04:00
usr , err := sc . userService . GetSignedInUser ( context . Background (), & getUserQuery )
2021-11-17 10:12:28 +01:00
require . NoError ( t , err )
2022-09-27 07:58:49 -04:00
assert . Equal ( t , tc . expectedUserRole , usr . OrgRole )
2021-11-17 10:12:28 +01:00
}
})
}
}
func TestDeleteOrgUsersAPIEndpoint_AccessControl ( t * testing . T ) {
url := "/api/orgs/%v/users/%v"
type testCase struct {
name string
enableAccessControl bool
2022-08-10 11:56:48 +02:00
user user . SignedInUser
2021-11-17 10:12:28 +01:00
targetUserId int64
targetOrg int64
expectedCode int
expectedMessage util . DynMap
expectedUserCount int
}
tests := [] testCase {
{
name : "server admin can delete users from his org (legacy)" ,
enableAccessControl : false ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testEditorOrg1 . UserID ,
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "User removed from organization" },
expectedUserCount : 1 ,
},
{
name : "server admin can delete users from another org (legacy)" ,
enableAccessControl : false ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 2 ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "User removed from organization" },
expectedUserCount : 1 ,
},
{
name : "org admin can delete users from his org (legacy)" ,
enableAccessControl : false ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
expectedCode : http . StatusForbidden ,
},
{
name : "org admin cannot delete users from another org (legacy)" ,
enableAccessControl : false ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testEditorOrg1 . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 1 ,
expectedCode : http . StatusForbidden ,
},
{
name : "server admin can delete users from his org" ,
enableAccessControl : true ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testEditorOrg1 . UserID ,
targetOrg : testServerAdminViewer . OrgID ,
2021-11-17 10:12:28 +01:00
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "User removed from organization" },
expectedUserCount : 1 ,
},
{
name : "server admin can delete users from another org" ,
enableAccessControl : true ,
user : testServerAdminViewer ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 2 ,
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "User removed from organization" },
expectedUserCount : 1 ,
},
{
name : "org admin can delete users from his org" ,
enableAccessControl : true ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testServerAdminViewer . UserID ,
targetOrg : testAdminOrg2 . OrgID ,
2021-11-17 10:12:28 +01:00
expectedCode : http . StatusOK ,
expectedMessage : util . DynMap { "message" : "User removed from organization" },
expectedUserCount : 1 ,
},
{
name : "org admin cannot delete users from another org" ,
enableAccessControl : true ,
user : testAdminOrg2 ,
2022-08-11 13:28:55 +02:00
targetUserId : testEditorOrg1 . UserID ,
2021-11-17 10:12:28 +01:00
targetOrg : 1 ,
expectedCode : http . StatusForbidden ,
},
}
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
2022-08-11 15:37:31 +02:00
cfg := setting . NewCfg ()
cfg . RBACEnabled = tc . enableAccessControl
2022-11-14 21:08:10 +02:00
var err error
2022-08-16 16:08:59 +02:00
sc := setupHTTPServerWithCfg ( t , false , cfg , func ( hs * HTTPServer ) {
2022-11-14 21:08:10 +02:00
quotaService := quotatest . New ( false , nil )
hs . userService , err = userimpl . ProvideService (
hs . SQLStore , nil , cfg , teamimpl . ProvideService ( hs . SQLStore .( * sqlstore . SQLStore ), cfg ), localcache . ProvideService (), quotaService )
require . NoError ( t , err )
hs . orgService , err = orgimpl . ProvideService ( hs . SQLStore , cfg , quotaService )
require . NoError ( t , err )
2022-08-16 16:08:59 +02:00
})
2022-11-22 18:02:39 +01:00
setupOrgUsersDBForAccessControlTests ( t , sc . db , sc . hs . orgService )
2021-11-17 10:12:28 +01:00
setInitCtxSignedInUser ( sc . initCtx , tc . user )
response := callAPI ( sc . server , http . MethodDelete , fmt . Sprintf ( url , tc . targetOrg , tc . targetUserId ), nil , t )
assert . Equal ( t , tc . expectedCode , response . Code )
if tc . expectedCode != http . StatusForbidden {
// Check result
var message util . DynMap
err := json . NewDecoder ( response . Body ). Decode ( & message )
require . NoError ( t , err )
assert . Equal ( t , tc . expectedMessage , message )
}
2021-09-17 09:19:36 +02:00
})
}
}