Пример #1
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        Tuple of User object and string (or None) indicating previous cohort

    Raises:
        User.DoesNotExist if can't find user.
        ValueError if user already present in this cohort.
    """
    user = get_user_by_username_or_email(username_or_email)

    membership = CohortMembership(course_user_group=cohort, user=user)
    membership.save()

    tracker.emit(
        "edx.cohort.user_add_requested",
        {
            "user_id": user.id,
            "cohort_id": cohort.id,
            "cohort_name": cohort.name,
            "previous_cohort_id": membership.previous_cohort_id,
            "previous_cohort_name": membership.previous_cohort_name,
        }
    )
    return (user, membership.previous_cohort_name)
Пример #2
0
def remove_user_from_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, remove them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        User object that has been removed from the cohort

    Raises:
        User.DoesNotExist if can't find user.

        ValueError if user is not in this cohort.
    """

    user = get_user_by_username_or_email(username_or_email)

    course_cohorts = CourseUserGroup.objects.filter(
        course_id=cohort.course_id,
        users__id=user.id,
        group_type=CourseUserGroup.COHORT,
    )
    if course_cohorts.exists():
        cohort.users.remove(user)

    return user
    def enter_grade(self, request, suffix=''):
        """
        """
        require(self.is_course_staff())
        user = get_user_by_username_or_email(request.params.get('user'))

        score = request.params.get('score')
        comment = request.params.get('comment')

        if not score:
            return Response(
                json_body={"error": "Enter a valid grade"},
                status_code=400,
            )

        try:
            score = int(score)
        except ValueError:
            return Response(
                json_body={"error": "Enter a valid grade"},
                status_code=400,
            )

        submission_id = self.get_submission_id(user)

        submission = submissions_api.create_submission(submission_id, {'comment': comment})

        submissions_api.set_score(submission['uuid'], score, self.max_score())

        self.get_or_create_student_module(user, score, comment)

        return Response(json_body={"success": "success"})
Пример #4
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        Tuple of User object and string (or None) indicating previous cohort

    Raises:
        User.DoesNotExist if can't find user.
        ValueError if user already present in this cohort.
    """
    user = get_user_by_username_or_email(username_or_email)

    membership = CohortMembership(course_user_group=cohort, user=user)
    membership.save(
    )  # This will handle both cases, creation and updating, of a CohortMembership for this user.

    tracker.emit(
        "edx.cohort.user_add_requested", {
            "user_id": user.id,
            "cohort_id": cohort.id,
            "cohort_name": cohort.name,
            "previous_cohort_id": membership.previous_cohort_id,
            "previous_cohort_name": membership.previous_cohort_name,
        })
    return (user, membership.previous_cohort_name)
Пример #5
0
    def handle(self, *args, **options):
        if len(args) != 1:
            raise CommandError('Must called with arguments: {}'.format(
                self.args))
        try:
            user = get_user_by_username_or_email(args[0])
        except:
            raise CommandError('No user exists [ {} ]'.format(args[0]))

        course_id = options['course_id']
        reactivate = options['reactivate']
        if course_id:
            try:
                course_id = CourseLocator.from_string(course_id)
            except InvalidKeyError:
                raise CommandError(
                    "'{}' is an invalid course_id".format(course_id))
            if not modulestore().get_course(course_id):
                raise CommandError("The specified course does not exist.")
            self.change_optout_state(user, course_id, reactivate)
        else:
            course_enrollments = CourseEnrollment.enrollments_for_user(user)
            for enrollment in course_enrollments:
                course_id = enrollment.course_id
                self.change_optout_state(user, course_id, reactivate)
Пример #6
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        Tuple of User object and string (or None) indicating previous cohort

    Raises:
        User.DoesNotExist if can't find user.
        ValueError if user already present in this cohort.
    """
    user = get_user_by_username_or_email(username_or_email)
    previous_cohort = None

    course_cohorts = CourseUserGroup.objects.filter(
        course_id=cohort.course_id,
        users__id=user.id,
        group_type=CourseUserGroup.COHORT
    )
    if course_cohorts.exists():
        if course_cohorts[0] == cohort:
            raise ValueError("User {0} already present in cohort {1}".format(
                user.username,
                cohort.name))
        else:
            previous_cohort = course_cohorts[0].name
            course_cohorts[0].users.remove(user)

    cohort.users.add(user)
    return (user, previous_cohort)
