Skip to content

Instantly share code, notes, and snippets.

@wbbradley
Forked from davehughes/gist:6458078
Last active December 23, 2015 11:29
Show Gist options
  • Save wbbradley/6628780 to your computer and use it in GitHub Desktop.
Save wbbradley/6628780 to your computer and use it in GitHub Desktop.
# 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'])
SESSION_KEY_BASE = middleware.MasqueradeMiddleware.SESSION_KEY_BASE
SESSION_KEY_EFFECTIVE = middleware.MasqueradeMiddleware.SESSION_KEY_EFFECTIVE
# override user based on session key for authorization purposes
user = request.session.get(SESSION_KEY_BASE, 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[SESSION_KEY_EFFECTIVE] = effective_user
request.session[SESSION_KEY_BASE] = 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 SESSION_KEY_EFFECTIVE in request.session:
del request.session[SESSION_KEY_EFFECTIVE]
if SESSION_KEY_BASE in request.session:
del request.session[SESSION_KEY_BASE]
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