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