ECOM-1644 Implementing course-access roles.
This commit is contained in:
@@ -3,6 +3,7 @@ django admin pages for courseware model
|
||||
'''
|
||||
from django import forms
|
||||
from config_models.admin import ConfigurationModelAdmin
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from student.models import UserProfile, UserTestGroup, CourseEnrollmentAllowed, DashboardConfiguration
|
||||
from student.models import (
|
||||
@@ -11,24 +12,113 @@ from student.models import (
|
||||
from ratelimitbackend import admin
|
||||
from student.roles import REGISTERED_ACCESS_ROLES
|
||||
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys import InvalidKeyError
|
||||
|
||||
|
||||
class CourseAccessRoleForm(forms.ModelForm):
|
||||
"""Form for adding new Course Access Roles view the Django Admin Panel."""
|
||||
class Meta:
|
||||
model = CourseAccessRole
|
||||
|
||||
email = forms.EmailField(required=True)
|
||||
COURSE_ACCESS_ROLES = [(role_name, role_name) for role_name in REGISTERED_ACCESS_ROLES.keys()]
|
||||
role = forms.ChoiceField(choices=COURSE_ACCESS_ROLES)
|
||||
|
||||
def clean_course_id(self):
|
||||
"""
|
||||
Checking course-id format and course exists in module store.
|
||||
This field can be null.
|
||||
"""
|
||||
if self.cleaned_data['course_id']:
|
||||
course_id = self.cleaned_data['course_id']
|
||||
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
except InvalidKeyError:
|
||||
raise forms.ValidationError(u"Cannot make a valid CourseKey from id {}!".format(course_id))
|
||||
|
||||
if not modulestore().has_course(course_key):
|
||||
raise forms.ValidationError(u"Cannot find course with id {} in the modulestore".format(course_id))
|
||||
|
||||
return course_key
|
||||
|
||||
return None
|
||||
|
||||
def clean_org(self):
|
||||
"""If org and course-id exists then Check organization name
|
||||
against the given course.
|
||||
"""
|
||||
if self.cleaned_data.get('course_id') and self.cleaned_data['org']:
|
||||
org = self.cleaned_data['org']
|
||||
org_name = self.cleaned_data.get('course_id').org
|
||||
if org.lower() != org_name.lower():
|
||||
raise forms.ValidationError(
|
||||
u"Org name {} is not valid. Valid name is {}.".format(
|
||||
org, org_name
|
||||
)
|
||||
)
|
||||
|
||||
return self.cleaned_data['org']
|
||||
|
||||
def clean_email(self):
|
||||
"""
|
||||
Checking user object against given email id.
|
||||
"""
|
||||
email = self.cleaned_data['email']
|
||||
try:
|
||||
user = User.objects.get(email=email)
|
||||
except Exception:
|
||||
raise forms.ValidationError(
|
||||
u"Email not exists. Could not find user by email address {email}.".format(
|
||||
email=email
|
||||
)
|
||||
)
|
||||
|
||||
return user
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Checking the course already exists in db.
|
||||
"""
|
||||
cleaned_data = super(CourseAccessRoleForm, self).clean()
|
||||
if not self.errors:
|
||||
if CourseAccessRole.objects.filter(
|
||||
user=cleaned_data.get("email"),
|
||||
org=cleaned_data.get("org"),
|
||||
course_id=cleaned_data.get("course_id"),
|
||||
role=cleaned_data.get("role")
|
||||
).exists():
|
||||
raise forms.ValidationError("Duplicate Record.")
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class CourseAccessRoleAdmin(admin.ModelAdmin):
|
||||
"""Admin panel for the Course Access Role. """
|
||||
form = CourseAccessRoleForm
|
||||
raw_id_fields = ("user",)
|
||||
list_display = (
|
||||
'id', 'user', 'org', 'course_id', 'role'
|
||||
exclude = ("user",)
|
||||
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('email', 'course_id', 'org', 'role',)
|
||||
}),
|
||||
)
|
||||
|
||||
list_display = (
|
||||
'id', 'user', 'org', 'course_id', 'role',
|
||||
)
|
||||
search_fields = (
|
||||
'id', 'user__username', 'user__email', 'org', 'course_id', 'role',
|
||||
)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
obj.user = form.cleaned_data['email']
|
||||
super(CourseAccessRoleAdmin, self).save_model(request, obj, form, change)
|
||||
|
||||
|
||||
class LinkedInAddToProfileConfigurationAdmin(admin.ModelAdmin):
|
||||
"""Admin interface for the LinkedIn Add to Profile configuration. """
|
||||
|
||||
148
common/djangoapps/student/tests/test_admin_views.py
Normal file
148
common/djangoapps/student/tests/test_admin_views.py
Normal file
@@ -0,0 +1,148 @@
|
||||
"""
|
||||
Tests student admin.py
|
||||
"""
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from student.tests.factories import UserFactory
|
||||
|
||||
|
||||
class AdminCourseRolesPageTest(ModuleStoreTestCase):
|
||||
"""Test the django admin course roles form saving data in db.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(AdminCourseRolesPageTest, self).setUp()
|
||||
self.user = UserFactory.create(is_staff=True, is_superuser=True)
|
||||
self.user.save()
|
||||
self.course = CourseFactory.create(org='edx')
|
||||
|
||||
def test_save_valid_data(self):
|
||||
|
||||
data = {
|
||||
'course_id': unicode(self.course.id),
|
||||
'role': 'finance_admin',
|
||||
'org': 'edx',
|
||||
'email': self.user.email
|
||||
}
|
||||
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
# # adding new role from django admin page
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertRedirects(response, reverse('admin:student_courseaccessrole_changelist'))
|
||||
|
||||
response = self.client.get(reverse('admin:student_courseaccessrole_changelist'))
|
||||
self.assertContains(response, 'Select course access role to change')
|
||||
self.assertContains(response, 'Add course access role')
|
||||
self.assertContains(response, 'finance_admin')
|
||||
self.assertContains(response, unicode(self.course.id))
|
||||
self.assertContains(response, '1 course access role')
|
||||
|
||||
#try adding with same information raise error.
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertContains(response, 'Duplicate')
|
||||
|
||||
def test_save_without_org_and_course_data(self):
|
||||
|
||||
data = {
|
||||
'role': 'staff',
|
||||
'email': self.user.email,
|
||||
'course_id': unicode(self.course.id)
|
||||
}
|
||||
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
# # adding new role from django admin page
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertRedirects(response, reverse('admin:student_courseaccessrole_changelist'))
|
||||
|
||||
response = self.client.get(reverse('admin:student_courseaccessrole_changelist'))
|
||||
self.assertContains(response, 'staff')
|
||||
self.assertContains(response, '1 course access role')
|
||||
|
||||
def test_save_with_course_only(self):
|
||||
|
||||
data = {
|
||||
'role': 'beta_testers',
|
||||
'email': self.user.email,
|
||||
|
||||
}
|
||||
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
# # adding new role from django admin page
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertRedirects(response, reverse('admin:student_courseaccessrole_changelist'))
|
||||
|
||||
response = self.client.get(reverse('admin:student_courseaccessrole_changelist'))
|
||||
self.assertContains(response, 'beta_testers')
|
||||
self.assertContains(response, '1 course access role')
|
||||
|
||||
def test_save_with_org_only(self):
|
||||
|
||||
data = {
|
||||
'role': 'beta_testers',
|
||||
'email': self.user.email,
|
||||
'org': 'myorg'
|
||||
|
||||
}
|
||||
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
# # adding new role from django admin page
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertRedirects(response, reverse('admin:student_courseaccessrole_changelist'))
|
||||
|
||||
response = self.client.get(reverse('admin:student_courseaccessrole_changelist'))
|
||||
self.assertContains(response, 'myorg')
|
||||
self.assertContains(response, '1 course access role')
|
||||
|
||||
def test_save_with_invalid_course(self):
|
||||
|
||||
course = unicode('no/edx/course')
|
||||
email = "invalid@email.com"
|
||||
data = {
|
||||
'course_id': course,
|
||||
'role': 'finance_admin',
|
||||
'org': 'edx',
|
||||
'email': email
|
||||
}
|
||||
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
# Adding new role with invalid data
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertContains(
|
||||
response,
|
||||
'Cannot find course with id {} in the modulestore'.format(
|
||||
course
|
||||
)
|
||||
)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
"Email not exists. Could not find user by email address {}".format(
|
||||
email
|
||||
)
|
||||
)
|
||||
|
||||
def test_save_valid_course_invalid_org(self):
|
||||
|
||||
data = {
|
||||
'course_id': unicode(self.course.id),
|
||||
'role': 'finance_admin',
|
||||
'org': 'edxxx',
|
||||
'email': self.user.email
|
||||
}
|
||||
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
# # adding new role from django admin page
|
||||
response = self.client.post(reverse('admin:student_courseaccessrole_add'), data=data)
|
||||
self.assertContains(
|
||||
response,
|
||||
'Org name {} is not valid. Valid name is {}.'.format(
|
||||
'edxxx', 'edx'
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user