REVMI-354 Add enroll_in_course permission (#21243)
* REVMI-354 Add enroll_in_course permission * Fix test
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
10
openedx/core/djangoapps/enrollments/permissions.py
Normal file
10
openedx/core/djangoapps/enrollments/permissions.py
Normal 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')
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user