Skip to content
Snippets Groups Projects
Commit d4a06794 authored by Sarina Canelake's avatar Sarina Canelake
Browse files

Clean up Forum Admin section of legacy dashboard

parent 5d7f820d
No related merge requests found
"""
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
##-----------------------------------------------------------------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment