Commit fb0a2323 by ichuang

allow staff to masquerade as student - works

Conflicts:
	lms/djangoapps/courseware/views.py
	lms/templates/courseware/course_navigation.html
parent c905cc74
......@@ -15,6 +15,7 @@ from xmodule.modulestore import Location
from xmodule.x_module import XModule, XModuleDescriptor
from student.models import CourseEnrollmentAllowed
from masquerade import is_masquerading_as_student
DEBUG_ACCESS = False
......@@ -543,6 +544,10 @@ def _has_access_to_location(user, location, access_level, course_context):
if user is None or (not user.is_authenticated()):
debug("Deny: no user or anon user")
return False
if is_masquerading_as_student(user):
return False
if user.is_staff:
debug("Allow: user.is_staff")
return True
......
......@@ -5,99 +5,52 @@
import json
import logging
import urllib
from functools import partial
from django.conf import settings
from django.core.context_processors import csrf
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import redirect
from mitxmako.shortcuts import render_to_response, render_to_string
#from django.views.decorators.csrf import ensure_csrf_cookie
from django_future.csrf import ensure_csrf_cookie
from django.views.decorators.cache import cache_control
from django.http import HttpResponse
from courseware import grades
from courseware.access import has_access
from courseware.courses import (get_courses, get_course_with_access,
get_courses_by_university, sort_by_announcement)
import courseware.tabs as tabs
from courseware.models import StudentModuleCache
from module_render import toc_for_course, get_module, get_instance_module, get_module_for_descriptor
from django_comment_client.utils import get_discussion_title
from student.models import UserTestGroup, CourseEnrollment
from util.cache import cache, cache_if_anonymous
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem
from xmodule.modulestore.search import path_to_location
log = logging.getLogger(__name__)
def handle_ajax(request, marg):
log.debug('masquerade handle_ajax marg=%s' % marg)
return HttpResponse(json.dumps({}))
MASQ_KEY = 'masquerade_identity'
def handle_ajax(request, marg):
if marg=='toggle':
status = request.session.get(MASQ_KEY, '')
if status is None or status in ['', 'staff']:
status = 'student'
else:
status = 'staff'
request.session[MASQ_KEY] = status
return HttpResponse(json.dumps({'status': status}))
MASQ_VAR = 'masquerade_identity'
class Masquerade(object):
def setup_masquerade(request, staff_access=False):
'''
Manage masquerade identity (allows staff to view courseware as either staff or student)
Setup masquerade identity (allows staff to view courseware as either staff or student)
State variables:
Uses request.session[MASQ_KEY] to store status of masquerading.
Adds masquerade status to request.user, if masquerading active.
Return string version of status of view (either 'staff' or 'student')
'''
if request.user is None:
return None
actual_user = User instance of the real, un-masqueraded user
user = User instance (what actual user is masquerading as)
usertype = "staff" or "student" or "nonstaff"
if not staff_access: # can masquerade only if user has staff access to course
return None
'''
usertype = request.session.get(MASQ_KEY, '')
if usertype is None or not usertype:
request.session[MASQ_KEY] = 'staff'
usertype = 'staff'
def __init__(self, request, staff_access=False):
'''
request = Django http request object
'''
self.request = request
self.actual_user = request.user
self.user = request.user
self.usertype = "nonstaff"
if request.user is not None and staff_access:
self.usertype = request.session.get(MASQ_VAR,'staff')
if self.usertype=='student':
self.user = self.get_student_user()
if usertype=='student':
request.user.masquerade_as_student = True
def get_student_user(self):
'''
Each staff user can have a corresponding student identity, with
the same username + "__student". Return that User.
Create the student user if doesn't already exist.
'''
suffix = '__student'
if self.user.username.endswith(suffix):
return self.user
user = User.get_or_create(username=self.user+suffix, email=self.user.email)
profile = UserProfile.get_or_create(user=user, name=self.user.profile.name+suffix)
return user
return usertype
def toggle_status(self):
"""
Toggle status from staff from student
"""
if self.usertype=='student':
self.user = self.actual_user
elif self.usertype=='staff':
self.user = self.get_student_user()
def view_status(self):
'''
Return string version of status of view
'''
STAT = {'staff': '<font color="red">Staff view</font>', 'student': '<font color="orange">Student view</font>'}
return STAT.get(self.usertype,'')
def is_masquerading_as_student(user):
masq = getattr(user, 'masquerade_as_student', False)
return masq
......@@ -17,6 +17,7 @@ from django.views.decorators.csrf import csrf_exempt
from requests.auth import HTTPBasicAuth
from capa.xqueue_interface import XQueueInterface
from courseware.masquerade import setup_masquerade
from courseware.access import has_access
from mitxmako.shortcuts import render_to_string
from .models import StudentModule
......@@ -168,6 +169,10 @@ def get_module_for_descriptor(user, request, descriptor, model_data_cache, cours
if not has_access(user, descriptor, 'load', course_id):
return None
# allow course staff to masquerade as student
if has_access(user, descriptor, 'staff', course_id):
setup_masquerade(request, True)
# Setup system context for module instance
ajax_url = reverse('modx_dispatch',
kwargs=dict(course_id=course_id,
......@@ -323,6 +328,7 @@ def get_module_for_descriptor(user, request, descriptor, model_data_cache, cours
return err_descriptor.xmodule(system)
system.set('user_is_staff', has_access(user, descriptor.location, 'staff', course_id))
log.debug('user_is_staff=%s' % system.user_is_staff)
_get_html = module.get_html
if wrap_xmodule_display == True:
......
......@@ -20,6 +20,7 @@ from courseware.access import has_access
from courseware.courses import (get_courses, get_course_with_access,
get_courses_by_university, sort_by_announcement)
import courseware.tabs as tabs
from courseware.masquerade import setup_masquerade
from courseware.model_data import ModelDataCache
from .module_render import toc_for_course, get_module_for_descriptor, get_module
from courseware.models import StudentModule, StudentModuleHistory
......@@ -268,6 +269,8 @@ def index(request, course_id, chapter=None, section=None,
log.debug('User %s tried to view course %s but is not enrolled' % (user, course.location.url()))
return redirect(reverse('about_course', args=[course.id]))
masq = setup_masquerade(request, staff_access)
try:
model_data_cache = ModelDataCache.cache_for_descriptor_descendents(
course.id, user, course, depth=2)
......
......@@ -27,6 +27,38 @@ def url_class(is_active):
</li>
% endfor
<%block name="extratabs" />
%if staff_access and masquerade:
<li style="float:right"><a href="#" id="staffstatus">Staff view</a></li>
%endif
</ol>
</div>
</nav>
%if staff_access and masquerade:
<script type="text/javascript">
masq = (function(){
var el = $('#staffstatus');
var setstat = function(status){
if (status=='student'){
el.html('<font color="green">Student view</font>');
}else{
el.html('<font color="red">Staff view</font>');
}
}
setstat('${masquerade}');
el.click(function(){
$.ajax({ url: '/masquerade/toggle',
type: 'GET',
success: function(result){
setstat(result.status);
location.reload();
},
error: function() {
alert('Error: cannot connect to server');
}
});
});
}() );
</script>
%endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment