@@ -861,3 +861,149 @@ def get(self, request: HttpRequest, username: str) -> Response:
861861 paginator = self .pagination_class ()
862862 paginated_response_data = paginator .paginate_queryset (assignments , request )
863863 return paginator .get_paginated_response (paginated_response_data )
864+
865+
866+ @view_auth_classes ()
867+ class AssignmentsAPIView (APIView ):
868+ """
869+ API view for listing all user role assignments
870+ This API is used on the main team members view on the Admin Console.
871+
872+ **Endpoints**
873+
874+ - GET: Retrieve all user role assignments
875+
876+ **Query Parameters**
877+
878+ - orgs (Optional): Comma-separated list of orgs to filter assignments by
879+ - roles (Optional): Comma-separated list of roles to filter assignments by
880+ - scopes (Optional): Comma-separated list of scopes to filter assignments by
881+ - search (Optional): Search term to filter assignments by full_name, username, or email
882+ - sort_by (Optional): Field to sort by. Options: role, org, scope, full_name, username, email. Defaults to full_name
883+ - order (Optional): Sort order, 'asc' or 'desc'. Defaults to asc
884+ - page (Optional): Page number for pagination
885+ - page_size (Optional): Number of items per page
886+
887+ **Response Format**
888+
889+ Returns a paginated list of user assignment objects, each containing:
890+
891+ - is_superadmin: whether this entry denotes a superadmin
892+ - role: The role
893+ - org: The org over which this role is applied
894+ - scope: The scope over which this role is applied
895+ - permission_count: The number of permissions that apply to this role
896+ - full_name: The full name of the user in this assignment
897+ - username: The username of the user in this assignment
898+ - email: The email of the user in this assignment
899+
900+ **Authentication and Permissions**
901+
902+ - Requires authenticated user.
903+ - Results are filtered according to calling user's "view scope team members" permissions.
904+
905+ **Example Request**
906+
907+ GET /api/authz/v1/assignments/?order=desc&sort_by=role&page=1&page_size=2&search=cont
908+
909+ **Example Response**::
910+
911+ {
912+ "count": 2,
913+ "next": null,
914+ "previous": null,
915+ "results": [
916+ {
917+ "is_superadmin": false,
918+ "role": "course_staff",
919+ "org": "OpenedX",
920+ "scope": "course-v1:OpenedX+DemoX+DemoCourse",
921+ "permission_count": 27,
922+ "full_name": "",
923+ "username": "contributor",
924+ 925+ },
926+ {
927+ "is_superadmin": true,
928+ "role": "django.superuser",
929+ "org": "*",
930+ "scope": "*",
931+ "permission_count": null,
932+ "full_name": "",
933+ "username": "admin",
934+ 935+ },
936+ ]
937+ }
938+ """
939+
940+ pagination_class = AuthZAPIViewPagination
941+ filter_backends = [UserAssignmentsSearchFilter , UserAssignmentsOrderingFilter ]
942+ permission_classes = [AnyScopePermission ]
943+
944+ @apidocs .schema (
945+ parameters = [
946+ apidocs .query_parameter ("orgs" , str , description = "The orgs to query assignments for" ),
947+ apidocs .query_parameter ("roles" , str , description = "The roles to query assignments for" ),
948+ apidocs .query_parameter ("scopes" , str , description = "The scopes to query assignments for" ),
949+ apidocs .query_parameter (
950+ "search" , str , description = "The search query to filter assignments by full_name, username, or email"
951+ ),
952+ apidocs .query_parameter (
953+ "sort_by" ,
954+ str ,
955+ description = "The field to sort by. Options: role, org, scope, full_name, username, email" ,
956+ ),
957+ apidocs .query_parameter ("order" , str , description = "The order to sort by" ),
958+ apidocs .query_parameter ("page" , int , description = "Page number for pagination" ),
959+ apidocs .query_parameter ("page_size" , int , description = "Number of items per page" ),
960+ ],
961+ responses = {
962+ status .HTTP_200_OK : TeamMemberUserAssignmentSerializer (many = True ),
963+ status .HTTP_400_BAD_REQUEST : "The request parameters are invalid" ,
964+ status .HTTP_401_UNAUTHORIZED : "The user is not authenticated or does not have the required permissions" ,
965+ status .HTTP_403_FORBIDDEN : "The user does not have the required permisisons" ,
966+ },
967+ )
968+ @authz_permissions (
969+ [
970+ permissions .VIEW_LIBRARY_TEAM .identifier ,
971+ permissions .COURSES_VIEW_COURSE_TEAM .identifier ,
972+ ]
973+ )
974+ def get (self , request : HttpRequest ) -> Response :
975+ """Retrieve all user role assignments."""
976+ serializer = ListAllTeamMembersAssignmentsSerializer (data = request .query_params )
977+ serializer .is_valid (raise_exception = True )
978+ query_params = serializer .validated_data
979+
980+ user_role_assignments : list [UserAssignmentData | SuperAdminAssignmentData ] = []
981+
982+ # Retrieve superadmin assignments (django staff or superuser users), as they always have access to everything
983+ user_role_assignments += get_superadmin_assignments ()
984+
985+ users_with_assignments = api .get_visible_role_assignments_for_user (
986+ orgs = query_params .get ("orgs" ),
987+ scopes = query_params .get ("scopes" ),
988+ roles = query_params .get ("roles" ),
989+ allowed_for_user_external_key = request .user .username ,
990+ )
991+
992+ # Unpack list of UserAssignments to a list of UserAssignmentData
993+ for uwa in users_with_assignments :
994+ user_role_assignments += [
995+ UserAssignmentData (
996+ user = uwa .user , subject = assignment .subject , roles = assignment .roles , scope = assignment .scope
997+ )
998+ for assignment in uwa .assignments
999+ ]
1000+
1001+ assignments = TeamMemberUserAssignmentSerializer (user_role_assignments , many = True ).data
1002+ for backend in self .filter_backends :
1003+ assignments = backend ().filter_queryset (request , assignments , self )
1004+
1005+ # Paginate
1006+ paginator = self .pagination_class ()
1007+ paginated_response_data = paginator .paginate_queryset (assignments , request )
1008+ return paginator .get_paginated_response (paginated_response_data )
1009+
0 commit comments