Пример #1
0
def _get_recipient_queryset(user_id, to_option, course_id, course_location):
    """
    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_location).users_with_role()
        instructor_qset = CourseInstructorRole(
            course_location).users_with_role()
        recipient_qset = staff_qset | instructor_qset
        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)
            recipient_qset = recipient_qset | enrollment_qset
        recipient_qset = recipient_qset.distinct()

    recipient_qset = recipient_qset.order_by('pk')
    return recipient_qset
Пример #2
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('MITx/edx4edx/edx4edx')
        CourseStaffRole(course.location).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()
Пример #3
0
    def test_gitlog_courseteam_access(self):
        """
        Ensure course team users are allowed to access only their own course.
        """

        self._mkdir(getattr(settings, 'GIT_REPO_DIR'))

        self._setstaff_login()
        self._add_edx4edx()
        self.user.is_staff = False
        self.user.save()
        logged_in = self.client.login(username=self.user.username,
                                      password='******')
        response = self.client.get(reverse('gitlogs'))
        # Make sure our non privileged user doesn't have access to all logs
        self.assertEqual(response.status_code, 404)
        # Or specific logs
        response = self.client.get(
            reverse('gitlogs_detail',
                    kwargs={'course_id': 'MITx/edx4edx/edx4edx'}))
        self.assertEqual(response.status_code, 404)

        # Add user as staff in course team
        def_ms = modulestore()
        course = def_ms.get_course('MITx/edx4edx/edx4edx')
        CourseStaffRole(course.location).add_users(self.user)

        self.assertTrue(CourseStaffRole(course.location).has_user(self.user))
        logged_in = self.client.login(username=self.user.username,
                                      password='******')
        self.assertTrue(logged_in)

        response = self.client.get(
            reverse('gitlogs_detail',
                    kwargs={'course_id': 'MITx/edx4edx/edx4edx'}))
        self.assertIn('======> IMPORTING course to location',
                      response.content)

        self._rm_edx4edx()
Пример #4
0
def _has_access_to_location(user, location, access_level, course_context):
    '''
    Returns True if the given user has access_level (= staff or
    instructor) access to a location.  For now this is equivalent to
    having staff / instructor access to the course location.course.

    This means that user is in the staff_* group or instructor_* group, or is an overall admin.

    TODO (vshnayder): this needs to be changed to allow per-course_id permissions, not per-course
    (e.g. staff in 2012 is different from 2013, but maybe some people always have access)

    course is a string: the course field of the location being accessed.
    location = location
    access_level = string, either "staff" or "instructor"
    '''
    if user is None or (not user.is_authenticated()):
        debug("Deny: no user or anon user")
        return False

    if is_masquerading_as_student(user):
        return False

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

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

    staff_access = (
        CourseStaffRole(location, course_context).has_user(user) or
        OrgStaffRole(location).has_user(user)
    )

    if staff_access and access_level == 'staff':
        debug("Allow: user has course staff access")
        return True

    instructor_access = (
        CourseInstructorRole(location, course_context).has_user(user) or
        OrgInstructorRole(location).has_user(user)
    )

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

    debug("Deny: user did not have correct access")
    return False
Пример #5
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)
Пример #6
0
    def setUp(self):
        clear_existing_modulestores()
        courses = modulestore().get_courses()

        self.course_id = "edX/toy/2012_Fall"
        self.toy = modulestore().get_course(self.course_id)

        # 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.location).add_users(
            User.objects.get(email=self.instructor))

        self.logout()
        self.login(self.instructor, self.password)
        self.enroll(self.toy)
Пример #7
0
def make_instructor(course, user_email):
    """
    Makes a given user an instructor in a course.
    """
    CourseStaffRole(course.location).add_users(User.objects.get(email=user_email))
Пример #8
0
 def course(self, create, extracted, **kwargs):
     if extracted is None:
         raise ValueError(
             "Must specify a course location for a course staff user")
     CourseStaffRole(extracted).add_users(self)
Пример #9
0
 def make_instructor(course):
     """ Create an instructor for the course."""
     CourseStaffRole(course.location).add_users(User.objects.get(email=self.instructor))
Пример #10
0
 def make_instructor(course):
     CourseStaffRole(course.location).add_users(
         User.objects.get(email=self.instructor))
Пример #11
0
 def test_revoke_twice(self):
     user = self.staff[0]
     revoke_access(self.course, user, 'staff')
     self.assertFalse(CourseStaffRole(self.course.location).has_user(user))
Пример #12
0
 def test_allow_twice(self):
     user = UserFactory()
     allow_access(self.course, user, 'staff')
     allow_access(self.course, user, 'staff')
     self.assertTrue(CourseStaffRole(self.course.location).has_user(user))
Пример #13
0
    def get(self, request, *args, **kwargs):
        """Shows logs of imports that happened as a result of a git import"""

        course_id = kwargs.get('course_id')

        # Set mongodb defaults even if it isn't defined in settings
        mongo_db = {
            'host': 'localhost',
            'user': '',
            'password': '',
            'db': 'xlog',
        }

        # Allow overrides
        if hasattr(settings, 'MONGODB_LOG'):
            for config_item in [
                    'host',
                    'user',
                    'password',
                    'db',
            ]:
                mongo_db[config_item] = settings.MONGODB_LOG.get(
                    config_item, mongo_db[config_item])

        mongouri = 'mongodb://{user}:{password}@{host}/{db}'.format(**mongo_db)

        error_msg = ''

        try:
            if mongo_db['user'] and mongo_db['password']:
                mdb = mongoengine.connect(mongo_db['db'], host=mongouri)
            else:
                mdb = mongoengine.connect(mongo_db['db'],
                                          host=mongo_db['host'])
        except mongoengine.connection.ConnectionError:
            logging.exception('Unable to connect to mongodb to save log, '
                              'please check MONGODB_LOG settings.')

        if course_id is None:
            # Require staff if not going to specific course
            if not request.user.is_staff:
                raise Http404
            cilset = CourseImportLog.objects.all().order_by('-created')
        else:
            try:
                course = get_course_by_id(course_id)
            except Exception:  # pylint: disable=broad-except
                cilset = None
                error_msg = _('Cannot find course {0}').format(course_id)

            # Allow only course team, instructors, and staff
            if not (request.user.is_staff or CourseInstructorRole(
                    course.location).has_user(request.user) or CourseStaffRole(
                        course.location).has_user(request.user)):
                raise Http404
            log.debug('course_id={0}'.format(course_id))
            cilset = CourseImportLog.objects.filter(
                course_id=course_id).order_by('-created')
            log.debug('cilset length={0}'.format(len(cilset)))
        mdb.disconnect()
        context = {
            'cilset': cilset,
            'course_id': course_id,
            'error_msg': error_msg
        }

        return render_to_response(self.template_name, context)