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__)
MASQ_KEY = 'masquerade_identity'
def handle_ajax(request, marg):
log.debug('masquerade handle_ajax marg=%s' % marg)
return HttpResponse(json.dumps({}))
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'
def setup_masquerade(request, staff_access=False):
'''
Setup masquerade identity (allows staff to view courseware as either staff or student)
class Masquerade(object):
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')
'''
Manage masquerade identity (allows staff to view courseware as either staff or student)
if request.user is None:
return None
State variables:
if not staff_access: # can masquerade only if user has staff access to course
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"
'''
usertype = request.session.get(MASQ_KEY, '')
if usertype is None or not usertype:
request.session[MASQ_KEY] = 'staff'
usertype = 'staff'
if usertype=='student':
request.user.masquerade_as_student = True
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()
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