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)
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)
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))
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)
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)
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)
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)
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
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)
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) )
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)
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))
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)