Skip to content

Commit af26138

Browse files
authored
Add django-impersonate when admin is enabled (#11894)
This used to live in .com, but I also find it useful to debug things in .org, specially now with the new dashboard. We used to check if the IMPERSONATE setting was defined in order to add the URLs, but since we are always using this when the admin is enabled, I'm just checking for that, that will allow us to have less code on .com/ops.
1 parent 18c31c9 commit af26138

File tree

8 files changed

+47
-1
lines changed

8 files changed

+47
-1
lines changed

readthedocs/core/admin.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from django.utils.html import format_html
1111
from django.utils.safestring import mark_safe
1212
from django.utils.translation import gettext_lazy as _
13+
from impersonate.admin import UserAdminImpersonateMixin
1314
from rest_framework.authtoken.admin import TokenAdmin
1415

1516
from readthedocs.core.history import ExtraSimpleHistoryAdmin
@@ -64,7 +65,7 @@ def queryset(self, request, queryset):
6465
return queryset.filter(projects__builds__date__gt=recent_date)
6566

6667

67-
class UserAdminExtra(ExtraSimpleHistoryAdmin, UserAdmin):
68+
class UserAdminExtra(ExtraSimpleHistoryAdmin, UserAdminImpersonateMixin, UserAdmin):
6869

6970
"""Admin configuration for User."""
7071

@@ -80,6 +81,9 @@ class UserAdminExtra(ExtraSimpleHistoryAdmin, UserAdmin):
8081
actions = ["ban_user", "sync_remote_repositories_action"]
8182
inlines = [UserProjectInline]
8283

84+
# Open a new tab when impersonating a user.
85+
open_new_window = True
86+
8387
@admin.display(
8488
description="Banned",
8589
boolean=True,

readthedocs/settings/base.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ def INSTALLED_APPS(self): # noqa
297297
"allauth.socialaccount.providers.gitlab",
298298
"allauth.socialaccount.providers.bitbucket_oauth2",
299299
"allauth.mfa",
300+
# Others
301+
# NOTE: impersonate functionality is only enabled when ALLOW_ADMIN is True,
302+
# but we still need to include it even when not enabled, since it has objects
303+
# related to the user model that Django needs to know about when deleting users.
304+
"impersonate",
300305
"cacheops",
301306
]
302307
if ext:
@@ -348,6 +353,8 @@ def MIDDLEWARE(self):
348353
]
349354
if self.SHOW_DEBUG_TOOLBAR:
350355
middlewares.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware")
356+
if self.ALLOW_ADMIN:
357+
middlewares.append("impersonate.middleware.ImpersonateMiddleware")
351358
return middlewares
352359

353360
AUTHENTICATION_BACKENDS = (
@@ -830,6 +837,12 @@ def SOCIALACCOUNT_PROVIDERS(self):
830837

831838
INTERNAL_IPS = ("127.0.0.1",)
832839

840+
# django-impersonate.
841+
IMPERSONATE = {
842+
# By default, only staff users can impersonate.
843+
"REQUIRE_SUPERUSER": True,
844+
}
845+
833846
# Taggit
834847
# https://django-taggit.readthedocs.io
835848
TAGGIT_TAGS_FROM_STRING = "readthedocs.projects.tag_utils.rtd_parse_tags"

readthedocs/urls.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.contrib import admin
88
from django.urls import include, path, re_path
99
from django.views.generic.base import RedirectView, TemplateView
10+
from impersonate.views import impersonate, stop_impersonate
1011

1112
from readthedocs.core.views import ErrorView, HomepageView, SupportView, do_not_track
1213
from readthedocs.search.views import GlobalSearchView
@@ -105,6 +106,22 @@
105106
re_path(r"^admin/", admin.site.urls),
106107
]
107108

109+
impersonate_urls = [
110+
# We don't use ``include('impersonate.urls')`` here because we don't want to
111+
# define ``/search`` and ``/list`` URLs
112+
path(
113+
"impersonate/stop/",
114+
stop_impersonate,
115+
name="impersonate-stop",
116+
),
117+
path(
118+
"impersonate/<path:uid>/",
119+
impersonate,
120+
name="impersonate-start",
121+
),
122+
]
123+
124+
108125
dnt_urls = [
109126
re_path(r"^\.well-known/dnt/$", do_not_track),
110127
# https://github.com/EFForg/dnt-guide#12-how-to-assert-dnt-compliance
@@ -158,6 +175,7 @@
158175

159176
if settings.ALLOW_ADMIN:
160177
groups.append(admin_urls)
178+
groups.append(impersonate_urls)
161179

162180
if settings.SHOW_DEBUG_TOOLBAR:
163181
import debug_toolbar

requirements/deploy.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ django-formtools==2.5.1
155155
# via -r requirements/pip.txt
156156
django-gravatar2==1.4.5
157157
# via -r requirements/pip.txt
158+
django-impersonate==1.9.4
159+
# via -r requirements/pip.txt
158160
django-ipware==5.0.2
159161
# via
160162
# -r requirements/pip.txt

requirements/docker.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ django-formtools==2.5.1
165165
# via -r requirements/pip.txt
166166
django-gravatar2==1.4.5
167167
# via -r requirements/pip.txt
168+
django-impersonate==1.9.4
169+
# via -r requirements/pip.txt
168170
django-ipware==5.0.2
169171
# via
170172
# -r requirements/pip.txt

requirements/pip.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ jsonfield
3535

3636
django-safemigrate
3737

38+
# Impersonate users in the Django admin for support.
39+
django-impersonate
40+
3841
# The latest version of requests isn't compatible with the
3942
# version of the docker-py library we're using.
4043
# See https://github.com/docker/docker-py/issues/3256.

requirements/pip.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ django-formtools==2.5.1
117117
# via -r requirements/pip.in
118118
django-gravatar2==1.4.5
119119
# via -r requirements/pip.in
120+
django-impersonate==1.9.4
121+
# via -r requirements/pip.in
120122
django-ipware==5.0.2
121123
# via
122124
# -r requirements/pip.in

requirements/testing.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ django-formtools==2.5.1
162162
# via -r requirements/pip.txt
163163
django-gravatar2==1.4.5
164164
# via -r requirements/pip.txt
165+
django-impersonate==1.9.4
166+
# via -r requirements/pip.txt
165167
django-ipware==5.0.2
166168
# via
167169
# -r requirements/pip.txt

0 commit comments

Comments
 (0)