Adds a waffle switch which gates access to the CourseEnrollmentAdmin views
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
""" Django admin pages for student app """
|
||||
from config_models.admin import ConfigurationModelAdmin
|
||||
import waffle
|
||||
from django import forms
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin.sites import NotRegistered
|
||||
@@ -165,13 +166,7 @@ class CourseEnrollmentForm(forms.ModelForm):
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
# Page disabled because it makes DB quries that impact performance enough to
|
||||
# cause a site outage. It may be re-enabled when it is updated to make more
|
||||
# efficent DB queries
|
||||
# https://openedx.atlassian.net/browse/OPS-2943
|
||||
# Learner ticket to add functionality to /support
|
||||
# https://openedx.atlassian.net/browse/LEARNER-4744
|
||||
#@admin.register(CourseEnrollment)
|
||||
@admin.register(CourseEnrollment)
|
||||
class CourseEnrollmentAdmin(admin.ModelAdmin):
|
||||
""" Admin interface for the CourseEnrollment model. """
|
||||
list_display = ('id', 'course_id', 'mode', 'user', 'is_active',)
|
||||
@@ -183,6 +178,43 @@ class CourseEnrollmentAdmin(admin.ModelAdmin):
|
||||
def queryset(self, request):
|
||||
return super(CourseEnrollmentAdmin, self).queryset(request).select_related('user')
|
||||
|
||||
def has_permission(self, request, method):
|
||||
"""
|
||||
Returns True if the given method is allowed.
|
||||
|
||||
Access to these admin views is restricted because it makes DB quries that impact performance enough to cause a
|
||||
site outage, cf https://openedx.atlassian.net/browse/OPS-2943
|
||||
|
||||
Enable these views using the waffle switch: `student.coursenrollment.admin`
|
||||
"""
|
||||
if waffle.switch_is_active('student.coursenrollment.admin'):
|
||||
return getattr(super(CourseEnrollmentAdmin, self), method)(request)
|
||||
return False
|
||||
|
||||
def has_add_permission(self, request):
|
||||
"""
|
||||
Returns True if CourseEnrollment objects can be added via the admin view.
|
||||
"""
|
||||
return self.has_permission(request, 'has_add_permission')
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
"""
|
||||
Returns True if CourseEnrollment objects can be modified via the admin view.
|
||||
"""
|
||||
return self.has_permission(request, 'has_change_permission')
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
"""
|
||||
Returns True if CourseEnrollment objects can be deleted via the admin view.
|
||||
"""
|
||||
return self.has_permission(request, 'has_delete_permission')
|
||||
|
||||
def has_module_permission(self, request):
|
||||
"""
|
||||
Returns True if links to the CourseEnrollment admin view can be displayed.
|
||||
"""
|
||||
return self.has_permission(request, 'has_module_permission')
|
||||
|
||||
|
||||
class UserProfileInline(admin.StackedInline):
|
||||
""" Inline admin interface for UserProfile model. """
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
Tests student admin.py
|
||||
"""
|
||||
import ddt
|
||||
from waffle.testutils import override_switch
|
||||
from django.contrib.admin.sites import AdminSite
|
||||
from django.contrib.auth.models import User
|
||||
from django.urls import reverse
|
||||
@@ -8,7 +10,7 @@ from django.test import TestCase
|
||||
from mock import Mock
|
||||
|
||||
from student.admin import UserAdmin
|
||||
from student.tests.factories import UserFactory
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
@@ -186,3 +188,49 @@ class AdminUserPageTest(TestCase):
|
||||
request = Mock()
|
||||
user = Mock()
|
||||
self.assertIn('username', self.admin.get_readonly_fields(request, user))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Unit tests for the CourseEnrollmentAdmin view.
|
||||
"""
|
||||
ADMIN_URLS = (
|
||||
('get', reverse('admin:student_courseenrollment_add')),
|
||||
('get', reverse('admin:student_courseenrollment_changelist')),
|
||||
('get', reverse('admin:student_courseenrollment_change', args=(1,))),
|
||||
('get', reverse('admin:student_courseenrollment_delete', args=(1,))),
|
||||
('post', reverse('admin:student_courseenrollment_add')),
|
||||
('post', reverse('admin:student_courseenrollment_changelist')),
|
||||
('post', reverse('admin:student_courseenrollment_change', args=(1,))),
|
||||
('post', reverse('admin:student_courseenrollment_delete', args=(1,))),
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(CourseEnrollmentAdminTest, self).setUp()
|
||||
self.user = UserFactory.create(is_staff=True, is_superuser=True)
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
CourseEnrollmentFactory(
|
||||
user=self.user,
|
||||
course_id=CourseFactory().id, # pylint: disable=no-member
|
||||
)
|
||||
|
||||
@ddt.data(*ADMIN_URLS)
|
||||
@ddt.unpack
|
||||
def test_view_disabled(self, method, url):
|
||||
"""
|
||||
All CourseEnrollmentAdmin views are disabled by default.
|
||||
"""
|
||||
response = getattr(self.client, method)(url)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@override_switch('student.coursenrollment.admin', active=True)
|
||||
@ddt.data(*ADMIN_URLS)
|
||||
@ddt.unpack
|
||||
def test_view_enabled(self, method, url):
|
||||
"""
|
||||
Ensure CourseEnrollmentAdmin views can be enabled with the waffle flag.
|
||||
"""
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
response = getattr(self.client, method)(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
Reference in New Issue
Block a user