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