Example #1
0
def delete_course_and_groups(course_id, commit=False):
    """
    This deletes the courseware associated with a course_id as well as cleaning update_item
    the various user table stuff (groups, permissions, etc.)
    """
    module_store = modulestore('direct')
    content_store = contentstore()

    org, course_num, _ = course_id.split("/")
    module_store.ignore_write_events_on_courses.append('{0}/{1}'.format(
        org, course_num))

    loc = CourseDescriptor.id_to_location(course_id)
    if delete_course(module_store, content_store, loc, commit):
        print 'removing forums permissions and roles...'
        unseed_permissions_roles(course_id)

        print 'removing User permissions from course....'
        # in the django layer, we need to remove all the user permissions groups associated with this course
        if commit:
            try:
                staff_role = CourseStaffRole(loc)
                staff_role.remove_users(*staff_role.users_with_role())
                instructor_role = CourseInstructorRole(loc)
                instructor_role.remove_users(
                    *instructor_role.users_with_role())
            except Exception as err:
                log.error(
                    "Error in deleting course groups for {0}: {1}".format(
                        loc, err))
Example #2
0
def delete_course_and_groups(course_id, commit=False):
    """
    This deletes the courseware associated with a course_id as well as cleaning update_item
    the various user table stuff (groups, permissions, etc.)
    """
    module_store = modulestore('direct')
    content_store = contentstore()

    course_id_dict = Location.parse_course_id(course_id)
    module_store.ignore_write_events_on_courses.append('{org}/{course}'.format(**course_id_dict))

    loc = CourseDescriptor.id_to_location(course_id)
    if delete_course(module_store, content_store, loc, commit):

        print 'removing User permissions from course....'
        # in the django layer, we need to remove all the user permissions groups associated with this course
        if commit:
            try:
                staff_role = CourseStaffRole(loc)
                staff_role.remove_users(*staff_role.users_with_role())
                instructor_role = CourseInstructorRole(loc)
                instructor_role.remove_users(*instructor_role.users_with_role())
            except Exception as err:
                log.error("Error in deleting course groups for {0}: {1}".format(loc, err))

            # remove location of this course from loc_mapper and cache
            loc_mapper().delete_course_mapping(loc)
    def test_transcript_delete_handler(self, is_staff, is_course_staff):
        """
        Tests that transcript delete handler works as expected with combinations of staff and course's staff.
        """
        # Setup user's roles
        self.user.is_staff = is_staff
        self.user.save()
        course_staff_role = CourseStaffRole(self.course.id)
        if is_course_staff:
            course_staff_role.add_users(self.user)
        else:
            course_staff_role.remove_users(self.user)

        # Assert the user role
        self.assertEqual(self.user.is_staff, is_staff)
        self.assertEqual(CourseStaffRole(self.course.id).has_user(self.user), is_course_staff)

        video_id, language_code = u'1234', u'en'
        # Create a real transcript in VAL.
        api.create_or_update_video_transcript(
            video_id=video_id,
            language_code=language_code,
            metadata={'file_format': 'srt'}
        )

        # Make request to transcript deletion handler
        response = self.client.delete(self.get_url_for_course_key(
            self.course.id,
            edx_video_id=video_id,
            language_code=language_code
        ))
        self.assertEqual(response.status_code, 200)
        self.assertFalse(api.get_video_transcript_data(video_id=video_id, language_code=language_code))
Example #4
0
 def test_get_user_for_role(self):
     """
     test users_for_role
     """
     role = CourseStaffRole(self.course_key)
     role.add_users(self.student)
     self.assertGreater(len(role.users_with_role()), 0)
Example #5
0
def remove_all_instructors(course_key):
    """
    Removes all instructor and staff users from the given course.
    """
    staff_role = CourseStaffRole(course_key)
    staff_role.remove_users(*staff_role.users_with_role())
    instructor_role = CourseInstructorRole(course_key)
    instructor_role.remove_users(*instructor_role.users_with_role())
    def make_staff(self):
        """
        create staff user
        """
        staff = AdminFactory.create(password="******")
        role = CourseStaffRole(self.course.id)
        role.add_users(staff)

        return staff
Example #7
0
def remove_all_instructors(course_key):
    """
    Removes given user as instructor and staff to the given course,
    after verifying that the requesting_user has permission to do so.
    """
    staff_role = CourseStaffRole(course_key)
    staff_role.remove_users(*staff_role.users_with_role())
    instructor_role = CourseInstructorRole(course_key)
    instructor_role.remove_users(*instructor_role.users_with_role())
Example #8
0
 def test_add_users_doesnt_add_duplicate_entry(self):
     """
     Tests that calling add_users multiple times before a single call
     to remove_users does not result in the user remaining in the group.
     """
     role = CourseStaffRole(self.course_key)
     role.add_users(self.student)
     self.assertTrue(role.has_user(self.student))
     # Call add_users a second time, then remove just once.
     role.add_users(self.student)
     role.remove_users(self.student)
     self.assertFalse(role.has_user(self.student))
