Exemplo n.º 1
0
    def get(self, request):
        """
        - URI: /mobile/v1/users/courses/grades?username={username}&course_id={course_id}
        - GET: return a JSON response of the user's course grade and course average

        * course_id: __required__, The course ID for the course to retrieve grades for
        * username: __optional__, A staff user can retrieve grades for different users
        by using this parameter. A regular user can only retrieve their own grades.
        """
        username = request.GET.get('username', None)
        course_id = request.GET.get('course_id', None)

        if not course_exists(course_id):
            return Response({}, status=status.HTTP_404_NOT_FOUND)

        user = self.request.user
        course_key = get_course_key(course_id)

        if username is not None and user.username != username:
            # Raise a 404 if the specified user doesn't exist or
            # if they aren't enrolled in this course
            user = get_object_or_404(User, username=username)
            if not CourseEnrollment.is_enrolled(user, course_key):
                return Response({}, status=status.HTTP_404_NOT_FOUND)

        grades = self._get_user_course_grades(user, course_id)

        return Response(
            {
                'username': username or self.request.user.username,
                'course_key': course_id,
                'course_grade': grades['course_grade'],
                'course_average_grade': grades['course_average_grade']
            },
            status=status.HTTP_200_OK)
Exemplo n.º 2
0
    def _get_user_course_grades(self, user, course_id):
        """
        Get the user's grade for the given course.

        Note: For performance reasons, we use the cached gradebook data here.
        Once persistent grades are enabled on the solutions fork, we'll use CourseGradeFactory instead.
        """
        course_key = get_course_key(course_id)
        data = get_cached_data('grade', course_id, user.id)
        params = {
            'exclude_users':
            get_aggregate_exclusion_user_ids(course_key, roles=None)
        }

        if not data:
            course_avg = StudentGradebook.course_grade_avg(
                course_key, **params)
            user_grade = StudentGradebook.get_user_grade(course_key, user.id)

            data = {'user_grade': user_grade, 'course_avg': course_avg}
            cache_course_data('grade', course_id, {'course_avg': course_avg})
            cache_course_user_data('grade', course_id, user.id,
                                   {'user_grade': user_grade})

        return {
            'course_grade': data.get('user_grade'),
            'course_average_grade': data.get('course_avg')
        }
Exemplo n.º 3
0
def get_course_enrollment_count(course_id,
                                org_id=None,
                                exclude_org_admins=False):
    """
    Get enrollment count of a course
    if org_id is passed then count is limited to that org's users
    """
    cache_category = 'course_enrollments'
    if org_id:
        cache_category = '{}_{}'.format(cache_category, org_id)
        if exclude_org_admins:
            cache_category = '{}_exclude_admins'.format(cache_category)

    enrollment_count = get_cached_data(cache_category, course_id)
    if enrollment_count is not None:
        return enrollment_count.get('enrollment_count')

    course_key = get_course_key(course_id)
    exclude_user_ids = get_aggregate_exclusion_user_ids(course_key)
    users_enrolled_qs = CourseEnrollment.objects.users_enrolled_in(
        course_key).exclude(id__in=exclude_user_ids)

    if org_id:
        users_enrolled_qs = users_enrolled_qs.filter(
            organizations=org_id).distinct()
        if exclude_org_admins:
            non_company_users = get_non_actual_company_users(
                'mcka_role_company_admin', org_id)
            users_enrolled_qs.exclude(id__in=non_company_users)

    enrollment_count = users_enrolled_qs.count()
    cache_course_data(cache_category, course_id,
                      {'enrollment_count': enrollment_count})

    return enrollment_count
Exemplo n.º 4
0
    def metrics(self, request, pk):
        """
        Provide statistical information for the specified Organization
        """
        response_data = {}
        grade_avg = 0
        grade_complete_match_range = getattr(
            settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE', 0.01)
        org_user_grades = StudentGradebook.objects.filter(
            user__organizations=pk, user__is_active=True)
        courses_filter = request.query_params.get('courses', None)
        courses = []
        exclude_users = set()
        if courses_filter:
            upper_bound = getattr(settings, 'API_LOOKUP_UPPER_BOUND', 100)
            courses_filter = courses_filter.split(",")[:upper_bound]
            for course_string in courses_filter:
                courses.append(get_course_key(course_string))

            # fill exclude users
            for course_key in courses:
                exclude_users.union(
                    get_aggregate_exclusion_user_ids(course_key))

            org_user_grades = org_user_grades.filter(
                course_id__in=courses).exclude(user_id__in=exclude_users)

        users_grade_sum = org_user_grades.aggregate(Sum('grade'))
        if users_grade_sum['grade__sum']:
            users_enrolled_qs = CourseEnrollment.objects.filter(user__is_active=True, is_active=True,
                                                                user__organizations=pk)\
                .exclude(user_id__in=exclude_users)
            if courses:
                users_enrolled_qs = users_enrolled_qs.filter(
                    course_id__in=courses)
            users_enrolled = users_enrolled_qs.aggregate(
                Count('user', distinct=True))
            total_users = users_enrolled['user__count']
            if total_users:
                # in order to compute avg across organization we need course of courses org has
                total_courses_in_org = len(courses)
                if not courses:
                    org_courses = users_enrolled_qs.aggregate(
                        Count('course_id', distinct=True))
                    total_courses_in_org = org_courses['course_id__count']
                grade_avg = float('{0:.3f}'.format(
                    float(users_grade_sum['grade__sum']) / total_users /
                    total_courses_in_org))
        response_data['users_grade_average'] = grade_avg

        users_grade_complete_count = org_user_grades\
            .filter(proforma_grade__lte=F('grade') + grade_complete_match_range, proforma_grade__gt=0)\
            .aggregate(Count('user', distinct=True))
        response_data[
            'users_grade_complete_count'] = users_grade_complete_count[
                'user__count'] or 0

        return Response(response_data, status=status.HTTP_200_OK)
Exemplo n.º 5
0
 def has_permission(self, request, view):
     user = request.user
     course_id = request.GET.get('course_id') \
                 or request.parser_context.get('kwargs', {}).get('course_id', None)
     course_key = get_course_key(course_id)
     if course_key:
         return user.is_staff or CourseEnrollment.is_enrolled(
             request.user, course_key)
     return False
    def grades(self, request, pk):
        """
        Submit a grade for a Workgroup.  The grade will be applied to all members of the workgroup
        """
        # Ensure we received all of the necessary information
        course_id = request.data.get('course_id')
        if course_id is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        course_key = get_course_key(course_id)
        if not course_key:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        course_descriptor = get_course(course_key)
        if not course_descriptor:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        content_id = request.data.get('content_id')
        if content_id is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        try:
            usage_key = UsageKey.from_string(content_id)
        except InvalidKeyError:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)
        content_descriptor = modulestore().get_item(usage_key)
        if content_descriptor is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        grade = request.data.get('grade')
        if grade is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        max_grade = request.data.get('max_grade')
        if max_grade is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)
        if grade > max_grade:
            max_grade = grade

        users = User.objects.filter(workgroups=pk)
        for user in users:
            SCORE_PUBLISHED.send(
                sender=None,
                block=content_descriptor,
                user=user,
                raw_earned=grade,
                raw_possible=max_grade,
                only_if_higher=None,
                )

        return Response({}, status=status.HTTP_201_CREATED)
Exemplo n.º 7
0
    def grades(self, request, pk):
        """
        Submit a grade for a Workgroup.  The grade will be applied to all members of the workgroup
        """
        # Ensure we received all of the necessary information
        course_id = request.data.get('course_id')
        if course_id is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        course_key = get_course_key(course_id)
        if not course_key:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        course_descriptor = get_course(course_key)
        if not course_descriptor:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        content_id = request.data.get('content_id')
        if content_id is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        try:
            usage_key = UsageKey.from_string(content_id)
        except InvalidKeyError:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)
        content_descriptor = modulestore().get_item(usage_key)
        if content_descriptor is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        grade = request.data.get('grade')
        if grade is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)

        max_grade = request.data.get('max_grade')
        if max_grade is None:
            return Response({}, status=status.HTTP_400_BAD_REQUEST)
        if grade > max_grade:
            max_grade = grade

        users = User.objects.filter(workgroups=pk)
        for user in users:
            SCORE_PUBLISHED.send(
                sender=None,
                block=content_descriptor,
                user=user,
                raw_earned=grade,
                raw_possible=max_grade,
                only_if_higher=None,
            )

        return Response({}, status=status.HTTP_201_CREATED)
    def metrics(self, request, pk):
        """
        Provide statistical information for the specified Organization
        """
        response_data = {}
        grade_avg = 0
        grade_complete_match_range = getattr(settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE', 0.01)
        org_user_grades = StudentGradebook.objects.filter(user__organizations=pk, user__is_active=True)
        courses_filter = request.query_params.get('courses', None)
        courses = []
        exclude_users = set()
        if courses_filter:
            upper_bound = getattr(settings, 'API_LOOKUP_UPPER_BOUND', 100)
            courses_filter = courses_filter.split(",")[:upper_bound]
            for course_string in courses_filter:
                courses.append(get_course_key(course_string))

            # fill exclude users
            for course_key in courses:
                exclude_users.union(get_aggregate_exclusion_user_ids(course_key))

            org_user_grades = org_user_grades.filter(course_id__in=courses).exclude(user_id__in=exclude_users)

        users_grade_sum = org_user_grades.aggregate(Sum('grade'))
        if users_grade_sum['grade__sum']:
            users_enrolled_qs = CourseEnrollment.objects.filter(user__is_active=True, is_active=True,
                                                                user__organizations=pk)\
                .exclude(user_id__in=exclude_users)
            if courses:
                users_enrolled_qs = users_enrolled_qs.filter(course_id__in=courses)
            users_enrolled = users_enrolled_qs.aggregate(Count('user', distinct=True))
            total_users = users_enrolled['user__count']
            if total_users:
                # in order to compute avg across organization we need course of courses org has
                total_courses_in_org = len(courses)
                if not courses:
                    org_courses = users_enrolled_qs.aggregate(Count('course_id', distinct=True))
                    total_courses_in_org = org_courses['course_id__count']
                grade_avg = float('{0:.3f}'.format(
                    float(users_grade_sum['grade__sum']) / total_users / total_courses_in_org
                ))
        response_data['users_grade_average'] = grade_avg

        users_grade_complete_count = org_user_grades\
            .filter(proforma_grade__lte=F('grade') + grade_complete_match_range, proforma_grade__gt=0)\
            .aggregate(Count('user', distinct=True))
        response_data['users_grade_complete_count'] = users_grade_complete_count['user__count'] or 0

        return Response(response_data, status=status.HTTP_200_OK)
    def create(self, request):
        """
        Create a new workgroup and its cohort.
        """
        assignment_type = request.data.get('assignment_type', CourseCohort.RANDOM)
        if assignment_type not in dict(CourseCohort.ASSIGNMENT_TYPE_CHOICES).keys():
            message = "Not a valid assignment type, '{}'".format(assignment_type)
            return Response({'details': message}, status.HTTP_400_BAD_REQUEST)
        response = super(WorkgroupsViewSet, self).create(request)
        if response.status_code == status.HTTP_201_CREATED:
            # create the workgroup cohort
            workgroup = get_object_or_404(self.queryset, pk=response.data['id'])
            course_key = get_course_key(workgroup.project.course_id)
            add_cohort(course_key, workgroup.cohort_name, assignment_type)

        return response
Exemplo n.º 10
0
    def _get_user_course_grades(self, user, course_id):
        """
        Get the user's grade for the given course.

        Note: For performance reasons, we use the cached gradebook data here.
        Once persistent grades are enabled on the solutions fork, we'll use CourseGradeFactory instead.
        """
        course_key = get_course_key(course_id)
        try:
            record = StudentGradebook.objects.get(user=user,
                                                  course_id=course_key)
            course_grade = record.grade
        except StudentGradebook.DoesNotExist:
            course_grade = 0

        course_average = self._get_course_average_grade(course_key)
        return {
            'course_grade': course_grade,
            'course_average_grade': course_average
        }
Exemplo n.º 11
0
    def create(self, request):
        """
        Create a new workgroup and its cohort.
        """
        assignment_type = request.data.get('assignment_type',
                                           CourseCohort.RANDOM)
        if assignment_type not in dict(
                CourseCohort.ASSIGNMENT_TYPE_CHOICES).keys():
            message = "Not a valid assignment type, '{}'".format(
                assignment_type)
            return Response({'details': message}, status.HTTP_400_BAD_REQUEST)
        response = super(WorkgroupsViewSet, self).create(request)
        if response.status_code == status.HTTP_201_CREATED:
            # create the workgroup cohort
            workgroup = get_object_or_404(self.queryset,
                                          pk=response.data['id'])
            course_key = get_course_key(workgroup.project.course_id)
            add_cohort(course_key, workgroup.cohort_name, assignment_type)

        return response
    def handle(self, *args, **options):
        if len(args) < 1 or len(args) > 2:
            print Command.help
            return

        dry_run = True
        create_log = False

        msg_string = 'Script started on {}'.format(datetime.datetime.now().ctime())

        if 'repair' in args:
            dry_run = False
        if 'dryrun' in args:
            dry_run = True
        if 'createlog' in args:
            create_log = True
            file_handler = logging.FileHandler('repair_internal_admin_instructor_role.log')
            file_handler.setLevel(logging.DEBUG)
            formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
            file_handler.setFormatter(formatter)
            log.addHandler(file_handler)

        log.info(msg_string)

        if dry_run:
            msg_string = 'Script started in dry run mode, this will print for all internal admins courses for which we need to remove or add theirs instructor role'
        else:
            msg_string = 'Script started in repair mode, this will permanently remove or add instructor role of internal admins. THIS IS IRREVERSIBLE!'

        log.info(msg_string)

        internal_admin_group_name = 'mcka_role_internal_admin'
        internal_tag_group_type = 'tag:internal'
        instructor_role = 'instructor'
        staff_role = 'staff'
        number_of_removed_roles = 0
        number_of_added_roles = 0

        #get all internal admins
        try:
            internal_admin_group = Group.objects.get(name__icontains=internal_admin_group_name)
        except ObjectDoesNotExist:
            internal_admin_group = None

        if internal_admin_group:
            internal_admins = internal_admin_group.user_set.all()

        #get internal tagged courses
        try:
            internal_courses_group = Group.objects.get(groupprofile__group_type=internal_tag_group_type)
        except ObjectDoesNotExist:
            internal_courses_group = None

        if internal_courses_group:
            internal_courses = CourseGroupRelationship.objects.filter(group=internal_courses_group)
            internal_courses_ids = []
            for internal_course in internal_courses:
                internal_courses_ids.append(internal_course.course_id)

        #for all internal admins check their roles and remove instructor role on course if he doesn't have staff role on course and course isn't tagged internal
        for internal_admin in internal_admins:
            user_roles = CourseAccessRole.objects.filter(user=internal_admin)

            instructor_courses = []
            staff_courses = []
            for user_role in user_roles:
                if user_role.role == instructor_role:
                    instructor_courses.append(user_role.course_id)
                if user_role.role == staff_role:
                    staff_courses.append(user_role.course_id)

            for instructor_course in instructor_courses:
                if str(instructor_course) not in internal_courses_ids and instructor_course not in staff_courses:
                    number_of_removed_roles += 1
                    if dry_run:
                        msg_string = 'Remove instructor role for internal admin ' + str(internal_admin.id) + ' on course ' + str(instructor_course) + '.'
                        log.info(msg_string)
                    else:
                        role_to_delete = CourseAccessRole.objects.get(user=internal_admin, role=instructor_role, course_id=instructor_course)
                        role_to_delete.delete()

        #for all internal tagged course check roles and if internal admins don't have instructor role on course add it
        for internal_course in internal_courses:
            course_id = get_course_key(internal_course.course_id)
            course_roles = CourseAccessRole.objects.filter(course_id=course_id)
            instructor_users = []
            for course_role in course_roles:
                if course_role.role == instructor_role:
                    instructor_users.append(course_role.user_id)

            for internal_admin in internal_admins:
                if internal_admin.id not in instructor_users:
                    number_of_added_roles += 1
                    if dry_run:
                        msg_string = 'Add instructor role for internal admin ' + str(internal_admin.id) + ' on course ' + str(course_id) + '.'
                        log.info(msg_string)
                    else:
                        course = courses.get_course(course_id, 0)
                        new_role = CourseAccessRole(user=internal_admin, role=instructor_role, course_id=course.id, org=course.org)
                        new_role.save()

        msg_string = 'Number of removed roles: ' + str(number_of_removed_roles) + '.'
        log.info(msg_string)
        msg_string = 'Number of added roles: ' + str(number_of_added_roles) + '.'
        log.info(msg_string)

        log.info('--------------------------------------------------------------------------------------------------------------------')

        if create_log:
            print 'Script started in create log mode, please open repair_internal_admin_instructor_role.log file.'
Exemplo n.º 13
0
    def users(self, request, pk):
        """
        - URI: ```/api/organizations/{org_id}/users/```
        - GET: Returns users in an organization
            * course_id parameter should filter user by course
            * include_course_counts parameter should be `true` to get user's enrollment count
            * include_grades parameter should be `true` to get user's grades
            * for the course given in the course_id parameter
            * view parameter can be used to get a particular data .i.e. view=ids to
            * get list of user ids
        - POST: Adds a User to an Organization
        - DELETE: Removes the user(s) given in the `users` param from an Organization.
        """
        if request.method == 'GET':
            include_course_counts = request.query_params.get(
                'include_course_counts', None)
            include_grades = request.query_params.get('include_grades', None)
            course_id = request.query_params.get('course_id', None)
            view = request.query_params.get('view', None)
            grade_complete_match_range = getattr(
                settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE',
                0.01)
            course_key = None
            if course_id:
                course_key = get_course_key(course_id)

            users = User.objects.filter(organizations=pk)

            if course_key:
                users = users.filter(
                    courseenrollment__course_id__exact=course_key,
                    courseenrollment__is_active=True)
            if str2bool(include_grades):
                users = users.prefetch_related('studentgradebook_set')

            if str2bool(include_course_counts):
                enrollments = CourseEnrollment.objects.filter(
                    user__in=users).values('user').order_by().annotate(
                        total=Count('user'))
                enrollments_by_user = {}
                for enrollment in enrollments:
                    enrollments_by_user[
                        enrollment['user']] = enrollment['total']

            # if we only need ids of users in organization return now
            if view == 'ids':
                user_ids = users.values_list('id', flat=True)
                return Response(user_ids)

            response_data = []
            if users:
                for user in users:
                    serializer = SimpleUserSerializer(user)
                    user_data = serializer.data

                    if str2bool(include_course_counts):
                        user_data['course_count'] = enrollments_by_user.get(
                            user.id, 0)

                    if str2bool(include_grades) and course_key:
                        user_grades = {
                            'grade': 0,
                            'proforma_grade': 0,
                            'complete_status': False
                        }
                        gradebook = user.studentgradebook_set.filter(
                            course_id=course_key)
                        if gradebook:
                            user_grades['grade'] = gradebook[0].grade
                            user_grades['proforma_grade'] = gradebook[
                                0].proforma_grade
                            user_grades['complete_status'] = True if 0 < gradebook[0].proforma_grade <= \
                                gradebook[0].grade + grade_complete_match_range else False
                        user_data.update(user_grades)

                    response_data.append(user_data)
            return Response(response_data, status=status.HTTP_200_OK)
        elif request.method == 'DELETE':
            user_ids = request.data.get('users')
            if not user_ids:
                return Response({"detail": _('users parameter is missing.')},
                                status.HTTP_400_BAD_REQUEST)
            try:
                user_ids = [
                    int(user_id)
                    for user_id in filter(None, user_ids.split(','))
                ]
            except (ValueError, AttributeError):
                return Response(
                    {
                        "detail":
                        _('users parameter must be comma separated list of integers.'
                          )
                    }, status.HTTP_400_BAD_REQUEST)

            organization = self.get_object()
            users_to_be_deleted = organization.users.filter(id__in=user_ids)
            total_users = len(users_to_be_deleted)
            for user in users_to_be_deleted:
                organization.users.remove(user)
            if total_users > 0:
                return Response(
                    {
                        "detail":
                        _("{users_removed} user(s) removed from organization").
                        format(users_removed=total_users)
                    },
                    status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            user_id = request.data.get('id')
            try:
                user = User.objects.get(id=user_id)
            except ObjectDoesNotExist:
                message = 'User {} does not exist'.format(user_id)
                return Response({"detail": message},
                                status.HTTP_400_BAD_REQUEST)
            organization = self.get_object()
            organization.users.add(user)
            organization.save()
            return Response({}, status=status.HTTP_201_CREATED)
    def users(self, request, pk):
        """
        - URI: ```/api/organizations/{org_id}/users/```
        - GET: Returns users in an organization
            * course_id parameter should filter user by course
            * include_course_counts parameter should be `true` to get user's enrollment count
            * include_grades parameter should be `true` to get user's grades
            * for the course given in the course_id parameter
            * view parameter can be used to get a particular data .i.e. view=ids to
            * get list of user ids
        - POST: Adds a User to an Organization
        - DELETE: Removes the user(s) given in the `users` param from an Organization.
        """
        if request.method == 'GET':
            include_course_counts = request.query_params.get('include_course_counts', None)
            include_grades = request.query_params.get('include_grades', None)
            course_id = request.query_params.get('course_id', None)
            view = request.query_params.get('view', None)
            grade_complete_match_range = getattr(settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE', 0.01)
            course_key = None
            if course_id:
                course_key = get_course_key(course_id)

            users = User.objects.filter(organizations=pk)

            if course_key:
                users = users.filter(courseenrollment__course_id__exact=course_key,
                                     courseenrollment__is_active=True)

                if str2bool(include_grades):
                    users = users.prefetch_related(
                        Prefetch('studentgradebook_set', queryset=StudentGradebook.objects.filter(course_id=course_key))
                    )

            if str2bool(include_course_counts):
                enrollments = CourseEnrollment.objects.filter(user__in=users).values('user').order_by().annotate(total=Count('user'))
                enrollments_by_user = {}
                for enrollment in enrollments:
                    enrollments_by_user[enrollment['user']] = enrollment['total']

            # if we only need ids of users in organization return now
            if view == 'ids':
                user_ids = users.values_list('id', flat=True)
                return Response(user_ids)

            response_data = []
            if users:
                for user in users:
                    serializer = SimpleUserSerializer(user)
                    user_data = serializer.data

                    if str2bool(include_course_counts):
                        user_data['course_count'] = enrollments_by_user.get(user.id, 0)

                    if str2bool(include_grades) and course_key:
                        user_grades = {'grade': 0, 'proforma_grade': 0, 'complete_status': False}
                        gradebook = user.studentgradebook_set.all()
                        if gradebook:
                            user_grades['grade'] = gradebook[0].grade
                            user_grades['proforma_grade'] = gradebook[0].proforma_grade
                            user_grades['complete_status'] = True if 0 < gradebook[0].proforma_grade <= \
                                gradebook[0].grade + grade_complete_match_range else False
                        user_data.update(user_grades)

                    response_data.append(user_data)
            return Response(response_data, status=status.HTTP_200_OK)
        elif request.method == 'DELETE':
            user_ids = request.data.get('users')
            if not user_ids:
                return Response({"detail": _('users parameter is missing.')}, status.HTTP_400_BAD_REQUEST)
            try:
                user_ids = [int(user_id) for user_id in filter(None, user_ids.split(','))]
            except (ValueError, AttributeError):
                return Response({
                    "detail": _('users parameter must be comma separated list of integers.')
                }, status.HTTP_400_BAD_REQUEST)

            organization = self.get_object()
            users_to_be_deleted = organization.users.filter(id__in=user_ids)
            total_users = len(users_to_be_deleted)
            if total_users > 0:
                organization.users.remove(*users_to_be_deleted)
                return Response({
                    "detail": _("{users_removed} user(s) removed from organization").format(users_removed=total_users)
                }, status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            user_id = request.data.get('id')
            try:
                user = User.objects.get(id=user_id)
            except ObjectDoesNotExist:
                message = 'User {} does not exist'.format(user_id)
                return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)
            organization = self.get_object()
            organization.users.add(user)
            organization.save()
            return Response({}, status=status.HTTP_201_CREATED)
Exemplo n.º 15
0
    def handle(self, *args, **options):
        if len(args) < 1 or len(args) > 2:
            print(Command.help)
            return

        dry_run = True
        create_log = False

        msg_string = 'Script started on {}'.format(
            datetime.datetime.now().ctime())

        if 'repair' in args:
            dry_run = False
        if 'dryrun' in args:
            dry_run = True
        if 'createlog' in args:
            create_log = True
            file_handler = logging.FileHandler(
                'repair_internal_admin_instructor_role.log')
            file_handler.setLevel(logging.DEBUG)
            formatter = logging.Formatter(
                '%(asctime)s-%(name)s-%(levelname)s-%(message)s')
            file_handler.setFormatter(formatter)
            log.addHandler(file_handler)

        log.info(msg_string)

        if dry_run:
            msg_string = 'Script started in dry run mode, this will print for all internal admins courses for which ' \
                         'we need to remove or add theirs instructor role'
        else:
            msg_string = 'Script started in repair mode, this will permanently remove or add instructor role of ' \
                         'internal admins. THIS IS IRREVERSIBLE!'

        log.info(msg_string)

        internal_admin_group_name = 'mcka_role_internal_admin'
        internal_tag_group_type = 'tag:internal'
        instructor_role = 'instructor'
        staff_role = 'staff'
        number_of_removed_roles = 0
        number_of_added_roles = 0

        #get all internal admins
        try:
            internal_admin_group = Group.objects.get(
                name__icontains=internal_admin_group_name)
        except ObjectDoesNotExist:
            internal_admin_group = None

        if internal_admin_group:
            internal_admins = internal_admin_group.user_set.all()

        #get internal tagged courses
        try:
            internal_courses_group = Group.objects.get(
                groupprofile__group_type=internal_tag_group_type)
        except ObjectDoesNotExist:
            internal_courses_group = None

        if internal_courses_group:
            internal_courses = CourseGroupRelationship.objects.filter(
                group=internal_courses_group)
            internal_courses_ids = []
            for internal_course in internal_courses:
                internal_courses_ids.append(internal_course.course_id)

        # for all internal admins check their roles and remove instructor role on course
        # if he doesn't have staff role on course and course isn't tagged internal
        for internal_admin in internal_admins:
            user_roles = CourseAccessRole.objects.filter(user=internal_admin)

            instructor_courses = []
            staff_courses = []
            for user_role in user_roles:
                if user_role.role == instructor_role:
                    instructor_courses.append(user_role.course_id)
                if user_role.role == staff_role:
                    staff_courses.append(user_role.course_id)

            for instructor_course in instructor_courses:
                if str(
                        instructor_course
                ) not in internal_courses_ids and instructor_course not in staff_courses:
                    number_of_removed_roles += 1
                    if dry_run:
                        msg_string = 'Remove instructor role for internal admin ' + str(internal_admin.id) +\
                                     ' on course ' + str(instructor_course) + '.'
                        log.info(msg_string)
                    else:
                        role_to_delete = CourseAccessRole.objects.get(
                            user=internal_admin,
                            role=instructor_role,
                            course_id=instructor_course)
                        role_to_delete.delete()

        # for all internal tagged course check roles and if internal admins don't have instructor role on course add it
        for internal_course in internal_courses:
            course_id = get_course_key(internal_course.course_id)
            course_roles = CourseAccessRole.objects.filter(course_id=course_id)
            instructor_users = []
            for course_role in course_roles:
                if course_role.role == instructor_role:
                    instructor_users.append(course_role.user_id)

            for internal_admin in internal_admins:
                if internal_admin.id not in instructor_users:
                    number_of_added_roles += 1
                    if dry_run:
                        msg_string = 'Add instructor role for internal admin ' + str(internal_admin.id) + \
                                     ' on course ' + str(course_id) + '.'
                        log.info(msg_string)
                    else:
                        course = courses.get_course(course_id, 0)
                        new_role = CourseAccessRole(user=internal_admin,
                                                    role=instructor_role,
                                                    course_id=course.id,
                                                    org=course.org)
                        new_role.save()

        msg_string = 'Number of removed roles: ' + str(
            number_of_removed_roles) + '.'
        log.info(msg_string)
        msg_string = 'Number of added roles: ' + str(
            number_of_added_roles) + '.'
        log.info(msg_string)

        log.info(
            '---------------------------------------------------------------------------------------------------'
        )

        if create_log:
            print(
                'Script started in create log mode, please open repair_internal_admin_instructor_role.log file.'
            )
    def users(self, request, pk):
        """
        Add a User to a Workgroup
        """
        if request.method == 'GET':
            users = User.objects.filter(workgroups=pk)
            response_data = []
            if users:
                for user in users:
                    serializer = UserSerializer(user, context={'request': request})
                    response_data.append(serializer.data)  # pylint: disable=E1101
            return Response(response_data, status=status.HTTP_200_OK)
        elif request.method == 'POST':
            user_id = request.data.get('id')
            try:
                user = User.objects.get(id=user_id)
            except ObjectDoesNotExist:
                message = 'User {} does not exist'.format(user_id)
                return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)

            workgroup = self.get_object()

            # Ensure the user is not already assigned to a project for this course
            existing_projects = Project.objects.filter(course_id=workgroup.project.course_id).filter(workgroups__users__id=user.id)
            if len(existing_projects):
                message = 'User {} already assigned to a project for this course'.format(user_id)
                return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)

            try:
                workgroup.add_user(user)
            except ValidationError as e:
                return Response({"detail": unicode(e)}, status.HTTP_400_BAD_REQUEST)

            workgroup.save()

            # add user to the workgroup cohort, create it if it doesn't exist (for cases where there is a legacy
            # workgroup)
            course_key = get_course_key(workgroup.project.course_id)
            try:
                cohort = get_cohort_by_name(course_key, workgroup.cohort_name)
                add_user_to_cohort(cohort, user.username)
            except ObjectDoesNotExist:
                # This use case handles cases where a workgroup might have been created before
                # the notion of a cohorted discussion. So we need to backfill in the data
                assignment_type = request.data.get('assignment_type', CourseCohort.RANDOM)
                if assignment_type not in dict(CourseCohort.ASSIGNMENT_TYPE_CHOICES).keys():
                    message = "Not a valid assignment type, '{}'".format(assignment_type)
                    return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)
                workgroup = self.get_object()
                cohort = add_cohort(course_key, workgroup.cohort_name, assignment_type)
                for workgroup_user in workgroup.users.all():
                    add_user_to_cohort(cohort, workgroup_user.username)
            return Response({}, status=status.HTTP_201_CREATED)
        else:
            user_id = request.data.get('id')
            try:
                user = User.objects.get(id=user_id)
            except ObjectDoesNotExist:
                message = 'User {} does not exist'.format(user_id)
                return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)
            workgroup = self.get_object()
            course_key = get_course_key(workgroup.project.course_id)
            cohort = get_cohort_by_name(course_key, workgroup.cohort_name)
            workgroup.remove_user(user)
            remove_user_from_cohort(cohort, user.username)
            return Response({}, status=status.HTTP_204_NO_CONTENT)
