Skip to main content

Django Impersonate Permissions

Add ability to control impersonate permissions.

Impersonate is a powerful Django app that allow site admins to log in to a user's account, and take actions on their behalf. This can be invalulable in providing technical support. However, with great power comes great responsiblity, and operationally you should never impersonate a user without their explicit consent.

This app provides a mechanism for recording user consent, and enforcing it.

How it works

The core concept is the "permission window". This is a time period during which the user has granted access to their account. How you determine when to ask for access is up to you - this library makes no assumptions about that.

The starting point is saving a new PermissionWindow object:

# views.py
def grant_permission(request):
    """Create a new PermissionWindow, allowing the user to be impersonated."""
    window = PermissionWindow.objects.create(user=request.user)
    return HttpResponse("OK")

Once you have an active PermissionWindow, the user will appear in the users_impersonable queryset. Whilst you are impersonating a user, the middleware will check that the permissions window is still valid. If it expires (or is disabled), the middleware will redirect the request to the impersonate-stop URL, effectively logging the impersonator out of the impersonation session.

Use

The app itself contains a model, PermissionWindow, that is use to record a user's permission, and a middleware class, EnforcePermissionWindowMiddleware that is used to enforce it.

You will need to add the middleware to your MIDDLEWARE Django settings. It also contains a function users_impersonable that you should set to the as the impersonate CUSTOM_USER_QUERYSET function:

# settings.py
INSTALLED_APPS = (
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.humanize",
    "impersonate",
    "impersonate_permissions",
    ...
)

MIDDLEWARE = (
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "impersonate.middleware.ImpersonateMiddleware",
    "impersonate_permissions.middleware.EnforcePermissionWindowMiddleware",
    "impersonate_permissions.middleware.ImpersonationAlertMiddleware",
    ...
)

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [path.join(PROJECT_DIR, "templates")],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.contrib.messages.context_processors.messages",
                "django.contrib.auth.context_processors.auth",
                "impersonate_permissions.context_processors.impersonation",
            ]
        },
    }
]

IMPERSONATE = {
    "CUSTOM_USER_QUERYSET": "impersonate_permissions.models.users_impersonable",
    "DEFAULT_PERMISSION_EXPIRY": 60,
    "PERMISSION_EXPIRY_WARNING_INTERVAL": 10,
}

There is a second piece of middleware, ImpersonationAlertMiddleware, that is optional - if installed it will add a flash message (using the django.contrib.messages app) for users who are being impersonated.

Templates

There are three templates included with the app, impersonating.tpl, expired.tpl, and impersonated.tpl, that are used to render the flash messages shown to users who are impersonating, or being impersonated. You can overwrite these templates to change the message if you wish.

Context Processor

There is a context processor, impersonation, which can be used to add three properties to template render contexts. This is just a shortcut to existing request properties:

{
    "is_impersonate": True,
    "impersonator": request.real_user,
    "impersonating": request.user,
}

Settings

The following settings can be set in the Django settings module, as part of the IMPERSONATE dictionary.

DEFAULT_PERMISSION_EXPIRY

An integer value that defines the default length of a permission 'window', in minutes, thereby setting its expiry.

Default value is 60 - which equates to a one hour window.

PERMISSION_EXPIRY_WARNING_INTERVAL

An integer value which is used to turn the impersation message level from INFO to WARNING. Value is in minutes.

Default value is 10, which means that the message will change 10 minutes before the session expires.

License

MIT.

Contributing

If you want to contribute, add features, fix bugs - thank you.

The project uses Poetry to handle dependencies, and it comes will a working Django project that you can use for testing.

Tests

To begin, it's best to install the virtualenv and check that the tests run:

$ poetry install
$ poetry run pytest

Once you have a working test run, you can set up the project locally (it uses SQLite), create a superuser account, and spin up the site:

$ poetry shell
(venv) $ python manage.py migrate
(venv) $ python manage.py createsuperuser
(venv) $ python manage.py runserver

Code style

The project contains a pre-commit config, and you should set this up before committing any code:

$ pre-commit install

Code must be formatted using isort and black.

All new code should use type hints.

CI

The project contains a .travis.yml config, and the tests will run on any new PR. This config runs the tests and a suite of linting / formatting tools: isort, black, pylint, flake8 (with bandit and pydocstyle) and mypy.

Metadata

Release files for django-impersonate-permissions 0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-impersonate-permissions 0.4
File Size Uploaded
django-impersonate-permissions-0.4.tar.gz 10.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-impersonate-permissions 0.4
File Interpreter ABI Platform
django_impersonate_permissions-0.4-py3-none-any.whl Python 3 none any Details

Total release size: 21.7 kB

Release files / django-impersonate-permissions-0.4.tar.gz

Download URL django-impersonate-permissions-0.4.tar.gz
Size 10.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8b11960ffd92fe4490162c603cc24060db4c89159934557a50d6b547cf9a3919
BLAKE2b-256 checksum
How to use checksums
48fc512bd40f4db5d41c4d4cfd552186fa3eb494be4d93b39e4b663734deb7f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.2 CPython/3.8.1 Darwin/19.5.0

Release files / django_impersonate_permissions-0.4-py3-none-any.whl

Download URL django_impersonate_permissions-0.4-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cec0852063d3124d6fff581cc54b4673fe03e4b69670f0a50853ae9de5dffe51
BLAKE2b-256 checksum
How to use checksums
e375c74ff1ab1d28e0ef3650216c2e9b0437d2f68495ea81ddb912c37ab87b9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.2 CPython/3.8.1 Darwin/19.5.0
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page