Commit 4f164247 by Matt Drayer Committed by Jonathan Piacenti

mattdrayer/api-users-courses-roles: Added support for setting user roles

parent e5a025df
......@@ -17,6 +17,8 @@ from django.test.utils import override_settings
from capa.tests.response_xml_factory import StringResponseXMLFactory
from courseware.tests.factories import StudentModuleFactory
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
from django_comment_common.models import Role, FORUM_ROLE_MODERATOR
from instructor.access import allow_access
from student.tests.factories import UserFactory, CourseEnrollmentFactory
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
......@@ -189,6 +191,10 @@ class CoursesApiTests(TestCase):
self.client = SecureClient()
cache.clear()
Role.objects.get_or_create(
name=FORUM_ROLE_MODERATOR,
course_id=self.course.id)
def do_get(self, uri):
"""Submit an HTTP GET request"""
headers = {
......@@ -1778,3 +1784,90 @@ class CoursesApiTests(TestCase):
self.assertEqual(len(response.data['results']), 1)
self.assertEqual(response.data['results'][0]['city'], 'Denver')
self.assertEqual(response.data['results'][0]['count'], 5)
def test_courses_roles_list_get(self):
allow_access(self.course, self.users[0], 'staff')
allow_access(self.course, self.users[1], 'instructor')
allow_access(self.course, self.users[2], 'staff')
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 3)
# filter roleset by user
user_id = {'user_id': '{}'.format(self.users[0].id)}
test_uri = '{}?{}'.format(test_uri, urlencode(user_id))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
def test_courses_roles_list_get_invalid_course(self):
test_uri = '/api/courses/{}/roles/'.format(self.test_bogus_course_id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_courses_roles_list_post(self):
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 0)
data = {'user_id': self.users[0].id, 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
def test_courses_roles_list_post_invalid_course(self):
test_uri = '/api/courses/{}/roles/'.format(self.test_bogus_course_id)
data = {'user_id': self.users[0].id, 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 404)
def test_courses_roles_list_post_invalid_user(self):
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
data = {'user_id': 23423, 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 404)
def test_courses_roles_list_post_invalid_role(self):
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
data = {'user_id': self.users[0].id, 'role': 'invalid_role'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 400)
def test_courses_roles_users_detail_delete(self):
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
data = {'user_id': self.users[0].id, 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(test_uri)
self.assertEqual(len(response.data), 1)
delete_uri = '{}instructor/users/{}'.format(test_uri, self.users[0].id)
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 204)
response = self.do_get(test_uri)
self.assertEqual(len(response.data), 0)
def test_courses_roles_users_detail_delete_invalid_course(self):
test_uri = '/api/courses/{}/roles/'.format(self.test_bogus_course_id)
delete_uri = '{}instructor/users/{}'.format(test_uri, self.users[0].id)
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 404)
def test_courses_roles_users_detail_delete_invalid_user(self):
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
delete_uri = '{}instructor/users/291231'.format(test_uri)
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 404)
def test_courses_roles_users_detail_delete_invalid_role(self):
test_uri = '/api/courses/{}/roles/'.format(unicode(self.course.id))
delete_uri = '{}invalid_role/users/{}'.format(test_uri, self.users[0].id)
print delete_uri
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 404)
......@@ -20,19 +20,21 @@ urlpatterns = patterns(
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/groups/(?P<group_id>[0-9]+)$', courses_views.CoursesGroupsDetail.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/groups/*$', courses_views.CoursesGroupsList.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/overview/*$', courses_views.CoursesOverview.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/updates/*$', courses_views.CoursesUpdates.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/static_tabs/(?P<tab_id>[a-zA-Z0-9_+\/:]+)$', courses_views.CoursesStaticTabsDetail.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/static_tabs/*$', courses_views.CoursesStaticTabsList.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/users/(?P<user_id>[0-9]+)$', courses_views.CoursesUsersDetail.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/users/*$', courses_views.CoursesUsersList.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/completions/*$', courses_views.CourseModuleCompletionList.as_view(), name='completion-list'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/projects/*$', courses_views.CoursesProjectList.as_view(), name='courseproject-list'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/*$', courses_views.CourseMetrics.as_view(), name='course-metrics'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/proficiency/leaders/*$', courses_views.CoursesLeadersList.as_view(), name='course-metrics-proficiency-leaders'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/cities/$', courses_views.CoursesCitiesMetrics.as_view(), name='courses-cities-metrics'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/completions/leaders/*$', courses_views.CoursesCompletionsLeadersList.as_view(), name='course-metrics-completions-leaders'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/workgroups/*$', courses_views.CoursesWorkgroupsList.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/proficiency/leaders/*$', courses_views.CoursesLeadersList.as_view(), name='course-metrics-proficiency-leaders'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/social/$', courses_views.CoursesSocialMetrics.as_view(), name='courses-social-metrics'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/cities/$', courses_views.CoursesCitiesMetrics.as_view(), name='courses-cities-metrics'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/roles/(?P<role>[a-z_]+)/users/(?P<user_id>[0-9]+)*$', courses_views.CoursesRolesUsersDetail.as_view(), name='courses-roles-users-detail'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/roles/*$', courses_views.CoursesRolesList.as_view(), name='courses-roles-list'),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/updates/*$', courses_views.CoursesUpdates.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/users/(?P<user_id>[0-9]+)$', courses_views.CoursesUsersDetail.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/users/*$', courses_views.CoursesUsersList.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)/workgroups/*$', courses_views.CoursesWorkgroupsList.as_view()),
url(r'^(?P<course_id>[a-zA-Z0-9_+\/:]+)$', courses_views.CoursesDetail.as_view()),
url(r'/*$^', courses_views.CoursesList.as_view()),
)
......
......@@ -6,6 +6,7 @@ import itertools
from lxml import etree
from StringIO import StringIO
from django.conf import settings
from django.contrib.auth.models import Group, User
from django.core.exceptions import ObjectDoesNotExist
......@@ -20,7 +21,11 @@ from rest_framework.response import Response
from courseware.courses import get_course_about_section, get_course_info_section
from courseware.models import StudentModule
from courseware.views import get_static_tab_contents
from django_comment_common.models import FORUM_ROLE_MODERATOR
from instructor.access import allow_access, revoke_access, update_forum_role
from student.models import CourseEnrollment, CourseEnrollmentAllowed
from student.roles import CourseInstructorRole, CourseStaffRole
from xmodule.modulestore.django import modulestore
from api_manager.courseware_access import get_course, get_course_child
......@@ -31,7 +36,6 @@ from api_manager.users.serializers import UserSerializer, UserCountByCitySeriali
from api_manager.utils import generate_base_uri
from projects.models import Project, Workgroup
from projects.serializers import ProjectSerializer, BasicWorkgroupSerializer
from .serializers import CourseModuleCompletionSerializer
from .serializers import GradeSerializer, CourseLeadersSerializer, CourseCompletionsLeadersSerializer
......@@ -975,7 +979,7 @@ class CoursesUsersList(SecureAPIView):
def get(self, request, course_id):
"""
GET /api/courses/{course_id}
GET /api/courses/{course_id}/users
"""
orgs = request.QUERY_PARAMS.get('organizations')
groups = request.QUERY_PARAMS.get('groups', None)
......@@ -1644,3 +1648,96 @@ class CoursesCitiesMetrics(SecureListAPIView):
queryset = queryset.values('profile__city').annotate(count=Count('profile__city'))\
.filter(count__gt=0).order_by('-count')
return queryset
class CoursesRolesList(SecureAPIView):
"""
### The CoursesRolesList view allows clients to interact with the Course's roleset
- URI: ```/api/courses/{course_id}/roles```
- GET: Returns a JSON representation of the specified Course roleset
### Use Cases/Notes:
* Use the CoursesRolesList view to manage a User's TA status
* Use GET to retrieve the set of roles configured for a particular course
"""
def get(self, request, course_id): # pylint: disable=W0613
"""
GET /api/courses/{course_id}/roles/
"""
course_id = self.kwargs['course_id']
course_descriptor, course_key, course_content = get_course(self.request, self.request.user, course_id, depth=None) # pylint: disable=W0612
if not course_descriptor:
raise Http404
response_data = []
instructors = CourseInstructorRole(course_key).users_with_role()
for instructor in instructors:
response_data.append({'id': instructor.id, 'role': 'instructor'})
staff = CourseStaffRole(course_key).users_with_role()
for admin in staff:
response_data.append({'id': admin.id, 'role': 'staff'})
user_id = self.request.QUERY_PARAMS.get('user_id', None)
if user_id:
response_data = list([item for item in response_data if int(item['id']) == int(user_id)])
return Response(response_data, status=status.HTTP_200_OK)
def post(self, request, course_id):
"""
POST /api/courses/{course_id}/roles/
"""
course_id = self.kwargs['course_id']
course_descriptor, course_key, course_content = get_course(self.request, self.request.user, course_id, depth=None) # pylint: disable=W0612
if not course_descriptor:
raise Http404
user_id = request.DATA.get('user_id', None)
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
raise Http404
role = request.DATA.get('role', None)
try:
allow_access(course_descriptor, user, role)
update_forum_role(course_key, user, FORUM_ROLE_MODERATOR, 'allow')
except ValueError:
return Response({}, status=status.HTTP_400_BAD_REQUEST)
return Response(request.DATA, status=status.HTTP_201_CREATED)
class CoursesRolesUsersDetail(SecureAPIView):
"""
### The CoursesUsersRolesDetail view allows clients to interact with a specific Course Role
- URI: ```/api/courses/{course_id}/roles/{role}/users/{user_id}```
- DELETE: Removes an existing Course Role specification
### Use Cases/Notes:
* Use the DELETE operation to revoke a particular role for the specified user
"""
def delete(self, request, course_id, role, user_id): # pylint: disable=W0613
"""
DELETE /api/courses/{course_id}/roles/{role}/users/{user_id}
"""
course_id = self.kwargs['course_id']
course_descriptor, course_key, course_content = get_course(self.request, self.request.user, course_id, depth=None) # pylint: disable=W0612
if not course_descriptor:
return Response({}, status=status.HTTP_404_NOT_FOUND)
user_id = self.kwargs['user_id']
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
return Response({}, status=status.HTTP_404_NOT_FOUND)
role = self.kwargs['role']
try:
revoke_access(course_descriptor, user, role)
update_forum_role(course_key, user, FORUM_ROLE_MODERATOR, 'revoke')
except ValueError:
return Response({}, status=status.HTTP_404_NOT_FOUND)
return Response({}, status=status.HTTP_204_NO_CONTENT)
......@@ -21,3 +21,9 @@ class UserCountByCitySerializer(serializers.Serializer):
""" Serializer for user count by city """
city = serializers.CharField(source='profile__city')
count = serializers.IntegerField()
class UserRolesSerializer(serializers.Serializer):
""" Serializer for user roles """
course_id = serializers.CharField(source='course_id')
role = serializers.CharField(source='role')
......@@ -19,6 +19,8 @@ from django.test.utils import override_settings
from capa.tests.response_xml_factory import StringResponseXMLFactory
from courseware.tests.factories import StudentModuleFactory
from django_comment_common.models import Role, FORUM_ROLE_MODERATOR
from instructor.access import allow_access
from projects.models import Project
from student.tests.factories import UserFactory
from student.models import anonymous_id_for_user
......@@ -93,6 +95,10 @@ class UsersApiTests(ModuleStoreTestCase):
self.client = SecureClient()
cache.clear()
Role.objects.get_or_create(
name=FORUM_ROLE_MODERATOR,
course_id=self.course.id)
def do_post(self, uri, data):
"""Submit an HTTP POST request"""
headers = {
......@@ -1346,3 +1352,106 @@ class UsersApiTests(ModuleStoreTestCase):
test_uri = '/api/users/{}/courses/{}/metrics/social/'.format(12345, self.course.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_users_roles_list_get(self):
allow_access(self.course, self.user, 'staff')
course2 = CourseFactory.create(
display_name="TEST COURSE2",
start=datetime(2014, 6, 16, 14, 30),
end=datetime(2015, 1, 16, 14, 30)
)
allow_access(course2, self.user, 'instructor')
course3 = CourseFactory.create(
display_name="TEST COURSE3",
start=datetime(2014, 6, 16, 14, 30),
end=datetime(2015, 1, 16, 14, 30)
)
allow_access(course3, self.user, 'staff')
test_uri = '/api/users/{}/roles/'.format(self.user.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['count'], 3)
# filter roleset by course
course_id = {'course_id': '{}'.format(unicode(course3.id))}
test_uri = '{}?{}'.format(test_uri, urlencode(course_id))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['count'], 1)
def test_users_roles_list_get_invalid_user(self):
test_uri = '/api/users/23423/roles/'
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_users_roles_list_get_invalid_course(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
course_id = {'course_id': '{}'.format(unicode(self.test_bogus_course_id))}
test_uri = '{}?{}'.format(test_uri, urlencode(course_id))
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_users_roles_list_post(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['count'], 0)
data = {'course_id': unicode(self.course.id), 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['count'], 1)
def test_users_roles_list_post_invalid_user(self):
test_uri = '/api/users/2131/roles/'
data = {'course_id': unicode(self.course.id), 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 404)
def test_users_roles_list_post_invalid_course(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
data = {'course_id': self.test_bogus_course_id, 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 404)
def test_users_roles_list_post_invalid_role(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
data = {'course_id': unicode(self.course.id), 'role': 'invalid_role'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 400)
def test_users_roles_courses_detail_delete(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
data = {'course_id': unicode(self.course.id), 'role': 'instructor'}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get(test_uri)
self.assertEqual(response.data['count'], 1)
delete_uri = '{}instructor/courses/{}'.format(test_uri, unicode(self.course.id))
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 204)
response = self.do_get(test_uri)
self.assertEqual(response.data['count'], 0)
def test_users_roles_courses_detail_delete_invalid_course(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
delete_uri = '{}instructor/courses/{}'.format(test_uri, self.test_bogus_course_id)
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 404)
def test_users_roles_courses_detail_delete_invalid_user(self):
test_uri = '/api/users/124134/roles/'
delete_uri = '{}instructor/courses/{}'.format(test_uri, unicode(self.course.id))
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 404)
def test_users_roles_courses_detail_delete_invalid_role(self):
test_uri = '/api/users/{}/roles/'.format(self.user.id)
delete_uri = '{}invalid_role/courses/{}'.format(test_uri, unicode(self.course.id))
response = self.do_delete(delete_uri)
self.assertEqual(response.status_code, 404)
......@@ -22,6 +22,8 @@ urlpatterns = patterns(
url(r'^(?P<user_id>[a-zA-Z0-9]+)/preferences$', users_views.UsersPreferences.as_view(), name='users-preferences-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/preferences/(?P<preference_id>[a-zA-Z0-9_]+)$', users_views.UsersPreferencesDetail.as_view(), name='users-preferences-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/organizations/$', users_views.UsersOrganizationsList.as_view(), name='users-organizations-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/roles/(?P<role>[a-z_]+)/courses/(?P<course_id>[a-zA-Z0-9_+\/:]+)$', users_views.UsersRolesCoursesDetail.as_view(), name='users-roles-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/roles/*$', users_views.UsersRolesList.as_view(), name='users-roles-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/workgroups/$', users_views.UsersWorkgroupsList.as_view(), name='users-workgroups-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)$', users_views.UsersDetail.as_view(), name='apimgr-users-detail'),
url(r'/*$^', users_views.UsersList.as_view(), name='apimgr-users-list'),
......
......@@ -15,37 +15,32 @@ from rest_framework import status
from rest_framework import filters
from rest_framework.response import Response
from api_manager.courseware_access import get_course, get_course_child, get_course_total_score
from api_manager.permissions import SecureAPIView, SecureListAPIView, IdsInFilterBackend, HasOrgsFilterBackend
from api_manager.models import GroupProfile, APIUser as User
from api_manager.organizations.serializers import OrganizationSerializer
from api_manager.courses.serializers import CourseModuleCompletionSerializer
from api_manager.utils import generate_base_uri
from projects.serializers import BasicWorkgroupSerializer
from .serializers import UserSerializer, UserCountByCitySerializer
from courseware import module_render
from courseware import grades, module_render
from courseware.model_data import FieldDataCache
from courseware.models import StudentModule
from courseware.views import get_module_for_descriptor, save_child_position, get_current_child
from courseware.views import save_child_position, get_current_child
from django_comment_common.models import FORUM_ROLE_MODERATOR
from instructor.access import allow_access, revoke_access, update_forum_role
from lang_pref import LANGUAGE_KEY
from lms.lib.comment_client.user import User as CommentUser
from lms.lib.comment_client.utils import CommentClientRequestError
from student.models import CourseEnrollment, PasswordHistory, UserProfile
from openedx.core.djangoapps.user_api.models import UserPreference
from xmodule.modulestore.django import modulestore
from student.roles import CourseInstructorRole, CourseStaffRole, UserBasedRole
from util.bad_request_rate_limiter import BadRequestRateLimiter
from util.password_policy_validators import (
validate_password_length, validate_password_complexity,
validate_password_dictionary
)
from util.bad_request_rate_limiter import BadRequestRateLimiter
from courseware import grades
from lms.lib.comment_client.user import User as CommentUser
from lms.lib.comment_client.utils import CommentClientRequestError
from api_manager.courses.serializers import CourseModuleCompletionSerializer
from api_manager.courseware_access import get_course, get_course_child, get_course_total_score
from api_manager.permissions import SecureAPIView, SecureListAPIView, IdsInFilterBackend, HasOrgsFilterBackend
from api_manager.models import GroupProfile, APIUser as User
from api_manager.organizations.serializers import OrganizationSerializer
from api_manager.utils import generate_base_uri
from projects.serializers import BasicWorkgroupSerializer
from .serializers import UserSerializer, UserCountByCitySerializer, UserRolesSerializer
log = logging.getLogger(__name__)
AUDIT_LOG = logging.getLogger("audit")
......@@ -713,8 +708,6 @@ class UsersCoursesDetail(SecureAPIView):
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
response_data['position'] = content_position
return Response(response_data, status=status.HTTP_200_OK)
def get(self, request, user_id, course_id):
......@@ -1083,3 +1076,95 @@ class UsersMetricsCitiesList(SecureListAPIView):
queryset = queryset.values('profile__city').annotate(count=Count('profile__city'))\
.filter(count__gt=0).order_by('-count')
return queryset
class UsersRolesList(SecureListAPIView):
"""
### The UsersRolesList view allows clients to interact with the User's roleset
- URI: ```/api/users/{user_id}/courses/{course_id}/roles```
- GET: Returns a JSON representation of the specified Course roleset
### Use Cases/Notes:
* Use the UsersRolesList view to manage a User's TA status
* Use GET to retrieve the set of roles a User plays for a particular course
"""
serializer_class = UserRolesSerializer
def get_queryset(self):
user_id = self.kwargs['user_id']
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
raise Http404
instructor_courses = UserBasedRole(user, CourseInstructorRole.ROLE).courses_with_role()
staff_courses = UserBasedRole(user, CourseStaffRole.ROLE).courses_with_role()
queryset = instructor_courses | staff_courses
course_id = self.request.QUERY_PARAMS.get('course_id', None)
if course_id:
course_descriptor, course_key, course_content = get_course(self.request, user, course_id, depth=None) # pylint: disable=W0612
if not course_descriptor:
raise Http404
queryset = queryset.filter(course_id=course_key)
return queryset
def post(self, request, user_id):
"""
POST /api/users/{user_id}/roles/
"""
user_id = self.kwargs['user_id']
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
raise Http404
course_id = request.DATA.get('course_id', None)
course_descriptor, course_key, course_content = get_course(self.request, self.request.user, course_id, depth=None) # pylint: disable=W0612
if not course_descriptor:
raise Http404
role = request.DATA.get('role', None)
try:
allow_access(course_descriptor, user, role)
update_forum_role(course_key, user, FORUM_ROLE_MODERATOR, 'allow')
except ValueError:
return Response({}, status=status.HTTP_400_BAD_REQUEST)
return Response(request.DATA, status=status.HTTP_201_CREATED)
class UsersRolesCoursesDetail(SecureAPIView):
"""
### The UsersRolesCoursesDetail view allows clients to interact with a specific User/Course Role
- URI: ```/api/users/{user_id}/roles/{role}/courses/{course_id}/```
- DELETE: Removes an existing Course Role specification
### Use Cases/Notes:
* Use the DELETE operation to revoke a particular role for the specified user
"""
def delete(self, request, user_id, role, course_id): # pylint: disable=W0613
"""
DELETE /api/users/{user_id}/roles/{role}/courses/{course_id}
"""
course_id = self.kwargs['course_id']
print course_id
course_descriptor, course_key, course_content = get_course(self.request, self.request.user, course_id, depth=None) # pylint: disable=W0612
if not course_descriptor:
return Response({}, status=status.HTTP_404_NOT_FOUND)
user_id = self.kwargs['user_id']
print user_id
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
return Response({}, status=status.HTTP_404_NOT_FOUND)
role = self.kwargs['role']
try:
revoke_access(course_descriptor, user, role)
update_forum_role(course_key, user, FORUM_ROLE_MODERATOR, 'revoke')
except ValueError:
return Response({}, status=status.HTTP_404_NOT_FOUND)
return Response({}, status=status.HTTP_204_NO_CONTENT)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment