Example #1
0
    def get(self, request, course_id):
        """
        Renders the teams dashboard, which is shown on the "Teams" tab.

        Raises a 404 if the course specified by course_id does not exist, the
        user is not registered for the course, or the teams feature is not enabled.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, "load", course_key)

        if not is_feature_enabled(course):
            raise Http404

        if not CourseEnrollment.is_enrolled(request.user, course.id) and \
                not has_access(request.user, 'staff', course, course.id):
            raise Http404

        sort_order = 'name'
        topics = get_ordered_topics(course, sort_order)
        topics_page = Paginator(topics, TOPICS_PER_PAGE).page(1)
        topics_serializer = PaginatedTopicSerializer(
            instance=topics_page,
            context={'course_id': course.id, 'sort_order': sort_order}
        )
        user = request.user

        team_memberships = CourseTeamMembership.get_memberships(request.user.username, [course.id])
        team_memberships_page = Paginator(team_memberships, TEAM_MEMBERSHIPS_PER_PAGE).page(1)
        team_memberships_serializer = PaginatedMembershipSerializer(
            instance=team_memberships_page,
            context={'expand': ('team',)},
        )

        context = {
            "course": course,
            "topics": topics_serializer.data,
            # It is necessary to pass both privileged and staff because only privileged users can
            # administer discussion threads, but both privileged and staff users are allowed to create
            # multiple teams (since they are not automatically added to teams upon creation).
            "user_info": {
                "username": user.username,
                "privileged": has_discussion_privileges(user, course_key),
                "staff": bool(has_access(user, 'staff', course_key)),
                "team_memberships_data": team_memberships_serializer.data,
            },
            "topic_url": reverse(
                'topics_detail', kwargs={'topic_id': 'topic_id', 'course_id': str(course_id)}, request=request
            ),
            "topics_url": reverse('topics_list', request=request),
            "teams_url": reverse('teams_list', request=request),
            "team_memberships_url": reverse('team_membership_list', request=request),
            "team_membership_detail_url": reverse('team_membership_detail', args=['team_id', user.username]),
            "languages": settings.ALL_LANGUAGES,
            "countries": list(countries),
            "disable_courseware_js": True,
            "teams_base_url": reverse('teams_dashboard', request=request, kwargs={'course_id': course_id}),
        }
        return render_to_response("teams/teams.html", context)
Example #2
0
    def get(self, request, course_id):
        """
        Renders the teams dashboard, which is shown on the "Teams" tab.

        Raises a 404 if the course specified by course_id does not exist, the
        user is not registered for the course, or the teams feature is not enabled.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, "load", course_key)

        if not is_feature_enabled(course):
            raise Http404

        if not CourseEnrollment.is_enrolled(request.user, course.id) and \
                not has_access(request.user, 'staff', course, course.id):
            raise Http404

        sort_order = 'name'
        topics = get_ordered_topics(course, sort_order)
        topics_page = Paginator(topics, TOPICS_PER_PAGE).page(1)
        topics_serializer = PaginatedTopicSerializer(instance=topics_page,
                                                     context={
                                                         'course_id':
                                                         course.id,
                                                         'sort_order':
                                                         sort_order
                                                     })
        user = request.user
        context = {
            "course":
            course,
            "topics":
            topics_serializer.data,
            "topic_url":
            reverse('topics_detail',
                    kwargs={
                        'topic_id': 'topic_id',
                        'course_id': str(course_id)
                    },
                    request=request),
            "topics_url":
            reverse('topics_list', request=request),
            "teams_url":
            reverse('teams_list', request=request),
            "languages":
            settings.ALL_LANGUAGES,
            "countries":
            list(countries),
            "username":
            user.username,
            "privileged":
            has_discussion_privileges(user, course_key),
            "disable_courseware_js":
            True,
        }
        return render_to_response("teams/teams.html", context)