Exemplo n.º 17
0
    def users(self, request, pk):
        """
        Add a User to a Workgroup
        """
        if request.method == 'GET':
            users = User.objects.filter(workgroups=pk)
            response_data = []
            if users:
                for user in users:
                    serializer = UserSerializer(user,
                                                context={'request': request})
                    response_data.append(serializer.data)  # pylint: disable=E1101
            return Response(response_data, status=status.HTTP_200_OK)
        elif request.method == 'POST':
            user_id = request.data.get('id')
            try:
                user = User.objects.get(id=user_id)
            except ObjectDoesNotExist:
                message = 'User {} does not exist'.format(user_id)
                return Response({"detail": message},
                                status.HTTP_400_BAD_REQUEST)

            workgroup = self.get_object()

            # Ensure the user is not already assigned to a project for this course
            existing_projects = Project.objects.filter(
                course_id=workgroup.project.course_id).filter(
                    workgroups__users__id=user.id)
            if len(existing_projects):
                message = 'User {} already assigned to a project for this course'.format(
                    user_id)
                return Response({"detail": message},
                                status.HTTP_400_BAD_REQUEST)

            try:
                workgroup.add_user(user)
            except ValidationError as e:
                return Response({"detail": unicode(e)},
                                status.HTTP_400_BAD_REQUEST)

            workgroup.save()

            # add user to the workgroup cohort, create it if it doesn't exist (for cases where there is a legacy
            # workgroup)
            course_key = get_course_key(workgroup.project.course_id)
            try:
                cohort = get_cohort_by_name(course_key, workgroup.cohort_name)
                add_user_to_cohort(cohort, user.username)
            except ObjectDoesNotExist:
                # This use case handles cases where a workgroup might have been created before
                # the notion of a cohorted discussion. So we need to backfill in the data
                assignment_type = request.data.get('assignment_type',
                                                   CourseCohort.RANDOM)
                if assignment_type not in dict(
                        CourseCohort.ASSIGNMENT_TYPE_CHOICES).keys():
                    message = "Not a valid assignment type, '{}'".format(
                        assignment_type)
                    return Response({"detail": message},
                                    status.HTTP_400_BAD_REQUEST)
                workgroup = self.get_object()
                cohort = add_cohort(course_key, workgroup.cohort_name,
                                    assignment_type)
                for workgroup_user in workgroup.users.all():
                    add_user_to_cohort(cohort, workgroup_user.username)
            return Response({}, status=status.HTTP_201_CREATED)
        else:
            user_id = request.data.get('id')
            try:
                user = User.objects.get(id=user_id)
            except ObjectDoesNotExist:
                message = 'User {} does not exist'.format(user_id)
                return Response({"detail": message},
                                status.HTTP_400_BAD_REQUEST)
            workgroup = self.get_object()
            course_key = get_course_key(workgroup.project.course_id)
            cohort = get_cohort_by_name(course_key, workgroup.cohort_name)
            workgroup.remove_user(user)
            remove_user_from_cohort(cohort, user.username)
            return Response({}, status=status.HTTP_204_NO_CONTENT)