Ejemplo n.º 1
0
    def test_post_list_staff_master_course_in_ccx(self):
        """
        Specific test to check that the staff and instructor of the master
        course are assigned to the CCX.
        """
        outbox = self.get_outbox()
        data = {
            'master_course_id': self.master_course_key_str,
            'max_students_allowed': 111,
            'display_name': 'CCX Test Title',
            'coach_email': self.coach.email
        }
        resp = self.client.post(self.list_url, data, format='json', HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
        # check that only one email has been sent and it is to to the coach
        self.assertEqual(len(outbox), 1)
        self.assertIn(self.coach.email, outbox[0].recipients())  # pylint: disable=no-member

        list_staff_master_course = list_with_level(self.course, 'staff')
        list_instructor_master_course = list_with_level(self.course, 'instructor')
        course_key = CourseKey.from_string(resp.data.get('ccx_course_id'))  # pylint: disable=no-member
        with ccx_course_cm(course_key) as course_ccx:
            list_staff_ccx_course = list_with_level(course_ccx, 'staff')
            list_instructor_ccx_course = list_with_level(course_ccx, 'instructor')

        self.assertEqual(len(list_staff_master_course), len(list_staff_ccx_course))
        for course_user, ccx_user in izip(sorted(list_staff_master_course), sorted(list_staff_ccx_course)):
            self.assertEqual(course_user, ccx_user)
        self.assertEqual(len(list_instructor_master_course), len(list_instructor_ccx_course))
        for course_user, ccx_user in izip(sorted(list_instructor_master_course), sorted(list_instructor_ccx_course)):
            self.assertEqual(course_user, ccx_user)
Ejemplo n.º 2
0
    def test_create_ccx(self, ccx_name='New CCX'):
        """
        Create CCX. Follow redirect to coach dashboard, confirm we see
        the coach dashboard for the new CCX.
        """

        self.make_coach()
        url = reverse(
            'create_ccx',
            kwargs={'course_id': unicode(self.course.id)})

        response = self.client.post(url, {'name': ccx_name})
        self.assertEqual(response.status_code, 302)
        url = response.get('location')  # pylint: disable=no-member
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        # Get the ccx_key
        path = urlparse.urlparse(url).path
        resolver = resolve(path)
        ccx_key = resolver.kwargs['course_id']

        course_key = CourseKey.from_string(ccx_key)

        self.assertTrue(CourseEnrollment.is_enrolled(self.coach, course_key))
        self.assertTrue(re.search('id="ccx-schedule"', response.content))

        # check if the max amount of student that can be enrolled has been overridden
        ccx = CustomCourseForEdX.objects.get()
        course_enrollments = get_override_for_ccx(ccx, self.course, 'max_student_enrollments_allowed')
        self.assertEqual(course_enrollments, settings.CCX_MAX_STUDENTS_ALLOWED)

        # assert ccx creator has role=ccx_coach
        role = CourseCcxCoachRole(course_key)
        self.assertTrue(role.has_user(self.coach))

        # assert that staff and instructors of master course has staff and instructor roles on ccx
        list_staff_master_course = list_with_level(self.course, 'staff')
        list_instructor_master_course = list_with_level(self.course, 'instructor')

        with ccx_course(course_key) as course_ccx:
            list_staff_ccx_course = list_with_level(course_ccx, 'staff')
            self.assertEqual(len(list_staff_master_course), len(list_staff_ccx_course))
            self.assertEqual(list_staff_master_course[0].email, list_staff_ccx_course[0].email)

            list_instructor_ccx_course = list_with_level(course_ccx, 'instructor')
            self.assertEqual(len(list_instructor_ccx_course), len(list_instructor_master_course))
            self.assertEqual(list_instructor_ccx_course[0].email, list_instructor_master_course[0].email)
Ejemplo n.º 3
0
def remove_master_course_staff_from_ccx(master_course, ccx_key, display_name, send_email=True):
    """
    Remove staff and instructor roles on ccx to all the staff and instructors members of master course.

    Arguments:
        master_course (CourseDescriptorWithMixins): Master course instance.
        ccx_key (CCXLocator): CCX course key.
        display_name (str): ccx display name for email.
        send_email (bool): flag to switch on or off email to the users on revoke access.

    """
    list_staff = list_with_level(master_course, 'staff')
    list_instructor = list_with_level(master_course, 'instructor')

    with ccx_course(ccx_key) as course_ccx:
        list_staff_ccx = list_with_level(course_ccx, 'staff')
        list_instructor_ccx = list_with_level(course_ccx, 'instructor')
        email_params = get_email_params(course_ccx, auto_enroll=True, course_key=ccx_key, display_name=display_name)
        for staff in list_staff:
            if staff in list_staff_ccx:
                # revoke 'staff' access on ccx.
                revoke_access(course_ccx, staff, 'staff')

                # Unenroll the staff on ccx.
                unenroll_email(
                    course_id=ccx_key,
                    student_email=staff.email,
                    email_students=send_email,
                    email_params=email_params,
                )

        for instructor in list_instructor:
            if instructor in list_instructor_ccx:
                # revoke 'instructor' access on ccx.
                revoke_access(course_ccx, instructor, 'instructor')

                # Unenroll the instructor on ccx.
                unenroll_email(
                    course_id=ccx_key,
                    student_email=instructor.email,
                    email_students=send_email,
                    email_params=email_params,
                )
Ejemplo n.º 4
0
def add_master_course_staff_to_ccx(master_course, ccx_key, display_name):
    """
    Added staff role on ccx to all the staff members of master course.

    Arguments:
        master_course (CourseDescriptorWithMixins): Master course instance
        ccx_key (CCXLocator): CCX course key
        display_name (str): ccx display name for email
    """
    list_staff = list_with_level(master_course, 'staff')
    list_instructor = list_with_level(master_course, 'instructor')

    with ccx_course(ccx_key) as course_ccx:
        email_params = get_email_params(course_ccx, auto_enroll=True, course_key=ccx_key, display_name=display_name)
        for staff in list_staff:
            # allow 'staff' access on ccx to staff of master course
            allow_access(course_ccx, staff, 'staff')

            # Enroll the staff in the ccx
            enroll_email(
                course_id=ccx_key,
                student_email=staff.email,
                auto_enroll=True,
                email_students=True,
                email_params=email_params,
            )

        for instructor in list_instructor:
            # allow 'instructor' access on ccx to instructor of master course
            allow_access(course_ccx, instructor, 'instructor')

            # Enroll the instructor in the ccx
            enroll_email(
                course_id=ccx_key,
                student_email=instructor.email,
                auto_enroll=True,
                email_students=True,
                email_params=email_params,
            )
Ejemplo n.º 5
0
def list_course_role_members(request, course_id):
    """
    List instructors and staff.
    Requires instructor access.

    rolename is one of ['instructor', 'staff', 'beta']

    Returns JSON of the form {
        "course_id": "some/course/id",
        "staff": [
            {
                "username": "******",
                "email": "*****@*****.**",
                "first_name": "Joe",
                "last_name": "Shmoe",
            }
        ]
    }
    """
    course = get_course_with_access(
        request.user, course_id, 'instructor', depth=None
    )

    rolename = request.GET.get('rolename')

    if not rolename in ['instructor', 'staff', 'beta']:
        return HttpResponseBadRequest()

    def extract_user_info(user):
        """ convert user into dicts for json view """
        return {
            'username': user.username,
            'email': user.email,
            'first_name': user.first_name,
            'last_name': user.last_name,
        }

    response_payload = {
        'course_id': course_id,
        rolename: map(extract_user_info, access.list_with_level(
            course, rolename
        )),
    }
    response = HttpResponse(
        json.dumps(response_payload), content_type="application/json"
    )
    return response
Ejemplo n.º 6
0
def list_course_role_members(request, course_id):
    """
    List instructors and staff.
    Requires instructor access.

    rolename is one of ['instructor', 'staff', 'beta']

    Returns JSON of the form {
        "course_id": "some/course/id",
        "staff": [
            {
                "username": "******",
                "email": "*****@*****.**",
                "first_name": "Joe",
                "last_name": "Shmoe",
            }
        ]
    }
    """
    course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(
        request.user, 'instructor', course_id, depth=None
    )

    rolename = request.GET.get('rolename')

    if not rolename in ['instructor', 'staff', 'beta']:
        return HttpResponseBadRequest()

    def extract_user_info(user):
        """ convert user into dicts for json view """
        return {
            'username': user.username,
            'email': user.email,
            'first_name': user.first_name,
            'last_name': user.last_name,
        }

    response_payload = {
        'course_id': course_id.to_deprecated_string(),
        rolename: map(extract_user_info, list_with_level(
            course, rolename
        )),
    }
    return JsonResponse(response_payload)
Ejemplo n.º 7
0
def list_course_role_members(request, course_id):
    """
    List instructors and staff.
    Requires instructor access.

    rolename is one of ['instructor', 'staff', 'beta']

    Returns JSON of the form {
        "course_id": "some/course/id",
        "staff": [
            {
                "username": "******",
                "email": "*****@*****.**",
                "first_name": "Joe",
                "last_name": "Shmoe",
            }
        ]
    }
    """
    course = get_course_with_access(request.user, course_id, "instructor", depth=None)

    rolename = request.GET.get("rolename")

    if not rolename in ["instructor", "staff", "beta"]:
        return HttpResponseBadRequest()

    def extract_user_info(user):
        """ convert user into dicts for json view """
        return {
            "username": user.username,
            "email": user.email,
            "first_name": user.first_name,
            "last_name": user.last_name,
        }

    response_payload = {"course_id": course_id, rolename: map(extract_user_info, list_with_level(course, rolename))}
    return JsonResponse(response_payload)
Ejemplo n.º 8
0
def add_master_course_staff_to_ccx(master_course, ccx_key, display_name, send_email=True):
    """
    Add staff and instructor roles on ccx to all the staff and instructors members of master course.

    Arguments:
        master_course (CourseDescriptorWithMixins): Master course instance.
        ccx_key (CCXLocator): CCX course key.
        display_name (str): ccx display name for email.
        send_email (bool): flag to switch on or off email to the users on access grant.

    """
    list_staff = list_with_level(master_course, 'staff')
    list_instructor = list_with_level(master_course, 'instructor')

    with ccx_course(ccx_key) as course_ccx:
        email_params = get_email_params(course_ccx, auto_enroll=True, course_key=ccx_key, display_name=display_name)
        list_staff_ccx = list_with_level(course_ccx, 'staff')
        list_instructor_ccx = list_with_level(course_ccx, 'instructor')
        for staff in list_staff:
            # this call should be idempotent
            if staff not in list_staff_ccx:
                try:
                    # Enroll the staff in the ccx
                    enroll_email(
                        course_id=ccx_key,
                        student_email=staff.email,
                        auto_enroll=True,
                        email_students=send_email,
                        email_params=email_params,
                    )

                    # allow 'staff' access on ccx to staff of master course
                    allow_access(course_ccx, staff, 'staff')
                except CourseEnrollmentException:
                    log.warning(
                        "Unable to enroll staff %s to course with id %s",
                        staff.email,
                        ccx_key
                    )
                    continue
                except SMTPException:
                    continue

        for instructor in list_instructor:
            # this call should be idempotent
            if instructor not in list_instructor_ccx:
                try:
                    # Enroll the instructor in the ccx
                    enroll_email(
                        course_id=ccx_key,
                        student_email=instructor.email,
                        auto_enroll=True,
                        email_students=send_email,
                        email_params=email_params,
                    )

                    # allow 'instructor' access on ccx to instructor of master course
                    allow_access(course_ccx, instructor, 'instructor')
                except CourseEnrollmentException:
                    log.warning(
                        "Unable to enroll instructor %s to course with id %s",
                        instructor.email,
                        ccx_key
                    )
                    continue
                except SMTPException:
                    continue
Ejemplo n.º 9
0
 def test_list_beta(self):
     beta_testers = list_with_level(self.course, 'beta')
     self.assertEqual(set(beta_testers), set(self.beta_testers))
Ejemplo n.º 10
0
 def test_list_instructors(self):
     instructors = list_with_level(self.course, 'instructor')
     self.assertEqual(set(instructors), set(self.instructors))
Ejemplo n.º 11
0
def add_master_course_staff_to_ccx(master_course,
                                   ccx_key,
                                   display_name,
                                   send_email=True):
    """
    Add staff and instructor roles on ccx to all the staff and instructors members of master course.

    Arguments:
        master_course (CourseDescriptorWithMixins): Master course instance.
        ccx_key (CCXLocator): CCX course key.
        display_name (str): ccx display name for email.
        send_email (bool): flag to switch on or off email to the users on access grant.

    """
    list_staff = list_with_level(master_course, 'staff')
    list_instructor = list_with_level(master_course, 'instructor')

    with ccx_course(ccx_key) as course_ccx:
        email_params = get_email_params(course_ccx,
                                        auto_enroll=True,
                                        course_key=ccx_key,
                                        display_name=display_name)
        list_staff_ccx = list_with_level(course_ccx, 'staff')
        list_instructor_ccx = list_with_level(course_ccx, 'instructor')
        for staff in list_staff:
            # this call should be idempotent
            if staff not in list_staff_ccx:
                try:
                    # Enroll the staff in the ccx
                    enroll_email(
                        course_id=ccx_key,
                        student_email=staff.email,
                        auto_enroll=True,
                        email_students=send_email,
                        email_params=email_params,
                    )

                    # allow 'staff' access on ccx to staff of master course
                    allow_access(course_ccx, staff, 'staff')
                except CourseEnrollmentException:
                    log.warning(
                        "Unable to enroll staff %s to course with id %s",
                        staff.email, ccx_key)
                    continue
                except SMTPException:
                    continue

        for instructor in list_instructor:
            # this call should be idempotent
            if instructor not in list_instructor_ccx:
                try:
                    # Enroll the instructor in the ccx
                    enroll_email(
                        course_id=ccx_key,
                        student_email=instructor.email,
                        auto_enroll=True,
                        email_students=send_email,
                        email_params=email_params,
                    )

                    # allow 'instructor' access on ccx to instructor of master course
                    allow_access(course_ccx, instructor, 'instructor')
                except CourseEnrollmentException:
                    log.warning(
                        "Unable to enroll instructor %s to course with id %s",
                        instructor.email, ccx_key)
                    continue
                except SMTPException:
                    continue
Ejemplo n.º 12
0
 def test_allow_beta(self):
     """ Test allow beta against list beta. """
     user = UserFactory()
     allow_access(self.course, user, 'beta')
     self.assertIn(user, list_with_level(self.course, 'beta'))
Ejemplo n.º 13
0
 def test_revoke_beta(self):
     user = self.beta_testers[0]
     revoke_access(self.course, user, 'beta')
     self.assertNotIn(user, list_with_level(self.course, 'beta'))
Ejemplo n.º 14
0
 def test_revoke_beta(self):
     user = self.beta_testers[0]
     revoke_access(self.course, user, 'beta')
     self.assertNotIn(user, list_with_level(self.course, 'beta'))
Ejemplo n.º 15
0
 def test_list_instructors(self):
     instructors = list_with_level(self.course, 'instructor')
     self.assertEqual(set(instructors), set(self.instructors))
Ejemplo n.º 16
0
 def test_list_beta(self):
     beta_testers = list_with_level(self.course, 'beta')
     self.assertEqual(set(beta_testers), set(self.beta_testers))
Ejemplo n.º 17
0
def populate_user(user, authentication_response):

    attr = authentication_response.find(CAS + 'authenticationSuccess/' + CAS +
                                        'attributes',
                                        namespaces=NSMAP)

    if attr is not None:

        staff_flag = attr.find(CAS + 'is_staff', NSMAP)
        if staff_flag is not None:
            user.is_staff = (staff_flag.text or '').upper() == 'TRUE'

        superuser_flag = attr.find(CAS + 'is_superuser', NSMAP)
        if superuser_flag is not None:
            user.is_superuser = (superuser_flag.text or '').upper() == 'TRUE'

        active_flag = attr.find(CAS + 'is_active', NSMAP)
        if active_flag is not None:
            user.is_active = (active_flag.text or '').upper() == 'TRUE'

        # Limiting by maximum lengths.
        # Max length of firstname/lastname is 30.
        # Max length of a email is 75.

        first_name = attr.find(CAS + 'givenName', NSMAP)
        if first_name is not None:
            user.first_name = (first_name.text or '')[0:30]

        last_name = attr.find(CAS + 'sn', NSMAP)
        if last_name is not None:
            user.last_name = (last_name.text or '')[0:30]

        email = attr.find(CAS + 'email', NSMAP)
        if email is not None:
            user.email = (email.text or '')[0:75]

        # Here we handle things that go into UserProfile instead.

        # This is a dirty hack and you shouldn't do that.
        # However, I don't think it's going to work when imported outside of the function body.

        from student.models import UserProfile

        # Make the user's password unusable. But only if they don't have an unusable password already,
        # to prevent SessionAuthenticationMiddleware from logging them out because their password changed.
        if user.has_usable_password():
            user.set_unusable_password()
        user.save()

        # If the user doesn't yet have a profile, it means it's a new one and we need to create it a profile.
        # but we need to save the user first.
        user_profile, created = UserProfile.objects.get_or_create(
            user=user, defaults={'name': user.username})

        # There should be more variables, but let's settle on the actual model first.
        full_name = attr.find(CAS + 'fullName', NSMAP)
        if full_name is not None:
            user_profile.name = full_name.text or ''

        user_profile.save()

        # Now the really fun bit. Signing the user up for courses given.
        coursetag = attr.find(CAS + 'courses', NSMAP)

        from student.models import CourseEnrollment
        from opaque_keys.edx.locator import CourseLocator
        from opaque_keys import InvalidKeyError
        from xmodule.modulestore.django import modulestore
        from xmodule.modulestore.exceptions import ItemNotFoundError

        if coursetag is not None:
            try:
                courses = json.loads(coursetag.text)
                assert isinstance(courses, list)
            except (ValueError, AssertionError):
                # We failed to parse the tag and get a list, so we leave.
                log.error("Course list failed to parse.")
                return

            # We got a list. Compare it to existing enrollments.
            existing_enrollments = CourseEnrollment.objects.filter(
                user=user, is_active=True).values_list('course_id', flat=True)

            for course in courses:
                if course and not course in existing_enrollments:
                    try:
                        locator = CourseLocator.from_string(course)
                    except (InvalidKeyError, AttributeError) as e:
                        log.error(
                            "Invalid course identifier {}".format(course))
                        continue
                    try:
                        course = modulestore().get_course(locator)
                    except ItemNotFoundError:
                        log.error("Course {} does not exist.".format(course))
                        continue
                    CourseEnrollment.enroll(user, locator)
            # Now we need to unsub the user from courses for which they are not enrolled.
            for course in existing_enrollments:
                if not course in courses:
                    try:
                        locator = CourseLocator.from_string(course)
                    except (InvalidKeyError, AttributeError) as e:
                        log.error(
                            "Invalid course identifier {} in existing enrollments."
                            .format(course))
                        continue
                    CourseEnrollment.unenroll(user, locator)

        # Now implement CourseEnrollmentAllowed objects, because otherwise they will only ever fire when
        # users click a link in the registration email -- which can never happen here.
        # Considering the new setup, I doubt this will ever be useful.
        if created:
            from student.models import CourseEnrollmentAllowed
            for cea in CourseEnrollmentAllowed.objects.filter(
                    email=user.email, auto_enroll=True):
                CourseEnrollment.enroll(user, cea.course_id)

        # Now, deal with course administration packets.
        course_admin_tag = attr.find(CAS + 'course_administration_update',
                                     NSMAP)

        if course_admin_tag is not None:
            try:
                courses = json.loads(course_admin_tag.text)
                assert isinstance(courses, dict)
            except (ValueError, AssertionError):
                # We failed to parse the tag, so we leave.
                log.error(
                    "Could not parse course administration block: <<{}>>".
                    format(course_admin_tag.text))
                return

            from instructor.access import list_with_level, allow_access, revoke_access
            from django_comment_common.models import Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA
            from django.contrib.auth.models import User

            for course_id, admin_block in courses.iteritems():
                try:
                    locator = CourseLocator.from_string(course_id)
                except (InvalidKeyError, AttributeError) as e:
                    log.error("Invalid course identifier {}".format(course_id))
                    continue
                try:
                    course = modulestore().get_course(locator)
                except ItemNotFoundError:
                    log.error("Course {} does not exist.".format(course_id))
                    continue

                if not course:
                    continue

                # Course roles are relatively easy.
                for block_name, role in [('admin', 'instructor'),
                                         ('staff', 'staff'), ('beta', 'beta')]:
                    role_list = admin_block.get(block_name, [])
                    existing = list_with_level(course, role)

                    for username in role_list:
                        try:
                            user = User.objects.get(username=username)
                        except User.DoesNotExist:
                            continue
                        if not user in existing:
                            allow_access(course, user, role)
                            try:
                                CourseEnrollment.enroll(user, locator)
                            except:
                                pass
                    for user in existing:
                        if not user.username in role_list:
                            revoke_access(course, user, role)

                # Forum roles, considerably different.

                for block_name, rolename in [
                    ('forum_admin', FORUM_ROLE_ADMINISTRATOR),
                    ('forum_moderator', FORUM_ROLE_MODERATOR),
                    ('forum_assistant', FORUM_ROLE_COMMUNITY_TA)
                ]:
                    role_list = admin_block.get(block_name, [])
                    try:
                        role = Role.objects.get(course_id=locator,
                                                name=rolename)
                    except Role.DoesNotExist:
                        continue
                    existing = role.users.all()

                    for user in existing:
                        if not user.username in role_list:
                            role.users.remove(user)
                    for username in role_list:
                        try:
                            user = User.objects.get(username=username)
                        except User.DoesNotExist:
                            continue
                        if not user in existing:
                            role.users.add(user)
                            try:
                                CourseEnrollment.enroll(user, locator)
                            except:
                                pass

    pass
Ejemplo n.º 18
0
def populate_user(user, authentication_response):

    attr = authentication_response.find(CAS + 'authenticationSuccess/'  + CAS + 'attributes'  , namespaces=NSMAP)

    if attr is not None:

        staff_flag = attr.find(CAS + 'is_staff', NSMAP)
        if staff_flag is not None:
            user.is_staff = (staff_flag.text or '').upper() == 'TRUE'

        superuser_flag = attr.find(CAS + 'is_superuser', NSMAP)
        if superuser_flag is not None:
            user.is_superuser = (superuser_flag.text or '').upper() == 'TRUE'

        active_flag = attr.find(CAS + 'is_active', NSMAP)
        if active_flag is not None:
            user.is_active = (active_flag.text or '').upper() == 'TRUE'

        # Limiting by maximum lengths.
        # Max length of firstname/lastname is 30.
        # Max length of a email is 75.

        first_name = attr.find(CAS + 'givenName', NSMAP)
        if first_name is not None:
            user.first_name = (first_name.text or '')[0:30]

        last_name = attr.find(CAS + 'sn', NSMAP)
        if last_name is not None:
            user.last_name = (last_name.text or '')[0:30]

        email = attr.find(CAS + 'email', NSMAP)
        if email is not None:
            user.email = (email.text or '')[0:75]

        # Here we handle things that go into UserProfile instead.

        # This is a dirty hack and you shouldn't do that.
        # However, I don't think it's going to work when imported outside of the function body.

        from student.models import UserProfile

        # Make the user's password unusable. But only if they don't have an unusable password already,
        # to prevent SessionAuthenticationMiddleware from logging them out because their password changed.
        if user.has_usable_password():
            user.set_unusable_password()
        user.save()

        # If the user doesn't yet have a profile, it means it's a new one and we need to create it a profile.
        # but we need to save the user first.
        user_profile, created = UserProfile.objects.get_or_create(user=user, defaults={'name':user.username})

        # There should be more variables, but let's settle on the actual model first.
        full_name = attr.find(CAS + 'fullName', NSMAP)
        if full_name is not None:
            user_profile.name = full_name.text or ''

        user_profile.save()

        # Now the really fun bit. Signing the user up for courses given.
        coursetag = attr.find(CAS + 'courses', NSMAP)

        from student.models import CourseEnrollment
        from opaque_keys.edx.locator import CourseLocator
        from opaque_keys import InvalidKeyError
        from xmodule.modulestore.django import modulestore
        from xmodule.modulestore.exceptions import ItemNotFoundError

        if coursetag is not None:
            try:
                courses = json.loads(coursetag.text)
                assert isinstance(courses,list)
            except (ValueError, AssertionError):
                # We failed to parse the tag and get a list, so we leave.
                log.error("Course list failed to parse.")
                return

            # We got a list. Compare it to existing enrollments.
            existing_enrollments = CourseEnrollment.objects.filter(user=user, is_active=True).values_list('course_id',flat=True)

            for course in courses:
                if course and not course in existing_enrollments:
                    try:
                        locator = CourseLocator.from_string(course)
                    except (InvalidKeyError, AttributeError) as e:
                        log.error("Invalid course identifier {}".format(course))
                        continue
                    try:
                        course = modulestore().get_course(locator)
                    except ItemNotFoundError:
                        log.error("Course {} does not exist.".format(course))
                        continue
                    CourseEnrollment.enroll(user,locator)
            # Now we need to unsub the user from courses for which they are not enrolled.
            for course in existing_enrollments:
                if not course in courses:
                    try:
                        locator = CourseLocator.from_string(course)
                    except (InvalidKeyError, AttributeError) as e:
                        log.error("Invalid course identifier {} in existing enrollments.".format(course))
                        continue
                    CourseEnrollment.unenroll(user, locator)

        # Now implement CourseEnrollmentAllowed objects, because otherwise they will only ever fire when
        # users click a link in the registration email -- which can never happen here.
        # Considering the new setup, I doubt this will ever be useful.
        if created:
            from student.models import CourseEnrollmentAllowed
            for cea in CourseEnrollmentAllowed.objects.filter(email=user.email, auto_enroll=True):
                    CourseEnrollment.enroll(user, cea.course_id)

        # Now, deal with course administration packets.
        course_admin_tag = attr.find(CAS + 'course_administration_update', NSMAP)

        if course_admin_tag is not None:
            try:
                courses = json.loads(course_admin_tag.text)
                assert isinstance(courses,dict)
            except (ValueError, AssertionError):
                # We failed to parse the tag, so we leave.
                log.error("Could not parse course administration block: <<{}>>".format(course_admin_tag.text))
                return

            from instructor.access import list_with_level, allow_access, revoke_access
            from django_comment_common.models import Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA
            from django.contrib.auth.models import User

            for course_id, admin_block in courses.iteritems():
                try:
                    locator = CourseLocator.from_string(course_id)
                except (InvalidKeyError, AttributeError) as e:
                    log.error("Invalid course identifier {}".format(course_id))
                    continue
                try:
                    course = modulestore().get_course(locator)
                except ItemNotFoundError:
                    log.error("Course {} does not exist.".format(course_id))
                    continue

                if not course:
                    continue

                # Course roles are relatively easy.
                for block_name, role in [('admin','instructor'), ('staff','staff'), ('beta','beta')]:
                    role_list = admin_block.get(block_name,[])
                    existing = list_with_level(course,role)

                    for username in role_list:
                        try:
                            user = User.objects.get(username=username)
                        except User.DoesNotExist:
                            continue
                        if not user in existing:
                            allow_access(course, user, role)
                            try:
                                CourseEnrollment.enroll(user, locator)
                            except:
                                pass
                    for user in existing:
                        if not user.username in role_list:
                            revoke_access(course, user, role)

                # Forum roles, considerably different.

                for block_name, rolename in [('forum_admin',FORUM_ROLE_ADMINISTRATOR), ('forum_moderator',FORUM_ROLE_MODERATOR), ('forum_assistant',FORUM_ROLE_COMMUNITY_TA)]:
                    role_list = admin_block.get(block_name,[])
                    try:
                        role = Role.objects.get(course_id=locator, name=rolename)
                    except Role.DoesNotExist:
                        continue
                    existing = role.users.all()

                    for user in existing:
                        if not user.username in role_list:
                            role.users.remove(user)
                    for username in role_list:
                        try:
                            user = User.objects.get(username=username)
                        except User.DoesNotExist:
                            continue
                        if not user in existing:
                            role.users.add(user)
                            try:
                                CourseEnrollment.enroll(user, locator)
                            except:
                                pass

    pass
Ejemplo n.º 19
0
 def test_allow_beta(self):
     """ Test allow beta against list beta. """
     user = UserFactory()
     allow_access(self.course, user, 'beta')
     self.assertIn(user, list_with_level(self.course, 'beta'))