Example #9
0
def assign_staff_role_to_ccx(ccx_locator, user, master_course_id):
    """
    Check if user has ccx_coach role on master course then assign him staff role on ccx only
    if role is not already assigned. Because of this coach can open dashboard from master course
    as well as ccx.
    :param ccx_locator: CCX key
    :param user: User to whom we want to assign role.
    :param master_course_id: Master course key
    """
    coach_role_on_master_course = CourseCcxCoachRole(master_course_id)
    # check if user has coach role on master course
    if coach_role_on_master_course.has_user(user):
        # Check if user has staff role on ccx.
        role = CourseStaffRole(ccx_locator)
        if not role.has_user(user):
            # assign user the staff role on ccx
            with ccx_course(ccx_locator) as course:
                allow_access(course, user, "staff", send_email=False)
Example #10
0
def delete_course_and_groups(course_id, user_id):
    """
    This deletes the courseware associated with a course_id as well as cleaning update_item
    the various user table stuff (groups, permissions, etc.)
    """
    module_store = modulestore()

    with module_store.bulk_write_operations(course_id):
        module_store.delete_course(course_id, user_id)

        print 'removing User permissions from course....'
        # in the django layer, we need to remove all the user permissions groups associated with this course
        try:
            staff_role = CourseStaffRole(course_id)
            staff_role.remove_users(*staff_role.users_with_role())
            instructor_role = CourseInstructorRole(course_id)
            instructor_role.remove_users(*instructor_role.users_with_role())
        except Exception as err:
            log.error("Error in deleting course groups for {0}: {1}".format(course_id, err))
Example #11
0
def delete_course_and_groups(course_id, commit=False):
    """
    This deletes the courseware associated with a course_id as well as cleaning update_item
    the various user table stuff (groups, permissions, etc.)
    """
    module_store = modulestore('direct')
    content_store = contentstore()

    module_store.ignore_write_events_on_courses.add(course_id)

    if delete_course(module_store, content_store, course_id, commit):

        print 'removing User permissions from course....'
        # in the django layer, we need to remove all the user permissions groups associated with this course
        if commit:
            try:
                staff_role = CourseStaffRole(course_id)
                staff_role.remove_users(*staff_role.users_with_role())
                instructor_role = CourseInstructorRole(course_id)
                instructor_role.remove_users(*instructor_role.users_with_role())
            except Exception as err:
                log.error("Error in deleting course groups for {0}: {1}".format(course_id, err))
    def create_staff_context(self):
        """
        Create staff user and course blocks accessible by that user
        """
        # Create a staff user to be able to test visible_to_staff_only
        staff_user = UserFactory.create()
        CourseStaffRole(self.course.location.course_key).add_users(staff_user)

        block_structure = get_course_blocks(
            staff_user,
            self.course.location,
            self.transformers,
        )
        return {
            'request': MagicMock(),
            'block_structure': block_structure,
            'requested_fields': ['type'],
        }
Example #13
0
    def setUp(self):
        clear_existing_modulestores()
        self.toy = modulestore().get_course(SlashSeparatedCourseKey("edX", "toy", "2012_Fall"))

        # Create two accounts
        self.student = '*****@*****.**'
        self.instructor = '*****@*****.**'
        self.password = '******'
        self.create_account('u1', self.student, self.password)
        self.create_account('u2', self.instructor, self.password)
        self.activate_user(self.student)
        self.activate_user(self.instructor)

        CourseStaffRole(self.toy.id).add_users(User.objects.get(email=self.instructor))

        self.logout()
        self.login(self.instructor, self.password)
        self.enroll(self.toy)
Example #14
0
    def test_render_html_view_with_preview_mode_when_user_already_has_cert(
            self):
        """
        test certificate web view should render properly in
        preview mode even if user who is previewing already has a certificate
        generated with different mode.
        """
        self._add_course_certificates(count=1, signatory_count=2)
        CourseStaffRole(self.course.id).add_users(self.user)

        test_url = get_certificate_url(user_id=self.user.id,
                                       course_id=unicode(self.course.id))
        # user has already has certificate generated for 'honor' mode
        # so let's try to preview in 'verified' mode.
        response = self.client.get(test_url + '?preview=verified')
        self.assertNotIn(self.course.display_name, response.content)
        self.assertIn('course_title_0', response.content)
        self.assertIn('Signatory_Title 0', response.content)
Example #15
0
    def setUp(self):
        """
        Set up tests
        """
        super(TestCoachDashboard, self).setUp()
        # Login with the instructor account
        self.client.login(username=self.coach.username, password="******")

        # adding staff to master course.
        staff = UserFactory()
        allow_access(self.course, staff, 'staff')
        self.assertTrue(CourseStaffRole(self.course.id).has_user(staff))

        # adding instructor to master course.
        instructor = UserFactory()
        allow_access(self.course, instructor, 'instructor')
        self.assertTrue(
            CourseInstructorRole(self.course.id).has_user(instructor))