Пример #7
0
def remove_user_from_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, remove them from the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Raises:
        User.DoesNotExist if can't find user.
        ValueError if user not already present in this cohort.
    """
    user = get_user_by_username_or_email(username_or_email)

    try:
        membership = CohortMembership.objects.get(course_user_group=cohort,
                                                  user=user)
        course_key = membership.course_id
        membership.delete()
        COHORT_MEMBERSHIP_UPDATED.send(sender=None,
                                       user=user,
                                       course_key=course_key)
    except CohortMembership.DoesNotExist:
        raise ValueError("User {} was not present in cohort {}".format(
            username_or_email, cohort))
Пример #8
0
 def validate_user_id(self, user_id):
     try:
         self.user = get_user_by_username_or_email(user_id)
         return user_id
     except DjangoUser.DoesNotExist:
         raise ValidationError(
             u"'{}' is not a valid student identifier".format(user_id))
Пример #9
0
 def filter_assigments_by_team_members(self, assignments, members):
     """This method compares the team's users with an assigments' list"""
     for member in members:
         user = get_user_by_username_or_email(member["user"]["username"])
         for assignment in assignments:
             if user == user_by_anonymous_id(assignment["student_id"]):
                 assignment["profile_image_url"] = self._user_image_url(
                     user)
                 yield assignment
Пример #10
0
def get_student_from_identifier(unique_student_identifier):
    """
    Gets a student object using either an email address or username.

    Returns the student object associated with `unique_student_identifier`

    Raises User.DoesNotExist if no user object can be found, the user was
    retired, or the user is in the process of being retired.

    DEPRECATED: use student.models.get_user_by_username_or_email instead.
    """
    return get_user_by_username_or_email(unique_student_identifier)
Пример #11
0
def get_student_from_identifier(unique_student_identifier):
    """
    Gets a student object using either an email address or username.

    Returns the student object associated with `unique_student_identifier`

    Raises User.DoesNotExist if no user object can be found, the user was
    retired, or the user is in the process of being retired.

    DEPRECATED: use student.models.get_user_by_username_or_email instead.
    """
    return get_user_by_username_or_email(unique_student_identifier)
Пример #12
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        Tuple of User object and string (or None) indicating previous cohort

    Raises:
        User.DoesNotExist if can't find user.
        ValueError if user already present in this cohort.
    """
    user = get_user_by_username_or_email(username_or_email)
    previous_cohort_name = None
    previous_cohort_id = None

    course_cohorts = CourseUserGroup.objects.filter(
        course_id=cohort.course_id,
        users__id=user.id,
        group_type=CourseUserGroup.COHORT
    )
    if course_cohorts.exists():
        if course_cohorts[0] == cohort:
            raise AlreadyAddedToCohortException("User {user_name} already present in cohort {cohort_name}".format(
                user_name=user.username,
                cohort_name=cohort.name
            ))
        else:
            previous_cohort = course_cohorts[0]
            previous_cohort.users.remove(user)
            previous_cohort_name = previous_cohort.name
            previous_cohort_id = previous_cohort.id

    tracker.emit(
        "edx.cohort.user_add_requested",
        {
            "user_id": user.id,
            "cohort_id": cohort.id,
            "cohort_name": cohort.name,
            "previous_cohort_id": previous_cohort_id,
            "previous_cohort_name": previous_cohort_name,
        }
    )
    cohort.users.add(user)
    return (user, previous_cohort_name)
Пример #13
0
def get_user_group_ids(course_id, content, user=None):
    """
    Given a user, course ID, and the content of the thread or comment, returns the group ID for the current user
    and the user that posted the thread/comment.
    """
    content_user_group_id = None
    user_group_id = None
    if course_id is not None:
        if content.get('username'):
            try:
                content_user = get_user_by_username_or_email(content.get('username'))
                content_user_group_id = get_group_id_for_user_from_cache(content_user, course_id)
            except User.DoesNotExist:
                content_user_group_id = None

        user_group_id = get_group_id_for_user_from_cache(user, course_id) if user else None
    return user_group_id, content_user_group_id
