REVMI-354 Add enroll_in_course permission (#21243)

* REVMI-354 Add enroll_in_course permission

* Fix test
This commit is contained in:
Christie Rice
2019-08-01 08:37:41 -04:00
committed by GitHub
parent c78db13de1
commit 3d062aab62
6 changed files with 27 additions and 17 deletions

View File

@@ -28,12 +28,12 @@ from opaque_keys.edx.keys import CourseKey
from six import text_type
from course_modes.models import CourseMode
from courseware.access import has_access
from edxmako.shortcuts import render_to_response
from lms.djangoapps.commerce.utils import EcommerceService
from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context
from openedx.core.djangoapps.catalog.utils import get_currency_data
from openedx.core.djangoapps.embargo import api as embargo_api
from openedx.core.djangoapps.enrollments.permissions import ENROLL_IN_COURSE
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
from openedx.features.course_experience.utils import get_first_purchase_offer_banner_fragment
@@ -150,7 +150,7 @@ class ChooseModeView(View):
# When a credit mode is available, students will be given the option
# to upgrade from a verified mode to a credit mode at the end of the course.
# This allows students who have completed photo verification to be eligible
# for univerity credit.
# for university credit.
# Since credit isn't one of the selectable options on the track selection page,
# we need to check *all* available course modes in order to determine whether
# a credit mode is available. If so, then we show slightly different messaging
@@ -259,7 +259,7 @@ class ChooseModeView(View):
# This is a bit redundant with logic in student.views.change_enrollment,
# but I don't really have the time to refactor it more nicely and test.
course = modulestore().get_course(course_key)
if not has_access(user, 'enroll', course):
if not user.has_perm(ENROLL_IN_COURSE, course):
error_msg = _("Enrollment is closed")
return self.get(request, course_id, error=error_msg)

View File

@@ -1255,7 +1255,7 @@ class CourseEnrollment(models.Model):
Arguments:
user (User): the user for whom we want the program enrollment
coure_id (CourseKey): the id of the course the user has a course enrollment in
course_id (CourseKey): the id of the course the user has a course enrollment in
Returns:
ProgramEnrollment object or None
@@ -1272,10 +1272,9 @@ class CourseEnrollment(models.Model):
Returns a boolean value regarding whether the user has access to enroll in the course. Returns False if the
enrollment has been closed.
"""
# Disable the pylint error here, as per ormsbee. This local import was previously
# in CourseEnrollment.enroll
from courseware.access import has_access # pylint: disable=import-error
return not has_access(user, 'enroll', course)
# pylint: disable=import-error
from openedx.core.djangoapps.enrollments.permissions import ENROLL_IN_COURSE
return not user.has_perm(ENROLL_IN_COURSE, course)
def update_enrollment(self, mode=None, is_active=None, skip_refund=False):
"""

View File

@@ -87,6 +87,7 @@ from openedx.core.djangoapps.credit.api import (
is_user_eligible_for_credit
)
from openedx.core.djangoapps.enrollments.api import add_enrollment
from openedx.core.djangoapps.enrollments.permissions import ENROLL_IN_COURSE
from openedx.core.djangoapps.models.course_details import CourseDetails
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from openedx.core.djangoapps.programs.utils import ProgramMarketingDataExtender
@@ -869,7 +870,7 @@ def course_about(request, course_id):
can_add_course_to_cart = _is_shopping_cart_enabled and registration_price and not ecommerce_checkout_link
# Used to provide context to message to student if enrollment not allowed
can_enroll = bool(has_access(request.user, 'enroll', course))
can_enroll = bool(request.user.has_perm(ENROLL_IN_COURSE, course))
invitation_only = course.invitation_only
is_course_full = CourseEnrollment.objects.is_course_full(course)

View File

@@ -0,0 +1,10 @@
"""
Permission definitions for the enrollments djangoapp
"""
from bridgekeeper import perms
from courseware.rules import HasAccessRule
ENROLL_IN_COURSE = 'enrollment.enroll_in_course'
perms[ENROLL_IN_COURSE] = HasAccessRule('enroll')

View File

@@ -335,7 +335,7 @@ class TestProgramProgressMeter(TestCase):
self.assertEqual(meter.progress(count_only=True), expected)
def test_mutiple_program_enrollment(self, mock_get_programs):
def test_multiple_program_enrollment(self, mock_get_programs):
"""
Verify that correct programs are returned in the correct order when the
user is enrolled in course runs appearing in programs.
@@ -1162,7 +1162,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
def test_learner_eligibility_for_one_click_purchase_user_entitlements(self):
"""
Learner should be eligibile for one click purchase if they hold an entitlement in one or more courses
Learner should be eligible for one click purchase if they hold an entitlement in one or more courses
in the program and there are remaining unpurchased courses in the program with entitlement products.
"""
course1 = _create_course(self, self.course_price, course_run_count=2, make_entitlement=True)
@@ -1236,7 +1236,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
"""
course1 = _create_course(self, self.course_price)
course2 = _create_course(self, self.course_price, course_run_count=2, make_entitlement=True)
# The above statement makes a verfied entitlement for the course, which is an applicable seat type
# The above statement makes a verified entitlement for the course, which is an applicable seat type
# and the statement below makes a professional entitlement for the same course, which is not applicable
course2['entitlements'].append(EntitlementFactory(mode=CourseMode.PROFESSIONAL))
expected_skus = set([course1['course_runs'][0]['seats'][0]['sku'], course2['entitlements'][0]['sku']])
@@ -1488,12 +1488,12 @@ class TestProgramMarketingDataExtender(ModuleStoreTestCase):
self.assertEqual(data['avg_price_per_course'], 0.0)
@ddt.data(True, False)
@mock.patch(UTILS_MODULE + '.has_access')
def test_can_enroll(self, can_enroll, mock_has_access):
@mock.patch('django.contrib.auth.models.PermissionsMixin.has_perm')
def test_can_enroll(self, can_enroll, mock_has_perm):
"""
Verify that the student's can_enroll status is included.
"""
mock_has_access.return_value = can_enroll
mock_has_perm.return_value = can_enroll
data = ProgramMarketingDataExtender(self.program, self.user).extend()

View File

@@ -26,13 +26,13 @@ from entitlements.models import CourseEntitlement
from lms.djangoapps.certificates import api as certificate_api
from lms.djangoapps.certificates.models import GeneratedCertificate
from lms.djangoapps.commerce.utils import EcommerceService
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.grades.api import CourseGradeFactory
from openedx.core.djangoapps.catalog.utils import get_fulfillable_course_runs_for_entitlement, get_programs
from openedx.core.djangoapps.certificates.api import available_date_for_certificate
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.credentials.utils import get_credentials
from openedx.core.djangoapps.enrollments.permissions import ENROLL_IN_COURSE
from openedx.core.djangoapps.programs import ALWAYS_CALCULATE_PROGRAM_PRICE_AS_ANONYMOUS_USER
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from student.models import CourseEnrollment
@@ -841,7 +841,7 @@ class ProgramMarketingDataExtender(ProgramDataExtender):
return {name for name in chain(cls.__dict__, ProgramDataExtender.__dict__) if name.startswith(prefix)}
def _attach_course_run_can_enroll(self, run_mode):
run_mode['can_enroll'] = bool(has_access(self.user, 'enroll', self.course_overview))
run_mode['can_enroll'] = bool(self.user.has_perm(ENROLL_IN_COURSE, self.course_overview))
def _attach_course_run_certificate_url(self, run_mode):
"""