Example #16
0
    def test_authorization_no_oauth_staff(self):
        """
        Check authorization for staff users logged in without oauth
        """
        # create a staff user
        staff_user = User.objects.create_user('test_staff_user',
                                              '*****@*****.**',
                                              'test')
        # add staff role to the staff user
        CourseStaffRole(self.master_course_key).add_users(staff_user)

        data = {'display_name': 'CCX Title'}
        # the staff user can perform the request
        self.client.login(username=staff_user.username, password='******')
        resp = self.client.get(self.detail_url)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        resp = self.client.patch(self.detail_url, data, format='json')
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
Example #17
0
def manage_library_users(request, library_key_string):
    """
    Studio UI for editing the users within a library.

    Uses the /course_team/:library_key/:user_email/ REST API to make changes.
    """
    library_key = CourseKey.from_string(library_key_string)
    if not isinstance(library_key, LibraryLocator):
        raise Http404  # This is not a library
    user_perms = get_user_permissions(request.user, library_key)
    if not user_perms & STUDIO_VIEW_USERS:
        raise PermissionDenied()
    library = modulestore().get_library(library_key)
    if library is None:
        raise Http404

    # Segment all the users explicitly associated with this library, ensuring each user only has one role listed:
    instructors = set(CourseInstructorRole(library_key).users_with_role())
    staff = set(CourseStaffRole(library_key).users_with_role()) - instructors
    users = set(
        LibraryUserRole(library_key).users_with_role()) - instructors - staff
    all_users = instructors | staff | users

    return render_to_response(
        'manage_users_lib.html', {
            'context_library':
            library,
            'staff':
            staff,
            'instructors':
            instructors,
            'users':
            users,
            'all_users':
            all_users,
            'allow_actions':
            bool(user_perms & STUDIO_EDIT_ROLES),
            'library_key':
            unicode(library_key),
            'lib_users_url':
            reverse_library_url('manage_library_users', library_key_string),
            'show_children_previews':
            library.show_children_previews
        })
Example #18
0
def _has_access_to_course(user, access_level, course_key):
    """
    Returns True if the given user has access_level (= staff or
    instructor) access to the course with the given course_key.
    This ensures the user is authenticated and checks if global staff or has
    staff / instructor access.

    access_level = string, either "staff" or "instructor"
    """
    if user is None or (not user.is_authenticated()):
        debug("Deny: no user or anon user")
        return ACCESS_DENIED

    if is_masquerading_as_student(user, course_key):
        return ACCESS_DENIED

    if GlobalStaff().has_user(user):
        debug("Allow: user.is_staff")
        return ACCESS_GRANTED

    if access_level not in ('staff', 'instructor'):
        log.debug("Error in access._has_access_to_course access_level=%s unknown", access_level)
        debug("Deny: unknown access level")
        return ACCESS_DENIED

    staff_access = (
        CourseStaffRole(course_key).has_user(user) or
        OrgStaffRole(course_key.org).has_user(user)
    )
    if staff_access and access_level == 'staff':
        debug("Allow: user has course staff access")
        return ACCESS_GRANTED

    instructor_access = (
        CourseInstructorRole(course_key).has_user(user) or
        OrgInstructorRole(course_key.org).has_user(user)
    )

    if instructor_access and access_level in ('staff', 'instructor'):
        debug("Allow: user has course instructor access")
        return ACCESS_GRANTED

    debug("Deny: user did not have correct access")
    return ACCESS_DENIED
Example #19
0
    def get(self, request):
        """Displays course Enrollment and staffing course statistics"""

        if not request.user.is_staff:
            raise Http404
        data = []

        courses = self.get_courses()

        for (cdir, course) in courses.items():  # pylint: disable=unused-variable
            datum = [course.display_name, course.id]
            datum += [
                CourseEnrollment.objects.filter(course_id=course.id).count()
            ]
            datum += [
                CourseStaffRole(course.location).users_with_role().count()
            ]
            datum += [
                ','.join([
                    x.username for x in CourseInstructorRole(
                        course.location).users_with_role()
                ])
            ]
            data.append(datum)

        datatable = dict(header=[
            _('Course Name'),
            _('course_id'),
            _('# enrolled'),
            _('# staff'),
            _('instructors')
        ],
                         title=_('Enrollment information for all courses'),
                         data=data)
        context = {
            'datatable': datatable,
            'msg': self.msg,
            'djangopid': os.getpid(),
            'modeflag': {
                'staffing': 'active-section'
            },
            'mitx_version': getattr(settings, 'VERSION_STRING', ''),
        }
        return render_to_response(self.template_name, context)
    def test_data(self):
        start = datetime.datetime.now(pytz.UTC)
        end = start + datetime.timedelta(days=30)
        enrollment_start = start - datetime.timedelta(days=7)
        enrollment_end = end - datetime.timedelta(days=14)

        course = CourseFactory(start=start,
                               end=end,
                               enrollment_start=enrollment_start,
                               enrollment_end=enrollment_end)
        instructor = UserFactory()
        CourseInstructorRole(course.id).add_users(instructor)
        staff = UserFactory()
        CourseStaffRole(course.id).add_users(staff)

        request = RequestFactory().get('')
        serializer = CourseRunSerializer(course, context={'request': request})
        expected = {
            'id':
            str(course.id),
            'title':
            course.display_name,
            'schedule': {
                'start': serialize_datetime(start),
                'end': serialize_datetime(end),
                'enrollment_start': serialize_datetime(enrollment_start),
                'enrollment_end': serialize_datetime(enrollment_end),
            },
            'team': [
                {
                    'user': instructor.username,
                    'role': 'instructor',
                },
                {
                    'user': staff.username,
                    'role': 'staff',
                },
            ],
            'images': {
                'card_image':
                request.build_absolute_uri(course_image_url(course)),
            }
        }
        assert serializer.data == expected
Example #21
0
    def test_remove_master_course_staff_from_ccx_no_email(self):
        """
        Test remove role of staff of master course on ccx course without
        sending enrollment email.
        """
        staff = self.make_staff()
        self.assertTrue(CourseStaffRole(self.course.id).has_user(staff))

        # adding instructor to master course.
        instructor = self.make_instructor()
        self.assertTrue(
            CourseInstructorRole(self.course.id).has_user(instructor))
        outbox = self.get_outbox()
        self.assertEqual(len(outbox), 0)
        remove_master_course_staff_from_ccx(self.course,
                                            self.ccx_locator,
                                            self.ccx.display_name,
                                            send_email=False)
        self.assertEqual(len(outbox), 0)
    def test_add_master_course_staff_to_ccx_idempotent(self):
        """
        Test add staff of master course to ccx course multiple time will
        not result in multiple enrollments.
        """
        staff = self.make_staff()
        self.assertTrue(CourseStaffRole(self.course.id).has_user(staff))

        # adding instructor to master course.
        instructor = self.make_instructor()
        self.assertTrue(CourseInstructorRole(self.course.id).has_user(instructor))
        outbox = self.get_outbox()
        list_staff_master_course = list_with_level(self.course, 'staff')
        list_instructor_master_course = list_with_level(self.course, 'instructor')
        self.assertEqual(len(outbox), 0)

        # run the assignment the first time
        add_master_course_staff_to_ccx(self.course, self.ccx_locator, self.ccx.display_name)
        self.assertEqual(len(outbox), len(list_staff_master_course) + len(list_instructor_master_course))
        with ccx_course(self.ccx_locator) 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 user in list_staff_master_course:
            self.assertIn(user, list_staff_ccx_course)
        self.assertEqual(len(list_instructor_master_course), len(list_instructor_ccx_course))
        for user in list_instructor_master_course:
            self.assertIn(user, list_instructor_ccx_course)

        # run the assignment again
        add_master_course_staff_to_ccx(self.course, self.ccx_locator, self.ccx.display_name)
        # there are no new duplicated email
        self.assertEqual(len(outbox), len(list_staff_master_course) + len(list_instructor_master_course))
        # there are no duplicated staffs
        with ccx_course(self.ccx_locator) 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 user in list_staff_master_course:
            self.assertIn(user, list_staff_ccx_course)
        self.assertEqual(len(list_instructor_master_course), len(list_instructor_ccx_course))
        for user in list_instructor_master_course:
            self.assertIn(user, list_instructor_ccx_course)
Example #23
0
def _get_recipient_queryset(user_id, to_option, course_id):
    """
    Returns a query set of email recipients corresponding to the requested to_option category.

    `to_option` is either SEND_TO_MYSELF, SEND_TO_STAFF, or SEND_TO_ALL.

    Recipients who are in more than one category (e.g. enrolled in the course and are staff or self)
    will be properly deduped.
    """
    if to_option not in TO_OPTIONS:
        log.error("Unexpected bulk email TO_OPTION found: %s", to_option)
        raise Exception(
            "Unexpected bulk email TO_OPTION found: {0}".format(to_option))

    if to_option == SEND_TO_MYSELF:
        recipient_qset = User.objects.filter(id=user_id)
    else:
        staff_qset = CourseStaffRole(course_id).users_with_role()
        instructor_qset = CourseInstructorRole(course_id).users_with_role()
        recipient_qset = (staff_qset | instructor_qset).distinct()
        if to_option == SEND_TO_ALL:
            # We also require students to have activated their accounts to
            # provide verification that the provided email address is valid.
            enrollment_qset = User.objects.filter(
                is_active=True,
                courseenrollment__course_id=course_id,
                courseenrollment__is_active=True)
            # Now we do some queryset sidestepping to avoid doing a DISTINCT
            # query across the course staff and the enrolled students, which
            # forces the creation of a temporary table in the db.
            unenrolled_staff_qset = recipient_qset.exclude(
                courseenrollment__course_id=course_id,
                courseenrollment__is_active=True)
            # use read_replica if available:
            unenrolled_staff_qset = use_read_replica_if_available(
                unenrolled_staff_qset)

            unenrolled_staff_ids = [user.id for user in unenrolled_staff_qset]
            recipient_qset = enrollment_qset | User.objects.filter(
                id__in=unenrolled_staff_ids)

    # again, use read_replica if available to lighten the load for large queries
    return use_read_replica_if_available(recipient_qset)