Пример #14
0
def get_user_group_ids(course_id, content, user=None):
    """
    Given a user, course ID, and the content of the thread or comment, returns the group ID for the current user
    and the user that posted the thread/comment.
    """
    content_user_group_id = None
    user_group_id = None
    if course_id is not None:
        if content.get('username'):
            try:
                content_user = get_user_by_username_or_email(content.get('username'))
                content_user_group_id = get_group_id_for_user_from_cache(content_user, course_id)
            except User.DoesNotExist:
                content_user_group_id = None

        user_group_id = get_group_id_for_user_from_cache(user, course_id) if user else None
    return user_group_id, content_user_group_id
Пример #15
0
    def get(self, request, course_id=None, username=None):
        """ Return user-metadata for the given course and user """
        try:
            user = get_user_by_username_or_email(username)
        except User.DoesNotExist:
            # Note: this will only be seen by staff, for administrative de-bugging purposes
            message = "Provided user is not found"
            return JsonResponse({'message': message}, status=404)

        try:
            course = courses.get_course_by_id(CourseKey.from_string(course_id))
        except Http404:
            message = "Provided course is not found"
            return JsonResponse({'message': message}, status=404)

        context = get_experiment_user_metadata_context(course, user)
        user_metadata = context.get('user_metadata')
        return JsonResponse(user_metadata)
Пример #16
0
def remove_user_from_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, remove them from the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Raises:
        User.DoesNotExist if can't find user.
        ValueError if user not already present in this cohort.
    """
    user = get_user_by_username_or_email(username_or_email)

    try:
        membership = CohortMembership.objects.get(course_user_group=cohort, user=user)
        membership.delete()
    except CohortMembership.DoesNotExist:
        raise ValueError("User {} was not present in cohort {}".format(username_or_email, cohort))
Пример #17
0
    def get_anonymous_user_id(self, username, course_id):
        """
        Get the anonymous user id for a user.

        Args:
            username(str): username of a user.
            course_id(str): course id of particular course.

        Returns:
            A unique anonymous_user_id for (user, course) pair.
            None for Non-staff users.
        """
        if not self.get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF):
            return None

        try:
            user = get_user_by_username_or_email(username_or_email=username)
        except User.DoesNotExist:
            return None

        course_id = CourseKey.from_string(course_id)
        return anonymous_id_for_user(user=user, course_id=course_id, save=False)
Пример #18
0
    def get_anonymous_user_id(self, username, course_id):
        """
        Get the anonymous user id for a user.

        Args:
            username(str): username of a user.
            course_id(str): course id of particular course.

        Returns:
            A unique anonymous_user_id for (user, course) pair.
            None for Non-staff users.
        """
        if not self.get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF):
            return None

        try:
            user = get_user_by_username_or_email(username_or_email=username)
        except User.DoesNotExist:
            return None

        course_id = CourseKey.from_string(course_id)
        return anonymous_id_for_user(user=user, course_id=course_id, save=False)
Пример #19
0
    def get_state_as_dict(self, username_or_email, block_id):
        """
        Return dict containing user state for a given set of parameters.

        Arguments:
            username_or_email: username or email of the user for whom the data is being retrieved
            block_id: string/object representation of the block whose user state is required

        Returns:
            Returns a dict containing user state, if present, else empty.
        """
        try:
            user = get_user_by_username_or_email(username_or_email=username_or_email)
        except User.DoesNotExist:
            return {}
        try:
            student_module = StudentModule.objects.get(
                student=user,
                module_state_key=block_id
            )
            return json.loads(student_module.state)
        except StudentModule.DoesNotExist:
            return {}
    def handle(self, *args, **options):
        if len(args) != 1:
            raise CommandError('Must called with arguments: {}'.format(self.args))
        try:
            user = get_user_by_username_or_email(args[0])
        except:
            raise CommandError('No user exists [ {} ]'.format(args[0]))

        course_id = options['course_id']
        reactivate = options['reactivate']
        if course_id:
            try:
                course_id = CourseLocator.from_string(course_id)
            except InvalidKeyError:
                raise CommandError("'{}' is an invalid course_id".format(course_id))
            if not modulestore().get_course(course_id):
                raise CommandError("The specified course does not exist.")
            self.change_optout_state(user, course_id, reactivate)
        else:
            course_enrollments = CourseEnrollment.enrollments_for_user(user)
            for enrollment in course_enrollments:
                course_id = enrollment.course_id
                self.change_optout_state(user, course_id, reactivate)
Пример #21
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        User object.

    Raises:
        User.DoesNotExist if can't find user.

        ValueError if user already present in this cohort.

        CohortConflict if user already in another cohort.
    """
    user = get_user_by_username_or_email(username_or_email)

    # If user in any cohorts in this course already, complain
    course_cohorts = CourseUserGroup.objects.filter(
        course_id=cohort.course_id,
        users__id=user.id,
        group_type=CourseUserGroup.COHORT)
    if course_cohorts.exists():
        if course_cohorts[0] == cohort:
            raise ValueError("User {0} already present in cohort {1}".format(
                user.username,
                cohort.name))
        else:
            raise CohortConflict("User {0} is in another cohort {1} in course"
                                 .format(user.username,
                                         course_cohorts[0].name))

    cohort.users.add(user)
    return user
Пример #22
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        User object.

    Raises:
        User.DoesNotExist if can't find user.

        ValueError if user already present in this cohort.

        CohortConflict if user already in another cohort.
    """
    user = get_user_by_username_or_email(username_or_email)

    # If user in any cohorts in this course already, complain
    course_cohorts = CourseUserGroup.objects.filter(
        course_id=cohort.course_id,
        users__id=user.id,
        group_type=CourseUserGroup.COHORT)
    if course_cohorts.exists():
        if course_cohorts[0] == cohort:
            raise ValueError("User {0} already present in cohort {1}".format(
                user.username,
                cohort.name))
        else:
            raise CohortConflict("User {0} is in another cohort {1} in course"
                                 .format(user.username,
                                         course_cohorts[0].name))

    cohort.users.add(user)
    return user
Пример #23
0
 def get_student():
     """ Fetches student instance if an identifier is provided, else return None """
     return None if not student_identifier else get_user_by_username_or_email(student_identifier)
Пример #24
0
 def check_user_enrollment(self, line, username):
     user = get_user_by_username_or_email(username)
     if not CourseEnrollment.is_enrolled(user, self.sga_block.course_id):
         self.add_form_error(
             line,
             _(u"User %s is not enrolled to this course.") % username)
Пример #25
0
 def get_student():
     """ Fetches student instance if an identifier is provided, else return None """
     return None if not student_identifier else get_user_by_username_or_email(
         student_identifier)
Пример #26
0
 def validate_user_id(self, user_id):
     try:
         self.user = get_user_by_username_or_email(user_id)
         return user_id
     except DjangoUser.DoesNotExist:
         raise ValidationError(u"'{}' is not a valid student identifier".format(user_id))
 def submission_id(self):
     """
     """
     user = get_user_by_username_or_email(self.username)
     return self.get_submission_id(user)
 def score(self):
     """
     """
     user = get_user_by_username_or_email(self.username)
     return self.get_score(user)
Пример #29
0
def add_user_to_cohort(cohort, username_or_email_or_user):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email_or_user: user or string.  Treated as email if has '@'

    Returns:
        User object (or None if the email address is preassigned),
        string (or None) indicating previous cohort,
        and whether the user is a preassigned user or not

    Raises:
        User.DoesNotExist if can't find user. However, if a valid email is provided for the user, it is stored
        in a database so that the user can be added to the cohort if they eventually enroll in the course.
        ValueError if user already present in this cohort.
        ValidationError if an invalid email address is entered.
        User.DoesNotExist if a user could not be found.
    """
    try:
        if hasattr(username_or_email_or_user, 'email'):
            user = username_or_email_or_user
        else:
            user = get_user_by_username_or_email(username_or_email_or_user)

        membership, previous_cohort = CohortMembership.assign(cohort, user)
        tracker.emit(
            "edx.cohort.user_add_requested",
            {
                "user_id": user.id,
                "cohort_id": cohort.id,
                "cohort_name": cohort.name,
                "previous_cohort_id": getattr(previous_cohort, 'id', None),
                "previous_cohort_name": getattr(previous_cohort, 'name', None),
            }
        )
        cache = RequestCache(COHORT_CACHE_NAMESPACE).data
        cache_key = _cohort_cache_key(user.id, membership.course_id)
        cache[cache_key] = membership.course_user_group
        COHORT_MEMBERSHIP_UPDATED.send(sender=None, user=user, course_key=membership.course_id)
        return user, getattr(previous_cohort, 'name', None), False
    except User.DoesNotExist as ex:
        # If username_or_email is an email address, store in database.
        try:
            validate_email(username_or_email_or_user)

            try:
                assignment = UnregisteredLearnerCohortAssignments.objects.get(
                    email=username_or_email_or_user, course_id=cohort.course_id
                )
                assignment.course_user_group = cohort
                assignment.save()
            except UnregisteredLearnerCohortAssignments.DoesNotExist:
                assignment = UnregisteredLearnerCohortAssignments.objects.create(
                    course_user_group=cohort, email=username_or_email_or_user, course_id=cohort.course_id
                )

            tracker.emit(
                "edx.cohort.email_address_preassigned",
                {
                    "user_email": assignment.email,
                    "cohort_id": cohort.id,
                    "cohort_name": cohort.name,
                }
            )

            return (None, None, True)
        except ValidationError as invalid:
            if "@" in username_or_email_or_user:
                raise invalid
            else:
                raise ex
