Add new course_module field which describes what the catalog visibility should be (both, about, none)
This commit is contained in:
@@ -8,7 +8,9 @@ import pytz
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
from xmodule.course_module import CourseDescriptor
|
||||
from xmodule.course_module import (
|
||||
CourseDescriptor, CATALOG_VISIBILITY_CATALOG_AND_ABOUT,
|
||||
CATALOG_VISIBILITY_ABOUT)
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.x_module import XModule
|
||||
|
||||
@@ -110,6 +112,8 @@ def _has_access_course_desc(user, action, course):
|
||||
ACCESS_REQUIRE_STAFF_FOR_COURSE,
|
||||
'see_exists' -- can see that the course exists.
|
||||
'staff' -- staff access to course.
|
||||
'see_in_catalog' -- user is able to see the course listed in the course catalog.
|
||||
'see_about_page' -- user is able to see the course about page.
|
||||
"""
|
||||
def can_load():
|
||||
"""
|
||||
@@ -204,6 +208,29 @@ def _has_access_course_desc(user, action, course):
|
||||
|
||||
return can_enroll() or can_load()
|
||||
|
||||
def can_see_in_catalog():
|
||||
"""
|
||||
Implements the "can see course in catalog" logic if a course should be visible in the main course catalog
|
||||
In this case we use the catalog_visibility property on the course descriptor
|
||||
but also allow course staff to see this.
|
||||
"""
|
||||
return (
|
||||
course.catalog_visibility == CATALOG_VISIBILITY_CATALOG_AND_ABOUT or
|
||||
_has_staff_access_to_descriptor(user, course, course.id)
|
||||
)
|
||||
|
||||
def can_see_about_page():
|
||||
"""
|
||||
Implements the "can see course about page" logic if a course about page should be visible
|
||||
In this case we use the catalog_visibility property on the course descriptor
|
||||
but also allow course staff to see this.
|
||||
"""
|
||||
return (
|
||||
course.catalog_visibility == CATALOG_VISIBILITY_CATALOG_AND_ABOUT or
|
||||
course.catalog_visibility == CATALOG_VISIBILITY_ABOUT or
|
||||
_has_staff_access_to_descriptor(user, course, course.id)
|
||||
)
|
||||
|
||||
checkers = {
|
||||
'load': can_load,
|
||||
'load_forum': can_load_forum,
|
||||
@@ -211,6 +238,8 @@ def _has_access_course_desc(user, action, course):
|
||||
'see_exists': see_exists,
|
||||
'staff': lambda: _has_staff_access_to_descriptor(user, course, course.id),
|
||||
'instructor': lambda: _has_instructor_access_to_descriptor(user, course, course.id),
|
||||
'see_in_catalog': can_see_in_catalog,
|
||||
'see_about_page': can_see_about_page,
|
||||
}
|
||||
|
||||
return _dispatch(checkers, action, user, course)
|
||||
|
||||
@@ -16,6 +16,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from static_replace import replace_static_urls
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
from microsite_configuration import microsite
|
||||
|
||||
from courseware.access import has_access
|
||||
from courseware.model_data import FieldDataCache
|
||||
@@ -256,7 +257,7 @@ def get_course_info_section_module(request, course, section_key):
|
||||
log_if_not_found=False,
|
||||
wrap_xmodule_display=False,
|
||||
static_asset_path=course.static_asset_path
|
||||
)
|
||||
)
|
||||
|
||||
def get_course_info_section(request, course, section_key):
|
||||
"""
|
||||
@@ -345,7 +346,13 @@ def get_courses(user, domain=None):
|
||||
Returns a list of courses available, sorted by course.number
|
||||
'''
|
||||
courses = branding.get_visible_courses()
|
||||
courses = [c for c in courses if has_access(user, 'see_exists', c)]
|
||||
|
||||
permission_name = microsite.get_value(
|
||||
'COURSE_CATALOG_VISIBILITY_PERMISSION',
|
||||
settings.COURSE_CATALOG_VISIBILITY_PERMISSION
|
||||
)
|
||||
|
||||
courses = [c for c in courses if has_access(user, permission_name, c)]
|
||||
|
||||
courses = sorted(courses, key=lambda course: course.number)
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@ from courseware.tests.modulestore_config import TEST_DATA_MONGO_MODULESTORE, TES
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from student.tests.factories import UserFactory, CourseEnrollmentAllowedFactory
|
||||
from course_modes.models import CourseMode
|
||||
from student.models import CourseEnrollment
|
||||
|
||||
from shoppingcart.models import Order, PaidCourseRegistration
|
||||
|
||||
from xmodule.course_module import CATALOG_VISIBILITY_ABOUT, CATALOG_VISIBILITY_NONE
|
||||
|
||||
# HTML for registration button
|
||||
REG_STR = "<form id=\"class_enroll_form\" method=\"post\" data-remote=\"true\" action=\"/change_enrollment\">"
|
||||
@@ -33,15 +39,28 @@ class AboutTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
category="about", parent_location=self.course.location,
|
||||
data="OOGIE BLOOGIE", display_name="overview"
|
||||
)
|
||||
self.course_without_about = CourseFactory.create(catalog_visibility=CATALOG_VISIBILITY_NONE)
|
||||
self.about = ItemFactory.create(
|
||||
category="about", parent_location=self.course_without_about.location,
|
||||
data="WITHOUT ABOUT", display_name="overview"
|
||||
)
|
||||
self.course_with_about = CourseFactory.create(catalog_visibility=CATALOG_VISIBILITY_ABOUT)
|
||||
self.about = ItemFactory.create(
|
||||
category="about", parent_location=self.course_with_about.location,
|
||||
data="WITH ABOUT", display_name="overview"
|
||||
)
|
||||
|
||||
def test_logged_in(self):
|
||||
self.setup_user()
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("OOGIE BLOOGIE", resp.content)
|
||||
self.purchase_course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy')
|
||||
self.course_mode = CourseMode(course_id=self.purchase_course.id,
|
||||
mode_slug="honor",
|
||||
mode_display_name="honor cert",
|
||||
min_price=10)
|
||||
self.course_mode.save()
|
||||
|
||||
def test_anonymous_user(self):
|
||||
"""
|
||||
This test asserts that a non-logged in user can visit the course about page
|
||||
"""
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
@@ -50,6 +69,43 @@ class AboutTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
# Check that registration button is present
|
||||
self.assertIn(REG_STR, resp.content)
|
||||
|
||||
def test_logged_in(self):
|
||||
"""
|
||||
This test asserts that a logged-in user can visit the course about page
|
||||
"""
|
||||
self.setup_user()
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("OOGIE BLOOGIE", resp.content)
|
||||
|
||||
def test_already_enrolled(self):
|
||||
"""
|
||||
Asserts that the end user sees the appropriate messaging
|
||||
when he/she visits the course about page, but is already enrolled
|
||||
"""
|
||||
self.setup_user()
|
||||
self.enroll(self.course, True)
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("You are registered for this course", resp.content)
|
||||
self.assertIn("View Courseware", resp.content)
|
||||
|
||||
@override_settings(COURSE_ABOUT_VISIBILITY_PERMISSION="see_about_page")
|
||||
def test_visible_about_page_settings(self):
|
||||
"""
|
||||
Verify that the About Page honors the permission settings in the course module
|
||||
"""
|
||||
url = reverse('about_course', args=[self.course_with_about.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("WITH ABOUT", resp.content)
|
||||
|
||||
url = reverse('about_course', args=[self.course_without_about.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 404)
|
||||
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
|
||||
def test_logged_in_marketing(self):
|
||||
self.setup_user()
|
||||
@@ -261,3 +317,155 @@ class AboutWithClosedEnrollment(ModuleStoreTestCase):
|
||||
|
||||
# Check that registration button is not present
|
||||
self.assertNotIn(REG_STR, resp.content)
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_SHOPPING_CART': True})
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True})
|
||||
class AboutPurchaseCourseTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
"""
|
||||
This test class runs through a suite of verifications regarding
|
||||
purchaseable courses
|
||||
"""
|
||||
def setUp(self):
|
||||
super(AboutPurchaseCourseTestCase, self).setUp()
|
||||
self.course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy')
|
||||
self._set_ecomm(self.course)
|
||||
|
||||
def _set_ecomm(self, course):
|
||||
"""
|
||||
Helper method to turn on ecommerce on the course
|
||||
"""
|
||||
course_mode = CourseMode(
|
||||
course_id=course.id,
|
||||
mode_slug="honor",
|
||||
mode_display_name="honor cert",
|
||||
min_price=10,
|
||||
)
|
||||
course_mode.save()
|
||||
|
||||
def test_anonymous_user(self):
|
||||
"""
|
||||
Make sure an anonymous user sees the purchase button
|
||||
"""
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
def test_logged_in(self):
|
||||
"""
|
||||
Make sure a logged in user sees the purchase button
|
||||
"""
|
||||
self.setup_user()
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
def test_already_in_cart(self):
|
||||
"""
|
||||
This makes sure if a user has this course in the cart, that the expected message
|
||||
appears
|
||||
"""
|
||||
self.setup_user()
|
||||
cart = Order.get_cart_for_user(self.user)
|
||||
PaidCourseRegistration.add_to_order(cart, self.course.id)
|
||||
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("This course is in your", resp.content)
|
||||
self.assertNotIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
def test_already_enrolled(self):
|
||||
"""
|
||||
This makes sure that the already enrolled message appears for paywalled courses
|
||||
"""
|
||||
self.setup_user()
|
||||
|
||||
# note that we can't call self.enroll here since that goes through
|
||||
# the Django student views, which doesn't allow for enrollments
|
||||
# for paywalled courses
|
||||
CourseEnrollment.enroll(self.user, self.course.id)
|
||||
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("You are registered for this course", resp.content)
|
||||
self.assertIn("View Courseware", resp.content)
|
||||
self.assertNotIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
def test_closed_enrollment(self):
|
||||
"""
|
||||
This makes sure that paywalled courses also honor the registration
|
||||
window
|
||||
"""
|
||||
self.setup_user()
|
||||
now = datetime.datetime.now(pytz.UTC)
|
||||
tomorrow = now + datetime.timedelta(days=1)
|
||||
nextday = tomorrow + datetime.timedelta(days=1)
|
||||
|
||||
self.course.enrollment_start = tomorrow
|
||||
self.course.enrollment_end = nextday
|
||||
self.course = self.update_course(self.course, self.user.id)
|
||||
|
||||
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("Enrollment is Closed", resp.content)
|
||||
self.assertNotIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
def test_invitation_only(self):
|
||||
"""
|
||||
This makes sure that the invitation only restirction takes prescendence over
|
||||
any purchase enablements
|
||||
"""
|
||||
course = CourseFactory.create(metadata={"invitation_only": True})
|
||||
self._set_ecomm(course)
|
||||
self.setup_user()
|
||||
|
||||
url = reverse('about_course', args=[course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("Enrollment in this course is by invitation only", resp.content)
|
||||
|
||||
def test_enrollment_cap(self):
|
||||
"""
|
||||
Make sure that capped enrollments work even with
|
||||
paywalled courses
|
||||
"""
|
||||
course = CourseFactory.create(
|
||||
metadata={
|
||||
"max_student_enrollments_allowed": 1,
|
||||
"display_coursenumber": "buyme",
|
||||
}
|
||||
)
|
||||
self._set_ecomm(course)
|
||||
|
||||
self.setup_user()
|
||||
url = reverse('about_course', args=[course.id.to_deprecated_string()])
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
# note that we can't call self.enroll here since that goes through
|
||||
# the Django student views, which doesn't allow for enrollments
|
||||
# for paywalled courses
|
||||
CourseEnrollment.enroll(self.user, course.id)
|
||||
|
||||
# create a new account since the first account is already registered for the course
|
||||
email = 'foo_second@test.com'
|
||||
password = 'bar'
|
||||
username = 'test_second'
|
||||
self.create_account(username,
|
||||
email, password)
|
||||
self.activate_user(email)
|
||||
self.login(email, password)
|
||||
|
||||
# Get the about page again and make sure that the page says that the course is full
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertIn("Course is full", resp.content)
|
||||
self.assertNotIn("Add buyme to Cart ($10)", resp.content)
|
||||
|
||||
@@ -11,8 +11,12 @@ from student.tests.factories import AnonymousUserFactory, CourseEnrollmentAllowe
|
||||
import pytz
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
# pylint: disable=C0111
|
||||
from xmodule.course_module import (
|
||||
CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CATALOG_VISIBILITY_ABOUT,
|
||||
CATALOG_VISIBILITY_NONE)
|
||||
|
||||
# pylint: disable=C0111
|
||||
# pylint: disable=W0212
|
||||
|
||||
class AccessTestCase(TestCase):
|
||||
"""
|
||||
@@ -202,6 +206,43 @@ class AccessTestCase(TestCase):
|
||||
"""Ensure has_access handles a user being passed as null"""
|
||||
access.has_access(None, 'staff', 'global', None)
|
||||
|
||||
def test__catalog_visibility(self):
|
||||
"""
|
||||
Tests the catalog visibility tri-states
|
||||
"""
|
||||
user = UserFactory.create()
|
||||
course_id = SlashSeparatedCourseKey('edX', 'test', '2012_Fall')
|
||||
staff = StaffFactory.create(course_key=course_id)
|
||||
|
||||
course = Mock(
|
||||
id=course_id,
|
||||
catalog_visibility=CATALOG_VISIBILITY_CATALOG_AND_ABOUT
|
||||
)
|
||||
self.assertTrue(access._has_access_course_desc(user, 'see_in_catalog', course))
|
||||
self.assertTrue(access._has_access_course_desc(user, 'see_about_page', course))
|
||||
self.assertTrue(access._has_access_course_desc(staff, 'see_in_catalog', course))
|
||||
self.assertTrue(access._has_access_course_desc(staff, 'see_about_page', course))
|
||||
|
||||
# Now set visibility to just about page
|
||||
course = Mock(
|
||||
id=SlashSeparatedCourseKey('edX', 'test', '2012_Fall'),
|
||||
catalog_visibility=CATALOG_VISIBILITY_ABOUT
|
||||
)
|
||||
self.assertFalse(access._has_access_course_desc(user, 'see_in_catalog', course))
|
||||
self.assertTrue(access._has_access_course_desc(user, 'see_about_page', course))
|
||||
self.assertTrue(access._has_access_course_desc(staff, 'see_in_catalog', course))
|
||||
self.assertTrue(access._has_access_course_desc(staff, 'see_about_page', course))
|
||||
|
||||
# Now set visibility to none, which means neither in catalog nor about pages
|
||||
course = Mock(
|
||||
id=SlashSeparatedCourseKey('edX', 'test', '2012_Fall'),
|
||||
catalog_visibility=CATALOG_VISIBILITY_NONE
|
||||
)
|
||||
self.assertFalse(access._has_access_course_desc(user, 'see_in_catalog', course))
|
||||
self.assertFalse(access._has_access_course_desc(user, 'see_about_page', course))
|
||||
self.assertTrue(access._has_access_course_desc(staff, 'see_in_catalog', course))
|
||||
self.assertTrue(access._has_access_course_desc(staff, 'see_about_page', course))
|
||||
|
||||
|
||||
class UserRoleTestCase(TestCase):
|
||||
"""
|
||||
|
||||
@@ -11,6 +11,8 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from helpers import LoginEnrollmentTestCase
|
||||
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
from xmodule.course_module import (
|
||||
CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CATALOG_VISIBILITY_NONE)
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
|
||||
class TestMicrosites(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
@@ -42,6 +44,20 @@ class TestMicrosites(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
|
||||
self.course_outside_microsite = CourseFactory.create(display_name='Robot_Course_Outside_Microsite', org='FooX')
|
||||
|
||||
# have a course which explicitly sets visibility in catalog to False
|
||||
self.course_hidden_visibility = CourseFactory.create(
|
||||
display_name='Hidden_course',
|
||||
org='TestMicrositeX',
|
||||
catalog_visibility=CATALOG_VISIBILITY_NONE,
|
||||
)
|
||||
|
||||
# have a course which explicitly sets visibility in catalog and about to true
|
||||
self.course_with_visibility = CourseFactory.create(
|
||||
display_name='visible_course',
|
||||
org='TestMicrositeX',
|
||||
catalog_visibility=CATALOG_VISIBILITY_CATALOG_AND_ABOUT,
|
||||
)
|
||||
|
||||
def setup_users(self):
|
||||
# Create student accounts and activate them.
|
||||
for i in range(len(self.STUDENT_INFO)):
|
||||
@@ -71,9 +87,15 @@ class TestMicrosites(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
# assert that test course display name is visible
|
||||
self.assertContains(resp, 'Robot_Super_Course')
|
||||
|
||||
# assert that test course with 'visible_in_catalog' to True is showing up
|
||||
self.assertContains(resp, 'visible_course')
|
||||
|
||||
# assert that test course that is outside microsite is not visible
|
||||
self.assertNotContains(resp, 'Robot_Course_Outside_Microsite')
|
||||
|
||||
# assert that a course that has visible_in_catalog=False is not visible
|
||||
self.assertNotContains(resp, 'Hidden_course')
|
||||
|
||||
# assert that footer template has been properly overriden on homepage
|
||||
self.assertContains(resp, 'This is a Test Microsite footer')
|
||||
|
||||
@@ -153,3 +175,17 @@ class TestMicrosites(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
resp = self.client.get(reverse('dashboard'))
|
||||
self.assertNotContains(resp, 'Robot_Super_Course')
|
||||
self.assertContains(resp, 'Robot_Course_Outside_Microsite')
|
||||
|
||||
@override_settings(SITE_NAME=settings.MICROSITE_TEST_HOSTNAME)
|
||||
def test_visible_about_page_settings(self):
|
||||
"""
|
||||
Make sure the Microsite is honoring the visible_about_page permissions that is
|
||||
set in configuration
|
||||
"""
|
||||
url = reverse('about_course', args=[self.course_with_visibility.id.to_deprecated_string()])
|
||||
resp = self.client.get(url, HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
url = reverse('about_course', args=[self.course_hidden_visibility.id.to_deprecated_string()])
|
||||
resp = self.client.get(url, HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME)
|
||||
self.assertEqual(resp.status_code, 404)
|
||||
|
||||
@@ -701,7 +701,12 @@ def course_about(request, course_id):
|
||||
"""
|
||||
|
||||
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
course = get_course_with_access(request.user, 'see_exists', course_key)
|
||||
|
||||
permission_name = microsite.get_value(
|
||||
'COURSE_ABOUT_VISIBILITY_PERMISSION',
|
||||
settings.COURSE_ABOUT_VISIBILITY_PERMISSION
|
||||
)
|
||||
course = get_course_with_access(request.user, permission_name, course_key)
|
||||
|
||||
if microsite.get_value(
|
||||
'ENABLE_MKTG_SITE',
|
||||
@@ -710,6 +715,7 @@ def course_about(request, course_id):
|
||||
return redirect(reverse('info', args=[course.id.to_deprecated_string()]))
|
||||
|
||||
registered = registered_for_course(course, request.user)
|
||||
|
||||
staff_access = has_access(request.user, 'staff', course)
|
||||
studio_url = get_studio_url(course, 'settings/details')
|
||||
|
||||
@@ -782,8 +788,12 @@ def mktg_course_about(request, course_id):
|
||||
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
|
||||
try:
|
||||
course = get_course_with_access(request.user, 'see_exists', course_key)
|
||||
except (ValueError, Http404) as e:
|
||||
permission_name = microsite.get_value(
|
||||
'COURSE_ABOUT_VISIBILITY_PERMISSION',
|
||||
settings.COURSE_ABOUT_VISIBILITY_PERMISSION
|
||||
)
|
||||
course = get_course_with_access(request.user, permission_name, course_key)
|
||||
except (ValueError, Http404):
|
||||
# if a course does not exist yet, display a coming
|
||||
# soon button
|
||||
return render_to_response(
|
||||
|
||||
Reference in New Issue
Block a user