Plain is headed towards 1.0! Subscribe for development updates →

plain.impersonate

See what your users see.

A key feature for providing customer support is to be able to view the site through their account. With impersonate installed, you can impersonate a user by finding them in the Django admin and clicking the "Impersonate" button.

Then with the staff toolbar enabled, you'll get a notice of the impersonation and a button to exit:

Installation

To impersonate users, you need the app, middleware, and URLs:

# settings.py
INSTALLED_PACKAGES = INSTALLED_PACKAGES + [
  "plain.staff.impersonate",
]

MIDDLEWARE = MIDDLEWARE + [
  "plain.staff.impersonate.ImpersonateMiddleware",
]
# urls.py
urlpatterns = [
    # ...
    path("impersonate/", include("plain.staff.impersonate.urls")),
]

Settings

By default, all staff users can impersonate other users.

# settings.py
IMPERSONATE_ALLOWED = lambda user: user.is_staff
 1from plain.auth import get_user_model
 2from plain.http import ResponseForbidden
 3
 4from .permissions import can_be_impersonator, can_impersonate_user
 5from .views import IMPERSONATE_KEY
 6
 7
 8def get_user_by_pk(pk):
 9    UserModel = get_user_model()
10
11    try:
12        return UserModel.objects.get(pk=pk)
13    except UserModel.DoesNotExist:
14        return None
15
16
17class ImpersonateMiddleware:
18    def __init__(self, get_response):
19        self.get_response = get_response
20
21    def __call__(self, request):
22        if (
23            IMPERSONATE_KEY in request.session
24            and request.user
25            and can_be_impersonator(request.user)
26        ):
27            user_to_impersonate = get_user_by_pk(request.session[IMPERSONATE_KEY])
28            if user_to_impersonate:
29                if not can_impersonate_user(request.user, user_to_impersonate):
30                    # Can't impersonate this user, remove it and show an error
31                    del request.session[IMPERSONATE_KEY]
32                    return ResponseForbidden()
33
34                # Finally, change the request user and keep a reference to the original
35                request.impersonator = request.user
36                request.user = user_to_impersonate
37
38        return self.get_response(request)