Пример #30
0
    def handle_grades_file(self, file):
        """Read the file and set score and finalize flag and fresh flag and grade date and comment.
        Note:
            We expect a csv file following this structure:
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
                | Username | Name | Filename | Uploaded at          | Fresh answer | Finalized | Grade Date           | Grade | Max grade | Comment  |
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
                | student1 | S.St | 5.PNG    | 10-03-2020 16:01 MSK | False        | False     | 10-03-2020 16:05 MSK | 23    | 100       | bad work |
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
                | student2 | Mary | 7.JPG    | 15-03-2020 11:01 MSK | True         | False     |                      |       | 100       |          |
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
        Args:
            file: The grades csv file.
        """
        grades_file = csv.DictReader(file, [
            'username', 'fullname', 'filename', 'timestamp', 'fresh',
            'finalized', 'date_fin', 'score', 'max_score', 'comment'
        ],
                                     delimiter=',')
        for line, row in enumerate(grades_file):
            if line:
                user = get_user_by_username_or_email(row['username'])
                module = self.get_or_create_student_module(user)
                state = json.loads(module.state)
                student_id = anonymous_id_for_user(
                    user, CourseKey.from_string(self.block_course_id))
                score = submissions_api.get_score(
                    self.get_student_item_dict(student_id))
                new = False
                if score and score['points_earned'] == row['score']:
                    pass
                elif score or row['score']:
                    new = True

                submission = self.get_submission(student_id)
                if not submission:
                    continue
                uuid = submission['uuid']
                if new:
                    submissions_api.set_score(uuid, row['score'],
                                              self.max_score())
                submission_obj = Submission.objects.get(uuid=uuid)
                if submission_obj.answer['finalized'] != json.loads(
                        row['finalized'].lower()):
                    submission_obj.answer['finalized'] = json.loads(
                        row['finalized'].lower())
                    submission_obj.save()
                    new = True
                if row['comment']:
                    try:
                        if state['comment'].encode('utf-8') != row['comment']:
                            new = True
                            state['comment'] = row['comment']
                    except:
                        state.update({'comment': row['comment']})
                        new = True
                if new:
                    state['date_fin'] = force_text(django_now())
                    state['fresh'] = False
                module.state = json.dumps(state)
                module.save()
Пример #31
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        User object (or None if the email address is preassigned),
        string (or None) indicating previous cohort,
        and whether the user is a preassigned user or not

    Raises:
        User.DoesNotExist if can't find user. However, if a valid email is provided for the user, it is stored
        in a database so that the user can be added to the cohort if they eventually enroll in the course.
        ValueError if user already present in this cohort.
        ValidationError if an invalid email address is entered.
        User.DoesNotExist if a user could not be found.
    """
    try:
        user = get_user_by_username_or_email(username_or_email)

        membership = CohortMembership(course_user_group=cohort, user=user)
        membership.save(
        )  # This will handle both cases, creation and updating, of a CohortMembership for this user.
        COHORT_MEMBERSHIP_UPDATED.send(sender=None,
                                       user=user,
                                       course_key=membership.course_id)
        tracker.emit(
            "edx.cohort.user_add_requested", {
                "user_id": user.id,
                "cohort_id": cohort.id,
                "cohort_name": cohort.name,
                "previous_cohort_id": membership.previous_cohort_id,
                "previous_cohort_name": membership.previous_cohort_name,
            })
        return (user, membership.previous_cohort_name, False)
    except User.DoesNotExist as ex:
        # If username_or_email is an email address, store in database.
        try:
            validate_email(username_or_email)

            try:
                assignment = UnregisteredLearnerCohortAssignments.objects.get(
                    email=username_or_email, course_id=cohort.course_id)
                assignment.course_user_group = cohort
                assignment.save()
            except UnregisteredLearnerCohortAssignments.DoesNotExist:
                assignment = UnregisteredLearnerCohortAssignments.objects.create(
                    course_user_group=cohort,
                    email=username_or_email,
                    course_id=cohort.course_id)

            tracker.emit(
                "edx.cohort.email_address_preassigned", {
                    "user_email": assignment.email,
                    "cohort_id": cohort.id,
                    "cohort_name": cohort.name,
                })

            return (None, None, True)
        except ValidationError as invalid:
            if "@" in username_or_email:
                raise invalid
            else:
                raise ex
Пример #32
0
def add_user_to_cohort(cohort, username_or_email):
    """
    Look up the given user, and if successful, add them to the specified cohort.

    Arguments:
        cohort: CourseUserGroup
        username_or_email: string.  Treated as email if has '@'

    Returns:
        User object (or None if the email address is preassigned),
        string (or None) indicating previous cohort,
        and whether the user is a preassigned user or not

    Raises:
        User.DoesNotExist if can't find user. However, if a valid email is provided for the user, it is stored
        in a database so that the user can be added to the cohort if they eventually enroll in the course.
        ValueError if user already present in this cohort.
        ValidationError if an invalid email address is entered.
        User.DoesNotExist if a user could not be found.
    """
    try:
        user = get_user_by_username_or_email(username_or_email)

        membership = CohortMembership(course_user_group=cohort, user=user)
        membership.save()  # This will handle both cases, creation and updating, of a CohortMembership for this user.

        tracker.emit(
            "edx.cohort.user_add_requested",
            {
                "user_id": user.id,
                "cohort_id": cohort.id,
                "cohort_name": cohort.name,
                "previous_cohort_id": membership.previous_cohort_id,
                "previous_cohort_name": membership.previous_cohort_name,
            }
        )
        return (user, membership.previous_cohort_name, False)
    except User.DoesNotExist as ex:
        # If username_or_email is an email address, store in database.
        try:
            validate_email(username_or_email)

            try:
                assignment = UnregisteredLearnerCohortAssignments.objects.get(
                    email=username_or_email, course_id=cohort.course_id
                )
                assignment.course_user_group = cohort
                assignment.save()
            except UnregisteredLearnerCohortAssignments.DoesNotExist:
                assignment = UnregisteredLearnerCohortAssignments.objects.create(
                    course_user_group=cohort, email=username_or_email, course_id=cohort.course_id
                )

            tracker.emit(
                "edx.cohort.email_address_preassigned",
                {
                    "user_email": assignment.email,
                    "cohort_id": cohort.id,
                    "cohort_name": cohort.name,
                }
            )

            return (None, None, True)
        except ValidationError as invalid:
            if "@" in username_or_email:
                raise invalid
            else:
                raise ex