@@ -3563,28 +3563,55 @@ def test_forum_admin_can_list_team_members(self):
35633563 response = self .client .get (url )
35643564 assert response .status_code == status .HTTP_200_OK
35653565
3566- def test_forum_admin_can_grant_role (self ):
3567- """Discussion Admin should be able to POST /team to grant a role."""
3566+ def test_forum_admin_can_grant_forum_role (self ):
3567+ """Discussion Admin should be able to grant a forum role."""
35683568 url = reverse ('instructor_api_v2:course_team' , kwargs = {'course_id' : str (self .course_key )})
35693569 target = UserFactory .create ()
35703570 self .client .force_authenticate (user = self .forum_admin )
35713571 response = self .client .post (url , {
35723572 'identifiers' : [target .username ],
3573- 'role' : 'staff ' ,
3573+ 'role' : 'Moderator ' ,
35743574 'action' : 'allow' ,
35753575 }, format = 'json' )
35763576 assert response .status_code == status .HTTP_200_OK
35773577
3578- def test_forum_admin_can_revoke_role (self ):
3579- """Discussion Admin should be able to DELETE /team/{username}."""
3578+ def test_forum_admin_can_revoke_forum_role (self ):
3579+ """Discussion Admin should be able to revoke a forum role."""
3580+ target = UserFactory .create ()
3581+ role = Role .objects .get (course_id = self .course_key , name = 'Moderator' )
3582+ role .users .add (target )
3583+ url = reverse (
3584+ 'instructor_api_v2:course_team_member' ,
3585+ kwargs = {'course_id' : str (self .course_key ), 'email_or_username' : target .username },
3586+ )
3587+ self .client .force_authenticate (user = self .forum_admin )
3588+ response = self .client .delete (url , {'roles' : ['Moderator' ]}, format = 'json' )
3589+ assert response .status_code == status .HTTP_200_OK
3590+
3591+ def test_forum_admin_cannot_grant_course_role (self ):
3592+ """Discussion Admin should not be able to grant a non-forum course role like staff."""
3593+ url = reverse ('instructor_api_v2:course_team' , kwargs = {'course_id' : str (self .course_key )})
3594+ target = UserFactory .create ()
3595+ self .client .force_authenticate (user = self .forum_admin )
3596+ response = self .client .post (url , {
3597+ 'identifiers' : [target .username ],
3598+ 'role' : 'staff' ,
3599+ 'action' : 'allow' ,
3600+ }, format = 'json' )
3601+ assert response .status_code == status .HTTP_403_FORBIDDEN
3602+ assert 'You do not have permissions to change this role' in response .data ['error' ]
3603+
3604+ def test_forum_admin_cannot_revoke_course_role (self ):
3605+ """Discussion Admin should not be able to revoke a non-forum course role like staff."""
35803606 target = StaffFactory .create (course_key = self .course_key )
35813607 url = reverse (
35823608 'instructor_api_v2:course_team_member' ,
35833609 kwargs = {'course_id' : str (self .course_key ), 'email_or_username' : target .username },
35843610 )
35853611 self .client .force_authenticate (user = self .forum_admin )
35863612 response = self .client .delete (url , {'roles' : ['staff' ]}, format = 'json' )
3587- assert response .status_code == status .HTTP_200_OK
3613+ assert response .status_code == status .HTTP_403_FORBIDDEN
3614+ assert 'You do not have permissions to change the requested roles' in response .data ['error' ]
35883615
35893616 def test_plain_staff_cannot_access_team_endpoints (self ):
35903617 """Staff without instructor or forum admin role should get 403."""
@@ -3615,10 +3642,10 @@ def test_forum_admin_cannot_grant_instructor_role(self):
36153642 'action' : 'allow' ,
36163643 }, format = 'json' )
36173644 assert response .status_code == status .HTTP_403_FORBIDDEN
3645+ assert 'You do not have permissions to change this role' in response .data ['error' ]
36183646
36193647 def test_forum_admin_cannot_revoke_instructor_role (self ):
36203648 """Discussion Admin should not be able to revoke the instructor role."""
3621- # Create an instructor to target
36223649 instructor = InstructorFactory .create (course_key = self .course_key )
36233650 url = reverse (
36243651 'instructor_api_v2:course_team_member' ,
@@ -3627,3 +3654,38 @@ def test_forum_admin_cannot_revoke_instructor_role(self):
36273654 self .client .force_authenticate (user = self .forum_admin )
36283655 response = self .client .delete (url , {'roles' : ['instructor' ]}, format = 'json' )
36293656 assert response .status_code == status .HTTP_403_FORBIDDEN
3657+ assert 'You do not have permissions to change the requested roles' in response .data ['error' ]
3658+
3659+ def test_roles_editable_param_filters_for_forum_admin (self ):
3660+ """GET /team/roles?editable=true returns only forum roles for Discussion Admin."""
3661+ url = reverse ('instructor_api_v2:course_team_roles' , kwargs = {'course_id' : str (self .course_key )})
3662+ self .client .force_authenticate (user = self .forum_admin )
3663+ response = self .client .get (url , {'editable' : 'true' })
3664+ assert response .status_code == status .HTTP_200_OK
3665+ returned_roles = {r ['role' ] for r in response .data ['results' ]}
3666+ assert returned_roles == {'Administrator' , 'Moderator' , 'Group Moderator' , 'Community TA' }
3667+
3668+ def test_roles_editable_param_returns_all_for_instructor (self ):
3669+ """GET /team/roles?editable=true returns all roles for an instructor."""
3670+ instructor = InstructorFactory .create (course_key = self .course_key )
3671+ url = reverse ('instructor_api_v2:course_team_roles' , kwargs = {'course_id' : str (self .course_key )})
3672+ self .client .force_authenticate (user = instructor )
3673+ response = self .client .get (url , {'editable' : 'true' })
3674+ assert response .status_code == status .HTTP_200_OK
3675+ returned_roles = {r ['role' ] for r in response .data ['results' ]}
3676+ # Instructor should see both course roles and forum roles
3677+ assert 'instructor' in returned_roles
3678+ assert 'staff' in returned_roles
3679+ assert 'Administrator' in returned_roles
3680+
3681+ def test_roles_without_editable_param_returns_all (self ):
3682+ """GET /team/roles without editable param returns all roles regardless of user."""
3683+ url = reverse ('instructor_api_v2:course_team_roles' , kwargs = {'course_id' : str (self .course_key )})
3684+ self .client .force_authenticate (user = self .forum_admin )
3685+ response = self .client .get (url )
3686+ assert response .status_code == status .HTTP_200_OK
3687+ returned_roles = {r ['role' ] for r in response .data ['results' ]}
3688+ # Without editable param, all roles are returned
3689+ assert 'instructor' in returned_roles
3690+ assert 'staff' in returned_roles
3691+ assert 'Administrator' in returned_roles
0 commit comments