Example #24
0
    def setUp(self):
        super(TestStaffOnCCX, self).setUp()

        # Create instructor account
        self.client.login(username=self.coach.username, password="******")

        # create an instance of modulestore
        self.mstore = modulestore()

        # adding staff to master course.
        staff = UserFactory()
        allow_access(self.course, staff, 'staff')
        self.assertTrue(CourseStaffRole(self.course.id).has_user(staff))

        # adding instructor to master course.
        instructor = UserFactory()
        allow_access(self.course, instructor, 'instructor')
        self.assertTrue(
            CourseInstructorRole(self.course.id).has_user(instructor))
Example #25
0
    def setUp(self):
        """
        Add courses with the end date set to various values
        """
        super(TestCourseIndexArchived, self).setUp()

        # Base course has no end date (so is active)
        self.course.end = None
        self.course.display_name = 'Active Course 1'
        self.ORG = self.course.location.org
        self.save_course()

        # Active course has end date set to tomorrow
        self.active_course = CourseFactory.create(
            display_name='Active Course 2',
            org=self.ORG,
            end=self.TOMORROW,
        )

        # Archived course has end date set to yesterday
        self.archived_course = CourseFactory.create(
            display_name='Archived Course',
            org=self.ORG,
            end=self.YESTERDAY,
        )

        # Base user has global staff access
        self.assertTrue(GlobalStaff().has_user(self.user))

        # Staff user just has course staff access
        self.staff, self.staff_password = self.create_non_staff_user()
        for course in (self.course, self.active_course, self.archived_course):
            CourseStaffRole(course.id).add_users(self.staff)

        # Make sure we've cached data which could change the query counts
        # depending on test execution order
        WaffleSwitchNamespace(name=COURSE_WAFFLE_NAMESPACE).is_enabled(
            u'enable_global_staff_optimization')
        WaffleSwitchNamespace(
            name=STUDIO_WAFFLE_NAMESPACE).is_enabled(u'enable_policy_page')
        WaffleSwitchNamespace(name=DJANGO_UTILS_NAMESPACE).is_enabled(
            u'enable_memory_middleware')
Example #26
0
    def setUpClass(cls):
        super(TeamAccessTests, cls).setUpClass()
        cls.user_audit = UserFactory.create(username='******')
        cls.user_staff = UserFactory.create(username='******')
        cls.user_masters = UserFactory.create(username='******')
        cls.user_unenrolled = UserFactory.create(username='******')
        cls.users = {
            'user_audit': cls.user_audit,
            'user_staff': cls.user_staff,
            'user_masters': cls.user_masters,
            'user_unenrolled': cls.user_unenrolled,
        }

        for user in (cls.user_audit, cls.user_staff):
            CourseEnrollmentFactory.create(user=user, course_id=COURSE_KEY1)
        CourseEnrollmentFactory.create(user=cls.user_masters,
                                       course_id=COURSE_KEY1,
                                       mode=CourseMode.MASTERS)

        CourseStaffRole(COURSE_KEY1).add_users(cls.user_staff)

        cls.topic_id = 'RANDOM TOPIC'
        cls.team_unprotected_1 = CourseTeamFactory(
            course_id=COURSE_KEY1,
            topic_id=cls.topic_id,
            team_id='team_unprotected_1')
        cls.team_unprotected_2 = CourseTeamFactory(
            course_id=COURSE_KEY1,
            topic_id=cls.topic_id,
            team_id='team_unprotected_2')
        cls.team_unprotected_3 = CourseTeamFactory(
            course_id=COURSE_KEY1,
            topic_id=cls.topic_id,
            team_id='team_unprotected_3')
        cls.team_protected_1 = CourseTeamFactory(course_id=COURSE_KEY1,
                                                 team_id='team_protected_1',
                                                 topic_id=cls.topic_id,
                                                 organization_protected=True)
        cls.team_protected_2 = CourseTeamFactory(course_id=COURSE_KEY1,
                                                 team_id='team_protected_2',
                                                 topic_id=cls.topic_id,
                                                 organization_protected=True)
Example #27
0
    def setUp(self):
        super(TestEolCourseEmailView, self).setUp()
        # create a course
        self.course = CourseFactory.create(org='mss',
                                           course='999',
                                           display_name='eol course email')

        # Create users, enroll
        self.users = [UserFactory.create() for _ in range(USER_COUNT)]
        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        # Patch the comment client user save method so it does not try
        # to create a new cc user when creating a django user
        with patch('student.models.cc.User.save'):
            # Create the student
            self.student = UserFactory(username='******',
                                       password='******',
                                       email='*****@*****.**')
            # Enroll the student in the course
            CourseEnrollmentFactory(user=self.student,
                                    course_id=self.course.id)

            # Create and Enroll staff user
            self.staff_user = UserFactory(username='******',
                                          password='******',
                                          email='*****@*****.**',
                                          is_staff=True)
            CourseEnrollmentFactory(user=self.staff_user,
                                    course_id=self.course.id)
            CourseStaffRole(self.course.id).add_users(self.staff_user)

            # Log the student in
            self.client = Client()
            self.assertTrue(
                self.client.login(username='******', password='******'))

            # Log the user staff in
            self.staff_client = Client()
            self.assertTrue(
                self.staff_client.login(username='******',
                                        password='******'))
Example #28
0
    def test_staff_csv(self):
        """Download and validate staff CSV"""

        self._setstaff_login()
        self._add_edx4edx()

        def_ms = modulestore()
        course = def_ms.get_course(SlashSeparatedCourseKey('MITx', 'edx4edx', 'edx4edx'))
        CourseStaffRole(course.id).add_users(self.user)

        response = self.client.post(reverse('sysadmin_staffing'),
                                    {'action': 'get_staff_csv', })
        self.assertIn('attachment', response['Content-Disposition'])
        self.assertEqual('text/csv', response['Content-Type'])
        columns = [_('course_id'), _('role'), _('username'),
                   _('email'), _('full_name'), ]
        self.assertIn(','.join('"' + c + '"' for c in columns),
                      response.content)

        self._rm_edx4edx()
Example #29
0
    def setUp(self):
        self.toy = CourseFactory.create(org='edX',
                                        course='toy',
                                        display_name='2012_Fall')

        # Create two accounts
        self.student = '*****@*****.**'
        self.instructor = '*****@*****.**'
        self.password = '******'
        self.create_account('u1', self.student, self.password)
        self.create_account('u2', self.instructor, self.password)
        self.activate_user(self.student)
        self.activate_user(self.instructor)

        CourseStaffRole(self.toy.id).add_users(
            User.objects.get(email=self.instructor))

        self.logout()
        self.login(self.instructor, self.password)
        self.enroll(self.toy)
Example #30
0
    def test_course_staff_courses_with_claims(self):
        CourseStaffRole(self.course_key).add_users(self.user)

        course_id = unicode(self.course_key)
        nonexistent_course_id = 'some/other/course'

        claims = {
            'staff_courses': {
                'values': [course_id, nonexistent_course_id],
                'essential': True,
            }
        }

        scopes, claims = self.get_id_token_values(scope='openid course_staff', claims=claims)

        self.assertIn('course_staff', scopes)
        self.assertIn('staff_courses', claims)
        self.assertEqual(len(claims['staff_courses']), 1)
        self.assertIn(course_id, claims['staff_courses'])
        self.assertNotIn(nonexistent_course_id, claims['staff_courses'])
Example #31
0
    def setUp(self):
        """
        Set up a simple course for testing basic grading functionality.
        """
        super(TestRawGradeCSV, self).setUp()

        self.instructor = '*****@*****.**'
        self.student_user2 = self.create_account('u2', self.instructor, self.password)
        self.activate_user(self.instructor)
        CourseStaffRole(self.course.id).add_users(User.objects.get(email=self.instructor))
        self.logout()
        self.login(self.instructor, self.password)
        self.enroll(self.course)

        # set up a simple course with four problems
        self.homework = self.add_graded_section_to_course('homework', late=False, reset=False, showanswer=False)
        self.add_dropdown_to_section(self.homework.location, 'p1', 1)
        self.add_dropdown_to_section(self.homework.location, 'p2', 1)
        self.add_dropdown_to_section(self.homework.location, 'p3', 1)
        self.refresh_course()
Example #32
0
    def test_access_course_team_users(self):
        """
        Test that members of the course team do not lose access to graded content
        """
        # There are two types of course team members: instructor and staff
        # they have different privileges, but for the purpose of this test the important thing is that they should both
        # have access to all graded content
        instructor = UserFactory.create()
        CourseInstructorRole(self.course.id).add_users(instructor)
        staff = UserFactory.create()
        CourseStaffRole(self.course.id).add_users(staff)

        # assert that all course team members have access to graded content
        for course_team_member in [instructor, staff]:
            self._assert_block_is_gated(
                block=self.blocks_dict['problem'],
                user_id=course_team_member.id,
                course=self.course,
                is_gated=False
            )
Example #33
0
def has_team_api_access(user, course_key, access_username=None):
    """Returns True if the user has access to the Team API for the course
    given by `course_key`. The user must either be enrolled in the course,
    be course staff, or be global staff.

    Args:
      user (User): The user to check access for.
      course_key (CourseKey): The key to the course which we are checking access to.
      access_username (string): If provided, access_username must match user.username for non staff access.

    Returns:
      bool: True if the user has access, False otherwise.
    """
    if user.is_staff:
        return True
    if CourseStaffRole(course_key).has_user(user):
        return True
    if not access_username or access_username == user.username:
        return CourseEnrollment.is_enrolled(user, course_key)
    return False
Example #34
0
def _manage_users(request, locator):
    """
    This view will return all CMS users who are editors for the specified course
    """
    old_location = loc_mapper().translate_locator_to_location(locator)

    # check that logged in user has permissions to this item
    if not has_course_access(request.user, locator):
        raise PermissionDenied()

    course_module = modulestore().get_item(old_location)
    instructors = CourseInstructorRole(locator).users_with_role()
    # the page only lists staff and assumes they're a superset of instructors. Do a union to ensure.
    staff = set(CourseStaffRole(locator).users_with_role()).union(instructors)
    return render_to_response('manage_users.html', {
        'context_course': course_module,
        'staff': staff,
        'instructors': instructors,
        'allow_actions': has_course_access(request.user, locator, role=CourseInstructorRole),
    })
