Skip to content

Instantly share code, notes, and snippets.

@davehughes
Created September 6, 2013 00:33
Show Gist options
  • Save davehughes/6458078 to your computer and use it in GitHub Desktop.
Save davehughes/6458078 to your computer and use it in GitHub Desktop.
Implementation of User 'masquerade' in Django.
# 1) Add MasqueradeMiddleware to Django's middleware stack (see comment below for placement)
class MasqueradeMiddleware(object):
'''
Looks for a field in the active session specifying a user to masquerade as
and sets request.user to that user, storing the real user to the session.
This middleware is dependent on the existence of sessions, so it should be
deployed after ('inside') Django's session middleware. It should probably
be deployed after middleware like the TermsAndConditionsMiddleware which
implement one-time intercepts, so that masquerading superusers don't get
redirected to (and have to accept, on behalf of the effective user) the
site terms.
'''
SESSION_KEY_BASE = 'user.base_user'
SESSION_KEY_EFFECTIVE = 'user.effective_user'
def process_request(self, request):
request.is_masquerade_session = False
if hasattr(request, 'session'):
eff_user = request.session.get(self.SESSION_KEY_EFFECTIVE)
if eff_user:
request.user = eff_user
request.is_masquerade_session = True
# 2) Route to this view function (guard with appropriate access control, like is_staff), which turns masquerading
# on and off
def masquerade(request):
if request.method != 'POST':
return http.HttpResponseNotAllowed(['POST'])
BASE_USER = middleware.MasqueradeMiddleware.SESSION_KEY_BASE
EFFECTIVE_USER = middleware.MasqueradeMiddleware.SESSION_KEY_EFFECTIVE
# override user based on session key for authorization purposes
user = request.session.get(BASE_USER, request.user)
if not user.is_superuser:
return http.HttpResponseForbidden()
# update session to reflect changes
if request.POST.get('update'):
user_id = request.POST.get('user_id')
if not user_id:
messages.error(request, 'No user ID provided.')
else:
# set appropriate masquerade info in session
try:
effective_user = User.objects.get(id=user_id)
request.session[EFFECTIVE_USER] = effective_user
request.session[BASE_USER] = user
request.user = effective_user
except User.DoesNotExist:
messages.error(request, 'User does not exist.')
elif request.POST.get('clear'):
# reset current request user and clear masquerade info from session
request.user = user
if EFFECTIVE_USER in request.session:
del request.session[EFFECTIVE_USER]
if BASE_USER in request.session:
del request.session[BASE_USER]
else:
messages.error(request, 'No valid operation specified')
return http.HttpResponseRedirect(request.REQUEST.get('next', '/'))
# 3) (Optional) add this context processor to Django's context processor stack to allow templates to do
# conditional things like displaying a 'stop masquerading' button
def masquerade_context(request):
'''
Context processor that adds an 'is_masquerade_session' variable to
indicate whether the user in the current session is masquerading as another
user (this is superuser functionality).
'''
ms = False
eu = None
if hasattr(request, 'session'):
if request.session.get(MasqueradeMiddleware.SESSION_KEY_EFFECTIVE):
ms = True
eu = request.session.get(MasqueradeMiddleware.SESSION_KEY_EFFECTIVE)
return { 'is_masquerade_session': ms, 'effective_user': eu }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment