Commit e9994a92 by Zia Fazal Committed by Jonathan Piacenti

Fixed malformed uri issue with course resources

parent f3465287
......@@ -211,6 +211,9 @@ class CoursesApiTests(TestCase):
confirm_uri = self.test_server_prefix + test_uri
self.assertEqual(response.data['uri'], confirm_uri)
self.assertGreater(len(response.data['content']), 0)
for resource in response.data['resources']:
response = self.do_get(resource['uri'])
self.assertEqual(response.status_code, 200)
def test_courses_detail_get_notfound(self):
test_uri = self.base_courses_uri + '/' + self.test_bogus_course_id
......
......@@ -26,27 +26,12 @@ from student.models import CourseEnrollment, CourseEnrollmentAllowed
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import Location, InvalidLocationError
from api_manager.permissions import SecureAPIView, SecureListAPIView
from api_manager.utils import generate_base_uri
from .serializers import CourseModuleCompletionSerializer
log = logging.getLogger(__name__)
def _generate_base_uri(request):
"""
Constructs the protocol:host:path component of the resource uri
"""
protocol = 'http'
if request.is_secure():
protocol = protocol + 's'
resource_uri = '{}://{}{}'.format(
protocol,
request.get_host(),
request.get_full_path()
)
return resource_uri
def _get_content_children(content, content_type=None):
"""
Parses the provided content object looking for children
......@@ -334,7 +319,7 @@ class CourseContentDetail(SecureAPIView):
"""
store = modulestore()
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
content_type = request.QUERY_PARAMS.get('type', None)
response_data['uri'] = base_uri
if course_id != content_id:
......@@ -366,10 +351,11 @@ class CourseContentDetail(SecureAPIView):
course_id,
children
)
base_uri_without_qs = generate_base_uri(request, True)
response_data['resources'] = []
resource_uri = '{}/users'.format(base_uri)
resource_uri = '{}/users'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
resource_uri = '{}/groups'.format(base_uri)
resource_uri = '{}/groups'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
status_code = status.HTTP_200_OK
else:
......@@ -450,20 +436,21 @@ class CoursesDetail(SecureAPIView):
course_descriptor.id,
course_descriptor
)
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
base_uri_without_qs = generate_base_uri(request, True)
response_data['resources'] = []
resource_uri = '{}/content/'.format(base_uri)
resource_uri = '{}/content/'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
resource_uri = '{}/groups/'.format(base_uri)
resource_uri = '{}/groups/'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
resource_uri = '{}/overview/'.format(base_uri)
resource_uri = '{}/overview/'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
resource_uri = '{}/updates/'.format(base_uri)
resource_uri = '{}/updates/'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
resource_uri = '{}/static_tabs/'.format(base_uri)
resource_uri = '{}/static_tabs/'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
resource_uri = '{}/users/'.format(base_uri)
resource_uri = '{}/users/'.format(base_uri_without_qs)
response_data['resources'].append({'uri': resource_uri})
return Response(response_data, status=status.HTTP_200_OK)
......@@ -492,7 +479,7 @@ class CoursesGroupsList(SecureAPIView):
"""
response_data = {}
group_id = request.DATA['group_id']
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
existing_course = get_course(course_id)
except ValueError:
......@@ -569,7 +556,7 @@ class CoursesGroupsDetail(SecureAPIView):
except ObjectDoesNotExist:
return Response({}, status=status.HTTP_404_NOT_FOUND)
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
response_data['course_id'] = course_id
response_data['group_id'] = group_id
......@@ -585,7 +572,7 @@ class CoursesGroupsDetail(SecureAPIView):
except ObjectDoesNotExist:
pass
response_data = {}
response_data['uri'] = _generate_base_uri(request)
response_data['uri'] = generate_base_uri(request)
return Response(response_data, status=status.HTTP_204_NO_CONTENT)
......@@ -795,7 +782,7 @@ class CoursesUsersList(SecureAPIView):
GET /api/courses/{course_id/users}
"""
response_data = OrderedDict()
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
try:
existing_course = get_course(course_id)
......@@ -840,7 +827,7 @@ class CoursesUsersDetail(SecureAPIView):
"""
GET /api/courses/{course_id}/users/{user_id}
"""
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data = {
'course_id': course_id,
'user_id': user_id,
......@@ -887,7 +874,7 @@ class CoursesUsersDetail(SecureAPIView):
if user:
CourseEnrollment.unenroll(user, course_id)
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
return Response(response_data, status=status.HTTP_204_NO_CONTENT)
......@@ -932,7 +919,7 @@ class CourseContentGroupsList(SecureAPIView):
except ObjectDoesNotExist:
return Response({}, status=status.HTTP_404_NOT_FOUND)
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = '{}/{}'.format(base_uri, existing_profile.group_id)
response_data['course_id'] = course_descriptor.id
response_data['content_id'] = existing_content.id
......
......@@ -357,15 +357,13 @@ class GroupsApiTests(ModuleStoreTestCase):
is_active = True
for num in range(0, 5):
local_username = self.test_username + str(randint(11, 99))
local_email = str(randint(11,99)) + self.test_email
if num == 3:
is_active = False
data = {
'email': local_email,
'username': local_username,
'email': '{}{}'.format(num, self.test_email),
'username': '{}{}'.format(num, self.test_username),
'password': self.test_password,
'first_name': self.test_first_name,
'last_name': self.test_last_name,
......
......@@ -16,30 +16,11 @@ from api_manager.models import GroupRelationship, CourseGroupRelationship, Group
from xmodule.modulestore.django import modulestore
from api_manager.permissions import SecureAPIView
from xmodule.modulestore import Location, InvalidLocationError
from api_manager.utils import str2bool
from api_manager.utils import str2bool, generate_base_uri
RELATIONSHIP_TYPES = {'hierarchical': 'h', 'graph': 'g'}
def _generate_base_uri(request, include_query_string=True):
"""
Constructs the protocol:host:path component of the resource uri
"""
protocol = 'http'
if request.is_secure():
protocol = protocol + 's'
if include_query_string:
path_to_use = request.get_full_path()
else:
path_to_use = request.path_info
resource_uri = '{}://{}{}'.format(
protocol,
request.get_host(),
path_to_use
)
return resource_uri
class GroupsList(SecureAPIView):
"""
### The GroupsList view allows clients to retrieve/append a list of Group entities
......@@ -84,7 +65,6 @@ class GroupsList(SecureAPIView):
if group_type is None:
return Response({}, status=status.HTTP_400_BAD_REQUEST)
response_data = {}
base_uri = _generate_base_uri(request)
# Group name must be unique, but we need to support dupes
group = Group.objects.create(name=str(uuid.uuid4()))
original_group_name = request.DATA.get('name', None)
......@@ -106,12 +86,9 @@ class GroupsList(SecureAPIView):
data=json.dumps(data)
)
response_data = {
'id': group.id,
'name': profile.name,
}
base_uri = _generate_base_uri(request)
response_data['uri'] = '{}/{}'.format(_generate_base_uri(request, False), group.id)
response_data['id'] = group.id
response_data['name'] = profile.name
response_data['uri'] = '{}/{}'.format(generate_base_uri(request, True), group.id)
response_status = status.HTTP_201_CREATED
return Response(response_data, status=response_status)
......@@ -135,7 +112,7 @@ class GroupsList(SecureAPIView):
item_data['type'] = profile.group_type
if profile.data:
item_data['data'] = json.loads(profile.data)
item_data['uri'] = '{}/{}'.format(_generate_base_uri(request, False), profile.group_id)
item_data['uri'] = '{}/{}'.format(generate_base_uri(request, True), profile.group_id)
response_data.append(item_data)
return Response(response_data, status=status.HTTP_200_OK)
......@@ -173,7 +150,6 @@ class GroupsDetail(SecureAPIView):
POST /api/groups/{group_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
try:
existing_group = Group.objects.get(id=group_id)
except ObjectDoesNotExist:
......@@ -189,7 +165,7 @@ class GroupsDetail(SecureAPIView):
response_data['id'] = existing_group.id
response_data['name'] = profile.name
response_data['type'] = profile.group_type
response_data['uri'] = _generate_base_uri(request)
response_data['uri'] = generate_base_uri(request)
return Response(response_data, status=status.HTTP_200_OK)
def get(self, request, group_id):
......@@ -197,7 +173,7 @@ class GroupsDetail(SecureAPIView):
GET /api/groups/{group_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
existing_group = Group.objects.get(id=group_id)
except ObjectDoesNotExist:
......@@ -252,7 +228,7 @@ class GroupsUsersList(SecureAPIView):
"""
POST /api/groups/{group_id}/users/
"""
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
existing_group = Group.objects.get(id=group_id)
except ObjectDoesNotExist:
......@@ -323,7 +299,7 @@ class GroupsUsersDetail(SecureAPIView):
GET /api/groups/{group_id}/users/{user_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
existing_group = Group.objects.get(id=group_id)
existing_relationship = existing_group.user_set.get(id=user_id)
......@@ -391,7 +367,7 @@ class GroupsGroupsList(SecureAPIView):
response_data = {}
to_group_id = request.DATA['group_id']
relationship_type = request.DATA['relationship_type']
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = '{}/{}'.format(base_uri, to_group_id)
response_data['group_id'] = str(to_group_id)
response_data['relationship_type'] = relationship_type
......@@ -426,7 +402,7 @@ class GroupsGroupsList(SecureAPIView):
from_group_relationship = None
response_data = []
if from_group_relationship:
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
group_type = request.QUERY_PARAMS.get('type', None)
child_groups = GroupRelationship.objects.filter(parent_group_id=group_id)
linked_groups = from_group_relationship.get_linked_group_relationships()
......@@ -473,7 +449,7 @@ class GroupsGroupsDetail(SecureAPIView):
GET /api/groups/{group_id}/groups/{related_group_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
response_data['from_group_id'] = group_id
response_data['to_group_id'] = related_group_id
......@@ -549,7 +525,7 @@ class GroupsCoursesList(SecureAPIView):
store = modulestore()
course_id = request.DATA['course_id']
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = '{}/{}'.format(base_uri, course_id)
existing_course = store.get_course(course_id)
......@@ -613,7 +589,7 @@ class GroupsCoursesDetail(SecureAPIView):
GET /api/groups/{group_id}/courses/{course_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
try:
existing_group = Group.objects.get(id=group_id)
......
......@@ -16,7 +16,7 @@ from rest_framework.response import Response
from util.bad_request_rate_limiter import BadRequestRateLimiter
from api_manager.utils import generate_base_uri
from api_manager.users.serializers import UserSerializer
from student.models import (
......@@ -24,22 +24,6 @@ from student.models import (
)
AUDIT_LOG = logging.getLogger("audit")
def _generate_base_uri(request):
"""
Constructs the protocol:host:path component of the resource uri
"""
protocol = 'http'
if request.is_secure():
protocol = protocol + 's'
resource_uri = '{}://{}{}'.format(
protocol,
request.get_host(),
request.get_full_path()
)
return resource_uri
class SessionsList(SecureAPIView):
""" Inherit with SecureAPIView """
......@@ -55,7 +39,7 @@ class SessionsList(SecureAPIView):
response_data['message'] = _('Rate limit exceeded in api login.')
return Response(response_data, status=status.HTTP_403_FORBIDDEN)
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
existing_user = User.objects.get(username=request.DATA['username'])
except ObjectDoesNotExist:
......@@ -121,7 +105,7 @@ class SessionsDetail(SecureAPIView):
GET retrieves an existing system session
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
engine = import_module(settings.SESSION_ENGINE)
session = engine.SessionStore(session_id)
try:
......@@ -145,7 +129,6 @@ class SessionsDetail(SecureAPIView):
DELETE flushes an existing system session from the system
"""
response_data = {}
base_uri = _generate_base_uri(request)
engine = import_module(settings.SESSION_ENGINE)
session = engine.SessionStore(session_id)
user_id = session[SESSION_KEY]
......
......@@ -5,30 +5,14 @@ from rest_framework import status
from rest_framework.response import Response
from api_manager.permissions import SecureAPIView
from api_manager.permissions import ApiKeyHeaderPermission
def _generate_base_uri(request):
"""
Constructs the protocol:host:path component of the resource uri
"""
protocol = 'http'
if request.is_secure():
protocol = protocol + 's'
resource_uri = '{}://{}{}'.format(
protocol,
request.get_host(),
request.get_full_path()
)
return resource_uri
from api_manager.utils import generate_base_uri
class SystemDetail(SecureAPIView):
"""Manages system-level information about the Open edX API"""
def get(self, request):
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data = {}
response_data['name'] = "Open edX System API"
response_data['description'] = "System interface for managing groups, users, and sessions."
......@@ -41,7 +25,7 @@ class ApiDetail(SecureAPIView):
"""Manages top-level information about the Open edX API"""
def get(self, request):
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data = {}
response_data['name'] = "Open edX API"
response_data['description'] = "Machine interface for interactions with Open edX."
......
......@@ -17,6 +17,7 @@ from django.db.models import Q
from api_manager.permissions import SecureAPIView, SecureListAPIView
from api_manager.models import GroupProfile
from api_manager.organizations.serializers import OrganizationSerializer
from api_manager.utils import generate_base_uri
from projects.serializers import BasicWorkgroupSerializer
from .serializers import UserSerializer
......@@ -40,21 +41,6 @@ log = logging.getLogger(__name__)
AUDIT_LOG = logging.getLogger("audit")
def _generate_base_uri(request):
"""
Constructs the protocol:host:path component of the resource uri
"""
protocol = 'http'
if request.is_secure():
protocol = protocol + 's'
resource_uri = '{}://{}{}'.format(
protocol,
request.get_host(),
request.get_full_path()
)
return resource_uri
def _serialize_user_profile(response_data, user_profile):
"""This function serialize user profile """
response_data['title'] = user_profile.title
......@@ -193,7 +179,7 @@ class UsersList(SecureListAPIView):
POST /api/users/
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
email = request.DATA['email']
username = request.DATA['username']
password = request.DATA['password']
......@@ -335,7 +321,7 @@ class UsersDetail(SecureAPIView):
GET /api/users/{user_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
existing_user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
......@@ -360,8 +346,7 @@ class UsersDetail(SecureAPIView):
POST /api/users/{user_id}
"""
response_data = {}
base_uri = _generate_base_uri(request)
response_data['uri'] = _generate_base_uri(request)
response_data['uri'] = generate_base_uri(request)
first_name = request.DATA.get('first_name') # Used in multiple spots below
last_name = request.DATA.get('last_name') # Used in multiple spots below
# Add some rate limiting here by re-using the RateLimitMixin as a helper class
......@@ -523,7 +508,7 @@ class UsersGroupsList(SecureAPIView):
"""
response_data = {}
group_id = request.DATA['group_id']
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = '{}/{}'.format(base_uri, str(group_id))
try:
existing_user = User.objects.get(id=user_id)
......@@ -552,7 +537,7 @@ class UsersGroupsList(SecureAPIView):
return Response({}, status=status.HTTP_404_NOT_FOUND)
group_type = request.QUERY_PARAMS.get('type', None)
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data['uri'] = base_uri
groups = existing_user.groups.all()
if group_type:
......@@ -590,7 +575,7 @@ class UsersGroupsDetail(SecureAPIView):
return Response({}, status=status.HTTP_404_NOT_FOUND)
response_data['user_id'] = existing_user.id
response_data['group_id'] = existing_relationship.id
response_data['uri'] = _generate_base_uri(request)
response_data['uri'] = generate_base_uri(request)
return Response(response_data, status=status.HTTP_200_OK)
def delete(self, request, user_id, group_id):
......@@ -633,7 +618,7 @@ class UsersCoursesList(SecureAPIView):
course_descriptor = store.get_course(course_id)
except (ObjectDoesNotExist, ValueError):
return Response({}, status=status.HTTP_404_NOT_FOUND)
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
course_enrollment = CourseEnrollment.enroll(user, course_id)
response_data['uri'] = '{}/{}'.format(base_uri, course_id)
response_data['id'] = course_id
......@@ -646,7 +631,7 @@ class UsersCoursesList(SecureAPIView):
GET /api/users/{user_id}/courses/
"""
store = modulestore()
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
......@@ -702,7 +687,7 @@ class UsersCoursesDetail(SecureAPIView):
POST /api/users/{user_id}/courses/{course_id}
"""
store = modulestore()
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
response_data = {}
response_data['uri'] = base_uri
try:
......@@ -728,7 +713,7 @@ class UsersCoursesDetail(SecureAPIView):
"""
store = modulestore()
response_data = {}
base_uri = _generate_base_uri(request)
base_uri = generate_base_uri(request)
try:
user = User.objects.get(id=user_id, is_active=True)
course_descriptor = store.get_course(course_id)
......
......@@ -34,3 +34,13 @@ def str2bool(value):
convert string to bool
"""
return value.lower() in ("true",)
def generate_base_uri(request, strip_qs=False):
"""
Build absolute uri
"""
if strip_qs:
return request.build_absolute_uri(request.path) # Don't need querystring that why giving location parameter
else:
return request.build_absolute_uri()
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