Example #35
0
    def test_errored_course_regular_access(self):
        """
        Test the course list for regular staff when get_course returns an ErrorDescriptor
        """
        GlobalStaff().remove_users(self.user)
        CourseStaffRole(SlashSeparatedCourseKey('Non', 'Existent', 'Course')).add_users(self.user)

        course_key = SlashSeparatedCourseKey('Org1', 'Course1', 'Run1')
        self._create_course_with_access_groups(course_key, self.user)

        with patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', Mock(side_effect=Exception)):
            self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor)

            # get courses through iterating all courses
            courses_list, __ = _accessible_courses_list(self.request)
            self.assertEqual(courses_list, [])

            # get courses by reversing group name formats
            courses_list_by_groups, __ = _accessible_courses_list_from_groups(self.request)
            self.assertEqual(courses_list_by_groups, [])
            self.assertEqual(courses_list, courses_list_by_groups)
Example #36
0
 def has_permission(self, request, view):
     """
     This method is assuming that a `master_course_id` parameter
     is available in the request as a GET parameter, a POST parameter
     or it is in the JSON payload included in the request.
     The reason is because this permission class is going
     to check if the user making the request is an instructor
     for the specified course.
     """
     master_course_id = (request.GET.get('master_course_id')
                         or request.POST.get('master_course_id')
                         or request.data.get('master_course_id'))
     if master_course_id is not None:
         try:
             course_key = CourseKey.from_string(master_course_id)
         except InvalidKeyError:
             raise Http404()
         return (hasattr(request, 'user') and
                 (CourseInstructorRole(course_key).has_user(request.user)
                  or CourseStaffRole(course_key).has_user(request.user)))
     return False
Example #37
0
def get_num_enrolled_in_exclude_admins(course_id, date_for):
    """
    Copied over from CourseEnrollmentManager.num_enrolled_in_exclude_admins method
    and modified to filter on date LT

    """
    course_locator = course_id

    if getattr(course_id, 'ccx', None):
        course_locator = course_id.to_course_locator()

    staff = CourseStaffRole(course_locator).users_with_role()
    admins = CourseInstructorRole(course_locator).users_with_role()
    coaches = CourseCcxCoachRole(course_locator).users_with_role()

    return CourseEnrollment.objects.filter(
        course_id=course_id,
        is_active=1,
        created__lt=as_datetime(next_day(date_for)),
    ).exclude(user__in=staff).exclude(user__in=admins).exclude(
        user__in=coaches).count()
Example #38
0
    def test_authorization_no_oauth_staff(self):
        """
        Check authorization for staff users logged in without oauth
        """
        # create a staff user
        staff_user = User.objects.create_user('test_staff_user', '*****@*****.**', 'test')
        # add staff role to the staff user
        CourseStaffRole(self.master_course_key).add_users(staff_user)

        data = {
            'master_course_id': self.master_course_key_str,
            'max_students_allowed': 111,
            'display_name': 'CCX Test Title',
            'coach_email': self.coach.email
        }
        # the staff user can perform the request
        self.client.login(username=staff_user.username, password='******')
        resp = self.client.get(self.list_url_master_course)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        resp = self.client.post(self.list_url, data, format='json')
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
Example #39
0
def get_user_permissions(user, course_key, org=None):
    """
    Get the bitmask of permissions that this user has in the given course context.
    Can also set course_key=None and pass in an org to get the user's
    permissions for that organization as a whole.
    """
    if org is None:
        org = course_key.org
        course_key = course_key.for_branch(None)
    else:
        assert course_key is None
    # No one has studio permissions for CCX courses
    if is_ccx_course(course_key):
        return STUDIO_NO_PERMISSIONS
    all_perms = STUDIO_EDIT_ROLES | STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT
    # global staff, org instructors, and course instructors have all permissions:
    if GlobalStaff().has_user(user) or OrgInstructorRole(
            org=org).has_user(user):
        return all_perms
    if course_key and user_has_role(user, CourseInstructorRole(course_key)):
        return all_perms
    # Staff have all permissions except EDIT_ROLES:
    if OrgStaffRole(org=org).has_user(user) or (course_key and user_has_role(
            user, CourseStaffRole(course_key))):
        return STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT
    # Otherwise, for libraries, users can view only:
    if course_key and isinstance(course_key, LibraryLocator):
        if OrgLibraryUserRole(org=org).has_user(user) or user_has_role(
                user, LibraryUserRole(course_key)):
            return STUDIO_VIEW_USERS | STUDIO_VIEW_CONTENT
    # Finally, check if user is linked directly to the organization:
    user_org = OrganizationUser.objects.filter(
        active=True, organization__short_name=org,
        user_id=user.id).values().first()
    if user_org:
        if user_org['is_staff']:
            return all_perms
        else:
            return STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT
    return STUDIO_NO_PERMISSIONS
Example #40
0
 def test_enrollment_list_permissions(self):
     """
     Test that the correct list of enrollments is returned, depending on the permissions of the
     requesting user.
     """
     # Create another course, and enroll self.user in both courses.
     other_course = CourseFactory.create(emit_signals=True)
     for course in self.course, other_course:
         CourseModeFactory.create(
             course_id=unicode(course.id),
             mode_slug=CourseMode.DEFAULT_MODE_SLUG,
             mode_display_name=CourseMode.DEFAULT_MODE_SLUG,
         )
         self.assert_enrollment_status(
             course_id=unicode(course.id),
             max_mongo_calls=0,
         )
     # Verify the user himself can see both of his enrollments.
     self._assert_enrollments_visible_in_list([self.course, other_course])
     # Verify that self.other_user can't see any of the enrollments.
     self.client.login(username=self.OTHER_USERNAME, password=self.PASSWORD)
     self._assert_enrollments_visible_in_list([])
     # Create a staff user for self.course (but nor for other_course) and log her in.
     staff_user = UserFactory.create(username='******',
                                     email='*****@*****.**',
                                     password=self.PASSWORD)
     CourseStaffRole(self.course.id).add_users(staff_user)
     self.client.login(username='******', password=self.PASSWORD)
     # Verify that she can see only the enrollment in the course she has staff privileges for.
     self._assert_enrollments_visible_in_list([self.course])
     # Create a global staff user, and verify she can see all enrollments.
     AdminFactory(username='******',
                  email='*****@*****.**',
                  password=self.PASSWORD)
     self.client.login(username='******', password=self.PASSWORD)
     self._assert_enrollments_visible_in_list([self.course, other_course])
     # Verify the server can see all enrollments.
     self.client.logout()
     self._assert_enrollments_visible_in_list([self.course, other_course],
                                              use_server_key=True)
Example #41
0
    def get(self, request):
        """Gets a list of all course enrollments for a user.

        Returns a list for the currently logged in user, or for the user named by the 'user' GET
        parameter. If the username does not match that of the currently logged in user, only
        courses for which the currently logged in user has the Staff or Admin role are listed.
        As a result, a course team member can find out which of his or her own courses a particular
        learner is enrolled in.

        Only the Staff or Admin role (granted on the Django administrative console as the staff
        or instructor permission) in individual courses gives the requesting user access to
        enrollment data. Permissions granted at the organizational level do not give a user
        access to enrollment data for all of that organization's courses.

        Users who have the global staff permission can access all enrollment data for all
        courses.
        """
        username = request.GET.get('user', request.user.username)
        try:
            enrollment_data = api.get_enrollments(username)
            print enrollment_data
        except CourseEnrollmentError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    "message":
                    (u"An error occurred while retrieving enrollments for user '{username}'"
                     ).format(username=username)
                })
        if username == request.user.username or GlobalStaff().has_user(request.user) or \
                self.has_api_key_permissions(request):
            return Response(enrollment_data)
        filtered_data = []
        for enrollment in enrollment_data:
            course_key = CourseKey.from_string(
                enrollment["course_details"]["course_id"])
            if user_has_role(request.user, CourseStaffRole(course_key)):
                filtered_data.append(enrollment)
        return Response(filtered_data)
    def test_enrollment_limit(self):
        """
        Assert that in a course with max student limit set to 1, we can enroll staff and instructor along with
        student. To make sure course full check excludes staff and instructors.
        """
        self.assertEqual(self.course_limited.max_student_enrollments_allowed, 1)
        user1 = UserFactory.create(username="******", email="*****@*****.**", password="******")
        user2 = UserFactory.create(username="******", email="*****@*****.**", password="******")

        # create staff on course.
        staff = UserFactory.create(username="******", email="*****@*****.**", password="******")
        role = CourseStaffRole(self.course_limited.id)
        role.add_users(staff)

        # create instructor on course.
        instructor = UserFactory.create(username="******", email="*****@*****.**", password="******")
        role = CourseInstructorRole(self.course_limited.id)
        role.add_users(instructor)

        CourseEnrollment.enroll(staff, self.course_limited.id, check_access=True)
        CourseEnrollment.enroll(instructor, self.course_limited.id, check_access=True)

        self.assertTrue(
            CourseEnrollment.objects.filter(course_id=self.course_limited.id, user=staff).exists()
        )

        self.assertTrue(
            CourseEnrollment.objects.filter(course_id=self.course_limited.id, user=instructor).exists()
        )

        CourseEnrollment.enroll(user1, self.course_limited.id, check_access=True)
        self.assertTrue(
            CourseEnrollment.objects.filter(course_id=self.course_limited.id, user=user1).exists()
        )

        with self.assertRaises(CourseFullError):
            CourseEnrollment.enroll(user2, self.course_limited.id, check_access=True)

        self.assertFalse(
            CourseEnrollment.objects.filter(course_id=self.course_limited.id, user=user2).exists()
        )