Commit 17b5c212 by Christina Roberts

Merge pull request #1910 from edx/christina/locations

Create explicit Locations.
parents 258d3227 ec55d8c1
...@@ -5,6 +5,7 @@ import mock ...@@ -5,6 +5,7 @@ import mock
from django.test import TestCase from django.test import TestCase
from django.contrib.auth.models import User from django.contrib.auth.models import User
from xmodule.modulestore import Location
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from auth.authz import add_user_to_creator_group, remove_user_from_creator_group, is_user_in_creator_group,\ from auth.authz import add_user_to_creator_group, remove_user_from_creator_group, is_user_in_creator_group,\
...@@ -129,7 +130,7 @@ class CourseGroupTest(TestCase): ...@@ -129,7 +130,7 @@ class CourseGroupTest(TestCase):
""" Test case setup """ """ Test case setup """
self.creator = User.objects.create_user('testcreator', 'testcreator+courses@edx.org', 'foo') self.creator = User.objects.create_user('testcreator', 'testcreator+courses@edx.org', 'foo')
self.staff = User.objects.create_user('teststaff', 'teststaff+courses@edx.org', 'foo') self.staff = User.objects.create_user('teststaff', 'teststaff+courses@edx.org', 'foo')
self.location = 'i4x', 'mitX', '101', 'course', 'test' self.location = Location('i4x', 'mitX', '101', 'course', 'test')
def test_add_user_to_course_group(self): def test_add_user_to_course_group(self):
""" """
...@@ -181,7 +182,7 @@ class CourseGroupTest(TestCase): ...@@ -181,7 +182,7 @@ class CourseGroupTest(TestCase):
create_all_course_groups(self.creator, self.location) create_all_course_groups(self.creator, self.location)
add_user_to_course_group(self.creator, self.staff, self.location, STAFF_ROLE_NAME) add_user_to_course_group(self.creator, self.staff, self.location, STAFF_ROLE_NAME)
location2 = 'i4x', 'mitX', '103', 'course', 'test2' location2 = Location('i4x', 'mitX', '103', 'course', 'test2')
staff2 = User.objects.create_user('teststaff2', 'teststaff2+courses@edx.org', 'foo') staff2 = User.objects.create_user('teststaff2', 'teststaff2+courses@edx.org', 'foo')
create_all_course_groups(self.creator, location2) create_all_course_groups(self.creator, location2)
add_user_to_course_group(self.creator, staff2, location2, STAFF_ROLE_NAME) add_user_to_course_group(self.creator, staff2, location2, STAFF_ROLE_NAME)
...@@ -193,7 +194,7 @@ class CourseGroupTest(TestCase): ...@@ -193,7 +194,7 @@ class CourseGroupTest(TestCase):
create_all_course_groups(self.creator, self.location) create_all_course_groups(self.creator, self.location)
add_user_to_course_group(self.creator, self.staff, self.location, STAFF_ROLE_NAME) add_user_to_course_group(self.creator, self.staff, self.location, STAFF_ROLE_NAME)
location2 = 'i4x', 'mitX', '103', 'course', 'test2' location2 = Location('i4x', 'mitX', '103', 'course', 'test2')
creator2 = User.objects.create_user('testcreator2', 'testcreator2+courses@edx.org', 'foo') creator2 = User.objects.create_user('testcreator2', 'testcreator2+courses@edx.org', 'foo')
staff2 = User.objects.create_user('teststaff2', 'teststaff2+courses@edx.org', 'foo') staff2 = User.objects.create_user('teststaff2', 'teststaff2+courses@edx.org', 'foo')
create_all_course_groups(creator2, location2) create_all_course_groups(creator2, location2)
......
...@@ -2,6 +2,7 @@ from django.core.management.base import BaseCommand, CommandError ...@@ -2,6 +2,7 @@ from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.xml_importer import check_module_metadata_editability from xmodule.modulestore.xml_importer import check_module_metadata_editability
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from xmodule.modulestore import Location
class Command(BaseCommand): class Command(BaseCommand):
...@@ -54,8 +55,16 @@ class Command(BaseCommand): ...@@ -54,8 +55,16 @@ class Command(BaseCommand):
discussion_items = _get_discussion_items(course) discussion_items = _get_discussion_items(course)
# now query all discussion items via get_items() and compare with the tree-traversal # now query all discussion items via get_items() and compare with the tree-traversal
queried_discussion_items = store.get_items(['i4x', course.location.org, course.location.course, queried_discussion_items = store.get_items(
'discussion', None, None]) Location(
'i4x',
course.location.org,
course.location.course,
'discussion',
None,
None
)
)
for item in queried_discussion_items: for item in queried_discussion_items:
if item.location.url() not in discussion_items: if item.location.url() not in discussion_items:
......
""" Tests for utils. """ """ Tests for utils. """
from contentstore import utils from contentstore import utils
import mock import mock
import unittest
import collections import collections
import copy import copy
import json
from uuid import uuid4
from django.test import TestCase from django.test import TestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from django.test.utils import override_settings from django.test.utils import override_settings
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.contentstore.content import StaticContent from xmodule.modulestore import Location
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.exceptions import NotFoundError
class LMSLinksTestCase(TestCase): class LMSLinksTestCase(TestCase):
...@@ -64,12 +57,12 @@ class LMSLinksTestCase(TestCase): ...@@ -64,12 +57,12 @@ class LMSLinksTestCase(TestCase):
def get_about_page_link(self): def get_about_page_link(self):
""" create mock course and return the about page link """ """ create mock course and return the about page link """
location = 'i4x', 'mitX', '101', 'course', 'test' location = Location('i4x', 'mitX', '101', 'course', 'test')
return utils.get_lms_link_for_about_page(location) return utils.get_lms_link_for_about_page(location)
def lms_link_test(self): def lms_link_test(self):
""" Tests get_lms_link_for_item. """ """ Tests get_lms_link_for_item. """
location = 'i4x', 'mitX', '101', 'vertical', 'contacting_us' location = Location('i4x', 'mitX', '101', 'vertical', 'contacting_us')
link = utils.get_lms_link_for_item(location, False, "mitX/101/test") link = utils.get_lms_link_for_item(location, False, "mitX/101/test")
self.assertEquals(link, "//localhost:8000/courses/mitX/101/test/jump_to/i4x://mitX/101/vertical/contacting_us") self.assertEquals(link, "//localhost:8000/courses/mitX/101/test/jump_to/i4x://mitX/101/vertical/contacting_us")
link = utils.get_lms_link_for_item(location, True, "mitX/101/test") link = utils.get_lms_link_for_item(location, True, "mitX/101/test")
...@@ -80,7 +73,7 @@ class LMSLinksTestCase(TestCase): ...@@ -80,7 +73,7 @@ class LMSLinksTestCase(TestCase):
# If no course_id is passed in, it is obtained from the location. This is the case for # If no course_id is passed in, it is obtained from the location. This is the case for
# Studio dashboard. # Studio dashboard.
location = 'i4x', 'mitX', '101', 'course', 'test' location = Location('i4x', 'mitX', '101', 'course', 'test')
link = utils.get_lms_link_for_item(location) link = utils.get_lms_link_for_item(location)
self.assertEquals( self.assertEquals(
link, link,
......
...@@ -79,7 +79,7 @@ def get_course_location_for_item(location): ...@@ -79,7 +79,7 @@ def get_course_location_for_item(location):
# @hack! We need to find the course location however, we don't # @hack! We need to find the course location however, we don't
# know the 'name' parameter in this context, so we have # know the 'name' parameter in this context, so we have
# to assume there's only one item in this query even though we are not specifying a name # to assume there's only one item in this query even though we are not specifying a name
course_search_location = ['i4x', item_loc.org, item_loc.course, 'course', None] course_search_location = Location('i4x', item_loc.org, item_loc.course, 'course', None)
courses = modulestore().get_items(course_search_location) courses = modulestore().get_items(course_search_location)
# make sure we found exactly one match on this above course search # make sure we found exactly one match on this above course search
...@@ -107,7 +107,7 @@ def get_course_for_item(location): ...@@ -107,7 +107,7 @@ def get_course_for_item(location):
# @hack! We need to find the course location however, we don't # @hack! We need to find the course location however, we don't
# know the 'name' parameter in this context, so we have # know the 'name' parameter in this context, so we have
# to assume there's only one item in this query even though we are not specifying a name # to assume there's only one item in this query even though we are not specifying a name
course_search_location = ['i4x', item_loc.org, item_loc.course, 'course', None] course_search_location = Location('i4x', item_loc.org, item_loc.course, 'course', None)
courses = modulestore().get_items(course_search_location) courses = modulestore().get_items(course_search_location)
# make sure we found exactly one match on this above course search # make sure we found exactly one match on this above course search
......
from auth.authz import STAFF_ROLE_NAME, INSTRUCTOR_ROLE_NAME from auth.authz import STAFF_ROLE_NAME, INSTRUCTOR_ROLE_NAME
from auth.authz import is_user_in_course_group_role from auth.authz import is_user_in_course_group_role
from django.core.exceptions import PermissionDenied
from ..utils import get_course_location_for_item from ..utils import get_course_location_for_item
from xmodule.modulestore import Location
from xmodule.modulestore.locator import CourseLocator from xmodule.modulestore.locator import CourseLocator
def get_location_and_verify_access(request, org, course, name):
"""
Create the location, verify that the user has permissions
to view the location. Returns the location as a Location
"""
location = ['i4x', org, course, 'course', name]
# check that logged in user has permissions to this item
if not has_access(request.user, location):
raise PermissionDenied()
return Location(location)
def has_access(user, location, role=STAFF_ROLE_NAME): def has_access(user, location, role=STAFF_ROLE_NAME):
''' """
Return True if user allowed to access this piece of data Return True if user allowed to access this piece of data
Note that the CMS permissions model is with respect to courses Note that the CMS permissions model is with respect to courses
There is a super-admin permissions if user.is_staff is set There is a super-admin permissions if user.is_staff is set
...@@ -29,7 +13,7 @@ def has_access(user, location, role=STAFF_ROLE_NAME): ...@@ -29,7 +13,7 @@ def has_access(user, location, role=STAFF_ROLE_NAME):
I'm presuming that the course instructor (formally known as admin) I'm presuming that the course instructor (formally known as admin)
will not be in both INSTRUCTOR and STAFF groups, so we have to cascade our will not be in both INSTRUCTOR and STAFF groups, so we have to cascade our
queries here as INSTRUCTOR has all the rights that STAFF do queries here as INSTRUCTOR has all the rights that STAFF do
''' """
if not isinstance(location, CourseLocator): if not isinstance(location, CourseLocator):
location = get_course_location_for_item(location) location = get_course_location_for_item(location)
_has_access = is_user_in_course_group_role(user, location, role) _has_access = is_user_in_course_group_role(user, location, role)
......
...@@ -128,7 +128,7 @@ def course_listing(request): ...@@ -128,7 +128,7 @@ def course_listing(request):
""" """
List all courses available to the logged in user List all courses available to the logged in user
""" """
courses = modulestore('direct').get_items(['i4x', None, None, 'course', None]) courses = modulestore('direct').get_items(Location('i4x', None, None, 'course', None))
# filter out courses that we don't have access too # filter out courses that we don't have access too
def course_filter(course): def course_filter(course):
......
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