Example #3
0
 def test_has_discussion_privileges(self):
     self.assertFalse(utils.has_discussion_privileges(self.student1, self.course_id))
     self.assertFalse(utils.has_discussion_privileges(self.student2, self.course_id))
     self.assertFalse(utils.has_discussion_privileges(self.course_staff, self.course_id))
     self.assertTrue(utils.has_discussion_privileges(self.moderator, self.course_id))
     self.assertTrue(utils.has_discussion_privileges(self.community_ta1, self.course_id))
     self.assertTrue(utils.has_discussion_privileges(self.community_ta2, self.course_id))
Example #4
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(ugettext_noop(
                'The supplied course_id {course_id} is not valid.'),
                                                        course_id=course_id)
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)

        # Course and global staff, as well as discussion "privileged" users, will not automatically
        # be added to a team when they create it. They are allowed to create multiple teams.
        team_administrator = (has_access(request.user, 'staff', course_key)
                              or has_discussion_privileges(
                                  request.user, course_key))
        if not team_administrator and CourseTeamMembership.user_in_team_for_course(
                request.user, course_key):
            error_message = build_api_error(
                ugettext_noop('You are already in a team in this course.'),
                course_id=course_id)
            return Response(error_message, status=status.HTTP_400_BAD_REQUEST)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            if not team_administrator:
                # Add the creating user to the team.
                team.add_user(request.user)
            return Response(CourseTeamSerializer(team).data)
Example #5
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get("course_id")
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors["course_id"] = build_api_error(
                ugettext_noop("The supplied course_id {course_id} is not valid."), course_id=course_id
            )
            return Response({"field_errors": field_errors}, status=status.HTTP_400_BAD_REQUEST)

        # Course and global staff, as well as discussion "privileged" users, will not automatically
        # be added to a team when they create it. They are allowed to create multiple teams.
        team_administrator = has_access(request.user, "staff", course_key) or has_discussion_privileges(
            request.user, course_key
        )
        if not team_administrator and CourseTeamMembership.user_in_team_for_course(request.user, course_key):
            error_message = build_api_error(
                ugettext_noop("You are already in a team in this course."), course_id=course_id
            )
            return Response(error_message, status=status.HTTP_400_BAD_REQUEST)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data["course_id"] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({"field_errors": field_errors}, status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            emit_team_event("edx.team.created", course_key, {"team_id": team.team_id})
            if not team_administrator:
                # Add the creating user to the team.
                team.add_user(request.user)
                emit_team_event(
                    "edx.team.learner_added",
                    course_key,
                    {"team_id": team.team_id, "user_id": request.user.id, "add_method": "added_on_create"},
                )
            return Response(CourseTeamSerializer(team).data)
Example #6
0
    def get(self, request, course_id):
        """
        Renders the teams dashboard, which is shown on the "Teams" tab.

        Raises a 404 if the course specified by course_id does not exist, the
        user is not registered for the course, or the teams feature is not enabled.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, "load", course_key)

        if not is_feature_enabled(course):
            raise Http404

        if not CourseEnrollment.is_enrolled(request.user, course.id) and \
                not has_access(request.user, 'staff', course, course.id):
            raise Http404

        sort_order = 'name'
        topics = get_ordered_topics(course, sort_order)
        topics_page = Paginator(topics, TOPICS_PER_PAGE).page(1)
        topics_serializer = PaginatedTopicSerializer(
            instance=topics_page,
            context={'course_id': course.id, 'sort_order': sort_order}
        )
        user = request.user

        team_memberships = CourseTeamMembership.get_memberships(request.user.username, [course.id])
        team_memberships_page = Paginator(team_memberships, TEAM_MEMBERSHIPS_PER_PAGE).page(1)
        team_memberships_serializer = PaginatedMembershipSerializer(
            instance=team_memberships_page,
            context={'expand': ('team',)},
        )

        context = {
            "course": course,
            "topics": topics_serializer.data,
            "topic_url": reverse(
                'topics_detail', kwargs={'topic_id': 'topic_id', 'course_id': str(course_id)}, request=request
            ),
            "team_memberships": team_memberships_serializer.data,
            "topics_url": reverse('topics_list', request=request),
            "teams_url": reverse('teams_list', request=request),
            "team_memberships_url": reverse('team_membership_list', request=request),
            "languages": settings.ALL_LANGUAGES,
            "countries": list(countries),
            "username": user.username,
            "privileged": has_discussion_privileges(user, course_key),
            "disable_courseware_js": True,
        }
        return render_to_response("teams/teams.html", context)
Example #7
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(
                ugettext_noop('The supplied course_id {course_id} is not valid.'),
                course_id=course_id
            )
            return Response({
                'field_errors': field_errors,
            }, status=status.HTTP_400_BAD_REQUEST)

        if CourseTeamMembership.user_in_team_for_course(request.user, course_key):
            error_message = build_api_error(
                ugettext_noop('You are already in a team in this course.'),
                course_id=course_id
            )
            return Response({
                'error_message': error_message,
            }, status=status.HTTP_400_BAD_REQUEST)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            }, status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            if not (has_access(request.user, 'staff', course_key)
                    or has_discussion_privileges(request.user, course_key)):
                # Add the creating user to the team.
                team.add_user(request.user)
            return Response(CourseTeamSerializer(team).data)
Example #8
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, be global staff, or have discussion privileges.

    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 has_discussion_privileges(user, course_key):
        return True
    if not access_username or access_username == user.username:
        return CourseEnrollment.is_enrolled(user, course_key)
    return False
Example #9
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, be global staff, or have discussion privileges.

    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 has_discussion_privileges(user, course_key):
        return True
    if not access_username or access_username == user.username:
        return CourseEnrollment.is_enrolled(user, course_key)
    return False
Example #10
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(ugettext_noop(
                'The supplied course_id {course_id} is not valid.'),
                                                        course_id=course_id)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            if not (has_access(request.user, 'staff', course_key)
                    or has_discussion_privileges(request.user, course_key)):
                # Add the creating user to the team.
                team.add_user(request.user)
            return Response(CourseTeamSerializer(team).data)
Example #11
0
 def has_object_permission(self, request, view, obj):
     return (
         has_discussion_privileges(request.user, obj.course_id) or
         super(IsStaffOrPrivilegedOrReadOnly, self).has_object_permission(request, view, obj)
     )
Example #12
0
    def get(self, request, course_id):
        """
        Renders the teams dashboard, which is shown on the "Teams" tab.

        Raises a 404 if the course specified by course_id does not exist, the
        user is not registered for the course, or the teams feature is not enabled.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, "load", course_key)

        if not is_feature_enabled(course):
            raise Http404

        if not CourseEnrollment.is_enrolled(request.user, course.id) and \
                not has_access(request.user, 'staff', course, course.id):
            raise Http404

        # Even though sorting is done outside of the serializer, sort_order needs to be passed
        # to the serializer so that the paginated results indicate how they were sorted.
        sort_order = 'name'
        topics = get_alphabetical_topics(course)
        topics_page = Paginator(topics, TOPICS_PER_PAGE).page(1)
        # BulkTeamCountPaginatedTopicSerializer will add team counts to the topics in a single
        # bulk operation per page.
        topics_serializer = BulkTeamCountPaginatedTopicSerializer(
            instance=topics_page,
            context={
                'course_id': course.id,
                'sort_order': sort_order
            })
        user = request.user

        team_memberships = CourseTeamMembership.get_memberships(
            request.user.username, [course.id])
        team_memberships_page = Paginator(team_memberships,
                                          TEAM_MEMBERSHIPS_PER_PAGE).page(1)
        team_memberships_serializer = PaginatedMembershipSerializer(
            instance=team_memberships_page,
            context={'expand': ('team', )},
        )

        context = {
            "course":
            course,
            "topics":
            topics_serializer.data,
            # It is necessary to pass both privileged and staff because only privileged users can
            # administer discussion threads, but both privileged and staff users are allowed to create
            # multiple teams (since they are not automatically added to teams upon creation).
            "user_info": {
                "username": user.username,
                "privileged": has_discussion_privileges(user, course_key),
                "staff": bool(has_access(user, 'staff', course_key)),
                "team_memberships_data": team_memberships_serializer.data,
            },
            "topic_url":
            reverse('topics_detail',
                    kwargs={
                        'topic_id': 'topic_id',
                        'course_id': str(course_id)
                    },
                    request=request),
            "topics_url":
            reverse('topics_list', request=request),
            "teams_url":
            reverse('teams_list', request=request),
            "team_memberships_url":
            reverse('team_membership_list', request=request),
            "team_membership_detail_url":
            reverse('team_membership_detail', args=['team_id', user.username]),
            "languages":
            settings.ALL_LANGUAGES,
            "countries":
            list(countries),
            "disable_courseware_js":
            True,
            "teams_base_url":
            reverse('teams_dashboard',
                    request=request,
                    kwargs={'course_id': course_id}),
        }
        return render_to_response("teams/teams.html", context)
Example #13
0
 def has_object_permission(self, request, view, obj):
     return (has_discussion_privileges(request.user, obj.course_id)
             or super(IsStaffOrPrivilegedOrReadOnly,
                      self).has_object_permission(request, view, obj))
Example #14
0
    def get(self, request, course_id):
        """
        Renders the teams dashboard, which is shown on the "Teams" tab.

        Raises a 404 if the course specified by course_id does not exist, the
        user is not registered for the course, or the teams feature is not enabled.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, "load", course_key)

        if not is_feature_enabled(course):
            raise Http404

        if not CourseEnrollment.is_enrolled(request.user, course.id) and not has_access(
            request.user, "staff", course, course.id
        ):
            raise Http404

        # Even though sorting is done outside of the serializer, sort_order needs to be passed
        # to the serializer so that the paginated results indicate how they were sorted.
        sort_order = "name"
        topics = get_alphabetical_topics(course)
        topics_page = Paginator(topics, TOPICS_PER_PAGE).page(1)
        # BulkTeamCountPaginatedTopicSerializer will add team counts to the topics in a single
        # bulk operation per page.
        topics_serializer = BulkTeamCountPaginatedTopicSerializer(
            instance=topics_page, context={"course_id": course.id, "sort_order": sort_order}
        )
        user = request.user

        team_memberships = CourseTeamMembership.get_memberships(request.user.username, [course.id])
        team_memberships_page = Paginator(team_memberships, TEAM_MEMBERSHIPS_PER_PAGE).page(1)
        team_memberships_serializer = PaginatedMembershipSerializer(
            instance=team_memberships_page, context={"expand": ("team", "user"), "request": request}
        )

        context = {
            "course": course,
            "topics": topics_serializer.data,
            # It is necessary to pass both privileged and staff because only privileged users can
            # administer discussion threads, but both privileged and staff users are allowed to create
            # multiple teams (since they are not automatically added to teams upon creation).
            "user_info": {
                "username": user.username,
                "privileged": has_discussion_privileges(user, course_key),
                "staff": bool(has_access(user, "staff", course_key)),
                "team_memberships_data": team_memberships_serializer.data,
            },
            "topic_url": reverse(
                "topics_detail", kwargs={"topic_id": "topic_id", "course_id": str(course_id)}, request=request
            ),
            "topics_url": reverse("topics_list", request=request),
            "teams_url": reverse("teams_list", request=request),
            "teams_detail_url": reverse("teams_detail", args=["team_id"]),
            "team_memberships_url": reverse("team_membership_list", request=request),
            "team_membership_detail_url": reverse("team_membership_detail", args=["team_id", user.username]),
            "languages": [
                [lang[0], _(lang[1])] for lang in settings.ALL_LANGUAGES
            ],  # pylint: disable=translation-of-non-string
            "countries": list(countries),
            "disable_courseware_js": True,
            "teams_base_url": reverse("teams_dashboard", request=request, kwargs={"course_id": course_id}),
        }
        return render_to_response("teams/teams.html", context)