Clean up Forum Admin section of legacy dashboard
This commit is contained in:
@@ -1,144 +0,0 @@
|
||||
"""
|
||||
Unit tests for instructor dashboard forum administration
|
||||
"""
|
||||
|
||||
|
||||
from django.test.utils import override_settings
|
||||
|
||||
# Need access to internal func to put users in the right group
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django_comment_common.models import Role, FORUM_ROLE_ADMINISTRATOR, \
|
||||
FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT
|
||||
from django_comment_client.utils import has_forum_access
|
||||
|
||||
from courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MOCK_MODULESTORE
|
||||
from student.roles import CourseStaffRole
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
FORUM_ROLES = [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA]
|
||||
FORUM_ADMIN_ACTION_SUFFIX = {FORUM_ROLE_ADMINISTRATOR: 'admin', FORUM_ROLE_MODERATOR: 'moderator', FORUM_ROLE_COMMUNITY_TA: 'community TA'}
|
||||
FORUM_ADMIN_USER = {FORUM_ROLE_ADMINISTRATOR: 'forumadmin', FORUM_ROLE_MODERATOR: 'forummoderator', FORUM_ROLE_COMMUNITY_TA: 'forummoderator'}
|
||||
|
||||
|
||||
def action_name(operation, rolename):
|
||||
if operation == 'List':
|
||||
return '{0} course forum {1}s'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename])
|
||||
else:
|
||||
return '{0} forum {1}'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename])
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MOCK_MODULESTORE)
|
||||
class TestInstructorDashboardForumAdmin(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
'''
|
||||
Check for change in forum admin role memberships
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
self.toy = CourseFactory.create(org='edX', course='toy', display_name='2012_Fall')
|
||||
|
||||
# Create two accounts
|
||||
self.student = 'view@test.com'
|
||||
self.instructor = 'view2@test.com'
|
||||
self.password = 'foo'
|
||||
self.create_account('u1', self.student, self.password)
|
||||
self.create_account('u2', self.instructor, self.password)
|
||||
self.activate_user(self.student)
|
||||
self.activate_user(self.instructor)
|
||||
|
||||
CourseStaffRole(self.toy.id).add_users(User.objects.get(email=self.instructor))
|
||||
|
||||
self.logout()
|
||||
self.login(self.instructor, self.password)
|
||||
self.enroll(self.toy)
|
||||
|
||||
def initialize_roles(self, course_id):
|
||||
self.admin_role = Role.objects.get_or_create(name=FORUM_ROLE_ADMINISTRATOR, course_id=course_id)[0]
|
||||
self.moderator_role = Role.objects.get_or_create(name=FORUM_ROLE_MODERATOR, course_id=course_id)[0]
|
||||
self.community_ta_role = Role.objects.get_or_create(name=FORUM_ROLE_COMMUNITY_TA, course_id=course_id)[0]
|
||||
|
||||
def test_add_forum_admin_users_for_unknown_user(self):
|
||||
course = self.toy
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'unknown'
|
||||
for action in ['Add', 'Remove']:
|
||||
for rolename in FORUM_ROLES:
|
||||
response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertTrue(response.content.find('Error: unknown username "{0}"'.format(username)) >= 0)
|
||||
|
||||
def test_add_forum_admin_users_for_missing_roles(self):
|
||||
course = self.toy
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'u1'
|
||||
for action in ['Add', 'Remove']:
|
||||
for rolename in FORUM_ROLES:
|
||||
response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertTrue(response.content.find('Error: unknown rolename "{0}"'.format(rolename)) >= 0)
|
||||
|
||||
def test_remove_forum_admin_users_for_missing_users(self):
|
||||
course = self.toy
|
||||
self.initialize_roles(course.id)
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'u1'
|
||||
action = 'Remove'
|
||||
for rolename in FORUM_ROLES:
|
||||
response = self.client.post(url, {'action': action_name(action, rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertTrue(response.content.find('Error: user "{0}" does not have rolename "{1}"'.format(username, rolename)) >= 0)
|
||||
|
||||
def test_add_and_remove_forum_admin_users(self):
|
||||
course = self.toy
|
||||
self.initialize_roles(course.id)
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'u2'
|
||||
for rolename in FORUM_ROLES:
|
||||
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertContains(response, 'Added "{0}" to "{1}" forum role = "{2}"'.format(username, course.id.to_deprecated_string(), rolename))
|
||||
self.assertTrue(has_forum_access(username, course.id, rolename))
|
||||
response = self.client.post(url, {'action': action_name('Remove', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertContains(response, 'Removed "{0}" from "{1}" forum role = "{2}"'.format(username, course.id.to_deprecated_string(), rolename))
|
||||
self.assertFalse(has_forum_access(username, course.id, rolename))
|
||||
|
||||
def test_add_and_read_forum_admin_users(self):
|
||||
course = self.toy
|
||||
self.initialize_roles(course.id)
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'u2'
|
||||
for rolename in FORUM_ROLES:
|
||||
# perform an add, and follow with a second identical add:
|
||||
self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertTrue(response.content.find('Error: user "{0}" already has rolename "{1}", cannot add'.format(username, rolename)) >= 0)
|
||||
self.assertTrue(has_forum_access(username, course.id, rolename))
|
||||
|
||||
def test_add_nonstaff_forum_admin_users(self):
|
||||
course = self.toy
|
||||
self.initialize_roles(course.id)
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'u1'
|
||||
rolename = FORUM_ROLE_ADMINISTRATOR
|
||||
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertTrue(response.content.find('Error: user "{0}" should first be added as staff'.format(username)) >= 0)
|
||||
|
||||
def test_list_forum_admin_users(self):
|
||||
course = self.toy
|
||||
self.initialize_roles(course.id)
|
||||
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
|
||||
username = 'u2'
|
||||
added_roles = [FORUM_ROLE_STUDENT] # u2 is already added as a student to the discussion forums
|
||||
self.assertTrue(has_forum_access(username, course.id, 'Student'))
|
||||
for rolename in FORUM_ROLES:
|
||||
response = self.client.post(url, {'action': action_name('Add', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
self.assertTrue(has_forum_access(username, course.id, rolename))
|
||||
response = self.client.post(url, {'action': action_name('List', rolename), FORUM_ADMIN_USER[rolename]: username})
|
||||
for header in ['Username', 'Full name', 'Roles']:
|
||||
self.assertTrue(response.content.find('<th>{0}</th>'.format(header)) > 0)
|
||||
self.assertTrue(response.content.find('<td>{0}</td>'.format(username)) >= 0)
|
||||
# concatenate all roles for user, in sorted order:
|
||||
added_roles.append(rolename)
|
||||
added_roles.sort()
|
||||
roles = ', '.join(added_roles)
|
||||
self.assertTrue(response.content.find('<td>{0}</td>'.format(roles)) >= 0, 'not finding roles "{0}"'.format(roles))
|
||||
@@ -399,86 +399,6 @@ def instructor_dashboard(request, course_id):
|
||||
msg += "<p>{0}</p>".format(
|
||||
remove_user_from_role(request, username_or_email, role, 'beta testers', 'beta-tester'))
|
||||
|
||||
#----------------------------------------
|
||||
# forum administration
|
||||
|
||||
elif action == 'List course forum admins':
|
||||
rolename = FORUM_ROLE_ADMINISTRATOR
|
||||
datatable = {}
|
||||
msg += _list_course_forum_members(course_key, rolename, datatable)
|
||||
track.views.server_track(
|
||||
request, "list-forum-admins", {"course": course_key.to_deprecated_string()}, page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'Remove forum admin':
|
||||
uname = request.POST['forumadmin']
|
||||
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_REMOVE)
|
||||
track.views.server_track(
|
||||
request, "remove-forum-admin", {"username": uname, "course": course_key.to_deprecated_string()},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'Add forum admin':
|
||||
uname = request.POST['forumadmin']
|
||||
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_ADD)
|
||||
track.views.server_track(
|
||||
request, "add-forum-admin", {"username": uname, "course": course_key.to_deprecated_string()},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'List course forum moderators':
|
||||
rolename = FORUM_ROLE_MODERATOR
|
||||
datatable = {}
|
||||
msg += _list_course_forum_members(course_key, rolename, datatable)
|
||||
track.views.server_track(
|
||||
request, "list-forum-mods", {"course": course_key.to_deprecated_string()}, page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'Remove forum moderator':
|
||||
uname = request.POST['forummoderator']
|
||||
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_MODERATOR, FORUM_ROLE_REMOVE)
|
||||
track.views.server_track(
|
||||
request, "remove-forum-mod", {"username": uname, "course": course_key.to_deprecated_string()},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'Add forum moderator':
|
||||
uname = request.POST['forummoderator']
|
||||
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_MODERATOR, FORUM_ROLE_ADD)
|
||||
track.views.server_track(
|
||||
request, "add-forum-mod", {"username": uname, "course": course_key.to_deprecated_string()},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'List course forum community TAs':
|
||||
rolename = FORUM_ROLE_COMMUNITY_TA
|
||||
datatable = {}
|
||||
msg += _list_course_forum_members(course_key, rolename, datatable)
|
||||
track.views.server_track(
|
||||
request, "list-forum-community-TAs", {"course": course_key.to_deprecated_string()},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'Remove forum community TA':
|
||||
uname = request.POST['forummoderator']
|
||||
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_REMOVE)
|
||||
track.views.server_track(
|
||||
request, "remove-forum-community-TA", {
|
||||
"username": uname, "course": course_key.to_deprecated_string()
|
||||
},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
elif action == 'Add forum community TA':
|
||||
uname = request.POST['forummoderator']
|
||||
msg += _update_forum_role_membership(uname, course, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_ADD)
|
||||
track.views.server_track(
|
||||
request, "add-forum-community-TA", {
|
||||
"username": uname, "course": course_key.to_deprecated_string()
|
||||
},
|
||||
page="idashboard"
|
||||
)
|
||||
|
||||
#----------------------------------------
|
||||
# enrollment
|
||||
|
||||
@@ -778,81 +698,6 @@ def _do_remote_gradebook(user, course, action, args=None, files=None):
|
||||
|
||||
return msg, datatable
|
||||
|
||||
|
||||
def _list_course_forum_members(course_key, rolename, datatable):
|
||||
"""
|
||||
Fills in datatable with forum membership information, for a given role,
|
||||
so that it will be displayed on instructor dashboard.
|
||||
|
||||
course_ID = the CourseKey for a course
|
||||
rolename = one of "Administrator", "Moderator", "Community TA"
|
||||
|
||||
Returns message status string to append to displayed message, if role is unknown.
|
||||
"""
|
||||
# make sure datatable is set up properly for display first, before checking for errors
|
||||
datatable['header'] = [_('Username'), _('Full name'), _('Roles')]
|
||||
datatable['title'] = _('List of Forum {name}s in course {id}').format(
|
||||
name=rolename, id=course_key.to_deprecated_string()
|
||||
)
|
||||
datatable['data'] = []
|
||||
try:
|
||||
role = Role.objects.get(name=rolename, course_id=course_key)
|
||||
except Role.DoesNotExist:
|
||||
return '<font color="red">' + _('Error: unknown rolename "{rolename}"').format(rolename=rolename) + '</font>'
|
||||
uset = role.users.all().order_by('username')
|
||||
msg = 'Role = {0}'.format(rolename)
|
||||
log.debug('role={0}'.format(rolename))
|
||||
datatable['data'] = [[x.username, x.profile.name, ', '.join([
|
||||
r.name for r in x.roles.filter(course_id=course_key).order_by('name')
|
||||
])] for x in uset]
|
||||
return msg
|
||||
|
||||
|
||||
def _update_forum_role_membership(uname, course, rolename, add_or_remove):
|
||||
'''
|
||||
Supports adding a user to a course's forum role
|
||||
|
||||
uname = username string for user
|
||||
course = course object
|
||||
rolename = one of "Administrator", "Moderator", "Community TA"
|
||||
add_or_remove = one of "add" or "remove"
|
||||
|
||||
Returns message status string to append to displayed message, Status is returned if user
|
||||
or role is unknown, or if entry already exists when adding, or if entry doesn't exist when removing.
|
||||
'''
|
||||
# check that username and rolename are valid:
|
||||
try:
|
||||
user = User.objects.get(username=uname)
|
||||
except User.DoesNotExist:
|
||||
return '<font color="red">' + _('Error: unknown username "{username}"').format(username=uname) + '</font>'
|
||||
try:
|
||||
role = Role.objects.get(name=rolename, course_id=course.id)
|
||||
except Role.DoesNotExist:
|
||||
return '<font color="red">' + _('Error: unknown rolename "{rolename}"').format(rolename=rolename) + '</font>'
|
||||
|
||||
# check whether role already has the specified user:
|
||||
alreadyexists = role.users.filter(username=uname).exists()
|
||||
msg = ''
|
||||
log.debug('rolename={0}'.format(rolename))
|
||||
if add_or_remove == FORUM_ROLE_REMOVE:
|
||||
if not alreadyexists:
|
||||
msg = '<font color="red">' + _('Error: user "{username}" does not have rolename "{rolename}", cannot remove').format(username=uname, rolename=rolename) + '</font>'
|
||||
else:
|
||||
user.roles.remove(role)
|
||||
msg = '<font color="green">' + _('Removed "{username}" from "{course_id}" forum role = "{rolename}"').format(username=user, course_id=course.id.to_deprecated_string(), rolename=rolename) + '</font>'
|
||||
else:
|
||||
if alreadyexists:
|
||||
msg = '<font color="red">' + _('Error: user "{username}" already has rolename "{rolename}", cannot add').format(username=uname, rolename=rolename) + '</font>'
|
||||
else:
|
||||
if (rolename == FORUM_ROLE_ADMINISTRATOR and not has_access(user, 'staff', course)):
|
||||
msg = '<font color="red">' + _('Error: user "{username}" should first be added as staff before adding as a forum administrator, cannot add').format(username=uname) + '</font>'
|
||||
else:
|
||||
user.roles.add(role)
|
||||
msg = '<font color="green">' + _('Added "{username}" to "{course_id}" forum role = "{rolename}"').format(username=user, course_id=course.id.to_deprecated_string(), rolename=rolename) + '</font>'
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def _role_members_table(role, title, course_key):
|
||||
"""
|
||||
Return a data table of usernames and names of users in group_name.
|
||||
|
||||
@@ -314,38 +314,7 @@ function goto( mode)
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
%if modeflag.get('Forum Admin'):
|
||||
%if instructor_access:
|
||||
<hr width="40%" style="align:left">
|
||||
<p>
|
||||
<input type="submit" name="action" value="List course forum admins">
|
||||
<p>
|
||||
<input type="text" name="forumadmin"> <input type="submit" name="action" value="Remove forum admin">
|
||||
<input type="submit" name="action" value="Add forum admin">
|
||||
<hr width="40%" style="align:left">
|
||||
%endif
|
||||
|
||||
%if instructor_access or forum_admin_access:
|
||||
<p>
|
||||
<input type="submit" name="action" value="List course forum moderators">
|
||||
<input type="submit" name="action" value="List course forum community TAs">
|
||||
<p>
|
||||
<input type="text" name="forummoderator">
|
||||
<input type="submit" name="action" value="Remove forum moderator">
|
||||
<input type="submit" name="action" value="Add forum moderator">
|
||||
<input type="submit" name="action" value="Remove forum community TA">
|
||||
<input type="submit" name="action" value="Add forum community TA">
|
||||
<hr width="40%" style="align:left">
|
||||
%else:
|
||||
<p>${_("User requires forum administrator privileges to perform administration tasks. See instructor.")}</p>
|
||||
%endif
|
||||
|
||||
<br />
|
||||
<h2>${_("Explanation of Roles:")}</h2>
|
||||
<p>${_("Forum Moderators: can edit or delete any post, remove misuse flags, close and re-open threads, endorse "
|
||||
"responses, and see posts from all cohorts (if the course is cohorted). Moderators' posts are marked as 'staff'.")}</p>
|
||||
<p>${_("Forum Admins: have moderator privileges, as well as the ability to edit the list of forum moderators "
|
||||
"(e.g. to appoint a new moderator). Admins' posts are marked as 'staff'.")}</p>
|
||||
<p>${_("Community TAs: have forum moderator privileges, and their posts are labelled 'Community TA'.")}</p>
|
||||
<p class="deprecated">${_("To manage forum roles, please visit the 'Membership' section of the instructor dashboard.")}</p>
|
||||
%endif
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user