|
43 | 43 | RemoveUsersFromRoleWithScopeSerializer, |
44 | 44 | TeamMemberSerializer, |
45 | 45 | UserRoleAssignmentSerializer, |
| 46 | + UserValidationAPIViewResponseSerializer, |
| 47 | + UserValidationAPIViewSerializer, |
46 | 48 | ) |
47 | 49 | from openedx_authz.utils import get_user_by_username_or_email |
48 | 50 |
|
@@ -590,3 +592,86 @@ def get(self, request: HttpRequest) -> Response: |
590 | 592 | paginator = self.pagination_class() |
591 | 593 | paginated_response_data = paginator.paginate_queryset(team_members, request) |
592 | 594 | return paginator.get_paginated_response(paginated_response_data) |
| 595 | + |
| 596 | + |
| 597 | +@view_auth_classes() |
| 598 | +class UserValidationAPIView(APIView): |
| 599 | + """API view for validating that provided user identifiers correspond to existing users. |
| 600 | +
|
| 601 | + This view allows clients to verify that a list of user identifiers (usernames or emails) |
| 602 | + correspond to valid users in the system. It is designed to support bulk validation of multiple |
| 603 | + user identifiers in a single request, providing a convenient way to check the validity of users before |
| 604 | + performing operations such as role assignments. |
| 605 | +
|
| 606 | + **Endpoints** |
| 607 | + - POST: Validate that the provided list of usernames or emails correspond to existing users |
| 608 | +
|
| 609 | + **Request Format (POST)** |
| 610 | + - users: List of user identifiers (username or email) |
| 611 | +
|
| 612 | + **Response Format (POST)** |
| 613 | +
|
| 614 | + Returns HTTP 200 OK with:: |
| 615 | +
|
| 616 | + { |
| 617 | + "valid_users": ["john_doe", "[email protected]"], |
| 618 | + "invalid_users": ["nonexistent_user"], |
| 619 | + "summary": { |
| 620 | + "total": 3, |
| 621 | + "valid_count": 2, |
| 622 | + "invalid_count": 1 |
| 623 | + } |
| 624 | + } |
| 625 | +
|
| 626 | + **Authentication and Permissions** |
| 627 | +
|
| 628 | + - Requires authenticated user. |
| 629 | + - Requires ``manage_library_team`` or ``manage_course_team`` permission in any scope. |
| 630 | +
|
| 631 | + **Example Request** |
| 632 | +
|
| 633 | + POST /api/authz/v1/users/validate/ :: |
| 634 | +
|
| 635 | + { |
| 636 | + "users": ["john_doe", "[email protected]", "nonexistent_user"] |
| 637 | + } |
| 638 | + """ |
| 639 | + |
| 640 | + permission_classes = [AnyScopePermission] |
| 641 | + |
| 642 | + @apidocs.schema( |
| 643 | + body=UserValidationAPIViewSerializer, |
| 644 | + responses={ |
| 645 | + status.HTTP_200_OK: UserValidationAPIViewResponseSerializer, |
| 646 | + status.HTTP_400_BAD_REQUEST: "The request data is invalid", |
| 647 | + status.HTTP_401_UNAUTHORIZED: "The user is not authenticated", |
| 648 | + status.HTTP_403_FORBIDDEN: "The user does not have the required permissions", |
| 649 | + status.HTTP_500_INTERNAL_SERVER_ERROR: "An unexpected error occurred while validating users", |
| 650 | + }, |
| 651 | + ) |
| 652 | + @authz_permissions([permissions.MANAGE_LIBRARY_TEAM.identifier, permissions.COURSES_MANAGE_COURSE_TEAM.identifier]) |
| 653 | + def post(self, request: HttpRequest) -> Response: |
| 654 | + """Validates the provided usernames or emails correspond to existing users.""" |
| 655 | + request_serializer = UserValidationAPIViewSerializer(data=request.data) |
| 656 | + request_serializer.is_valid(raise_exception=True) |
| 657 | + serialized_request_users = request_serializer.validated_data["users"] |
| 658 | + try: |
| 659 | + valid_users, invalid_users = api.validate_users(serialized_request_users) |
| 660 | + except Exception as e: # pylint: disable=broad-exception-caught |
| 661 | + logger.error(f"Error validating users: {e}") |
| 662 | + return Response( |
| 663 | + data={"message": "An error occurred while validating users"}, |
| 664 | + status=status.HTTP_500_INTERNAL_SERVER_ERROR, |
| 665 | + ) |
| 666 | + |
| 667 | + response_data = { |
| 668 | + "valid_users": valid_users, |
| 669 | + "invalid_users": invalid_users, |
| 670 | + "summary": { |
| 671 | + "total": len(serialized_request_users), |
| 672 | + "valid_count": len(valid_users), |
| 673 | + "invalid_count": len(invalid_users), |
| 674 | + }, |
| 675 | + } |
| 676 | + response_serializer = UserValidationAPIViewResponseSerializer(response_data) |
| 677 | + return Response(response_serializer.data, status=status.HTTP_200_OK) |
0 commit comments