|
5 | 5 | permissions, roles, and user assignments within Open edX platform. |
6 | 6 | """ |
7 | 7 |
|
| 8 | +from dataclasses import dataclass |
8 | 9 | import logging |
9 | 10 |
|
10 | 11 | import edx_api_doc_tools as apidocs |
|
31 | 32 | AddUsersToRoleWithScopeSerializer, |
32 | 33 | ListRolesWithScopeResponseSerializer, |
33 | 34 | ListRolesWithScopeSerializer, |
| 35 | + ListTeamMembersSerializer, |
34 | 36 | ListUsersInRoleWithScopeSerializer, |
35 | 37 | PermissionValidationResponseSerializer, |
36 | 38 | PermissionValidationSerializer, |
@@ -449,3 +451,87 @@ def get(self, request: HttpRequest) -> Response: |
449 | 451 | paginated_response_data = paginator.paginate_queryset(response_data, request) |
450 | 452 | serialized_data = ListRolesWithScopeResponseSerializer(paginated_response_data, many=True) |
451 | 453 | return paginator.get_paginated_response(serialized_data.data) |
| 454 | + |
| 455 | +@dataclass |
| 456 | +class UserAssignments: |
| 457 | + user: "User" |
| 458 | + assignments: list[api.RoleAssignmentData] |
| 459 | + |
| 460 | +def get_user_assignment_map(role_assignments: list[api.RoleAssignmentData]) -> list[UserAssignments]: |
| 461 | + """ |
| 462 | + Group role assignments by user |
| 463 | + """ |
| 464 | + usernames = {assignment.subject.username for assignment in role_assignments} |
| 465 | + user_map = get_user_map(usernames) |
| 466 | + |
| 467 | + users_with_assignments: list[UserAssignments] = [] |
| 468 | + |
| 469 | + for username, user in user_map.items(): |
| 470 | + assignments = [a for a in role_assignments if a.subject.username == username] |
| 471 | + users_with_assignments.append(UserAssignments(user=user, assignments=assignments)) |
| 472 | + |
| 473 | + return users_with_assignments |
| 474 | + |
| 475 | + |
| 476 | + |
| 477 | +@view_auth_classes() |
| 478 | +class TeamMembersAPIView(APIView): |
| 479 | + """ |
| 480 | + API view for listing users in relation to role assignations |
| 481 | + """ |
| 482 | + |
| 483 | + pagination_class = AuthZAPIViewPagination |
| 484 | + permission_classes = [DynamicScopePermission] # TODO check if this is needed/works |
| 485 | + |
| 486 | + @apidocs.schema( |
| 487 | + parameters=[ |
| 488 | + apidocs.query_parameter("scopes", str, description="The scopes to query assignations for"), |
| 489 | + apidocs.query_parameter("orgs", str, description="The orgs to query assignations for"), |
| 490 | + apidocs.query_parameter("search", str, description="The search query to filter users by"), |
| 491 | + apidocs.query_parameter("sort_by", str, description="The field to sort by"), |
| 492 | + apidocs.query_parameter("order", str, description="The order to sort by"), |
| 493 | + apidocs.query_parameter("page", int, description="Page number for pagination"), |
| 494 | + apidocs.query_parameter("page_size", int, description="Number of items per page"), |
| 495 | + ], |
| 496 | + responses={ |
| 497 | + status.HTTP_200_OK: ListRolesWithScopeResponseSerializer(many=True), |
| 498 | + status.HTTP_400_BAD_REQUEST: "The request parameters are invalid", |
| 499 | + status.HTTP_401_UNAUTHORIZED: "The user is not authenticated or does not have the required permissions", |
| 500 | + }, |
| 501 | + ) |
| 502 | + @authz_permissions([permissions.VIEW_LIBRARY.identifier]) |
| 503 | + def get(self, request: HttpRequest) -> Response: |
| 504 | + """Retrieve all users that have at least one assignation according to the filtering fields.""" |
| 505 | + serializer = ListTeamMembersSerializer(data=request.query_params) |
| 506 | + serializer.is_valid(raise_exception=True) |
| 507 | + query_params = serializer.validated_data |
| 508 | + |
| 509 | + user_role_assignments = api.get_all_user_role_assignments() |
| 510 | + # Group assignments by user |
| 511 | + users_with_assignments = get_user_assignment_map(user_role_assignments) |
| 512 | + |
| 513 | + if query_params.scopes: |
| 514 | + # Filter by scopes |
| 515 | + scopes = {s.strip() for s in query_params.scopes.split(",")} |
| 516 | + users_with_assignments = [ |
| 517 | + uwa for uwa in users_with_assignments if any(a.scope.external_key in scopes for a in uwa.assignments) |
| 518 | + ] |
| 519 | + |
| 520 | + if query_params.orgs: |
| 521 | + # Filter by orgs |
| 522 | + orgs = {o.strip() for o in query_params.orgs.split(",")} |
| 523 | + users_with_assignments = [ |
| 524 | + uwa for uwa in users_with_assignments if any(a.scope.org in orgs for a in uwa.assignments) |
| 525 | + ] |
| 526 | + |
| 527 | + |
| 528 | + logger.info(f">>>>Query params: {query_params}") |
| 529 | + logger.info(f">>>>assignments: {user_role_assignments}") |
| 530 | + |
| 531 | + # sort |
| 532 | + # paginate |
| 533 | + |
| 534 | + |
| 535 | + return Response({"results": []}, status=status.HTTP_200_OK) |
| 536 | + |
| 537 | + |
0 commit comments