Skip to content

Commit 154ee10

Browse files
committed
Remove user and session from request attributes
1 parent 6d14f44 commit 154ee10

File tree

39 files changed

+344
-166
lines changed

39 files changed

+344
-166
lines changed

demos/full/app/settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
MIDDLEWARE = [
3636
"plain.sessions.middleware.SessionMiddleware",
37-
"plain.auth.middleware.AuthenticationMiddleware",
3837
"plain.admin.AdminMiddleware",
3938
]
4039

plain-admin/plain/admin/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ AUTH_LOGIN_URL = "login"
141141

142142
MIDDLEWARE = [
143143
"plain.sessions.middleware.SessionMiddleware",
144-
"plain.auth.middleware.AuthenticationMiddleware",
145144
"plain.admin.AdminMiddleware",
146145
]
147146
```
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
from .middleware import ImpersonateMiddleware
2+
from .requests import get_request_impersonator
23

3-
__all__ = ["ImpersonateMiddleware"]
4+
__all__ = [
5+
"ImpersonateMiddleware",
6+
"get_request_impersonator",
7+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
IMPERSONATE_SESSION_KEY = "impersonate"
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
from plain.auth import get_user_model
2+
from plain.auth.requests import get_request_user, set_request_user
23
from plain.http import ResponseForbidden
4+
from plain.sessions import get_request_session
35

6+
from .constants import IMPERSONATE_SESSION_KEY
47
from .permissions import can_be_impersonator, can_impersonate_user
5-
from .views import IMPERSONATE_KEY
8+
from .requests import set_request_impersonator
69

710

811
def get_user_by_id(id):
@@ -19,20 +22,24 @@ def __init__(self, get_response):
1922
self.get_response = get_response
2023

2124
def __call__(self, request):
25+
session = get_request_session(request)
26+
user = get_request_user(request)
27+
2228
if (
23-
IMPERSONATE_KEY in request.session
24-
and request.user
25-
and can_be_impersonator(request.user)
29+
session
30+
and IMPERSONATE_SESSION_KEY in session
31+
and user
32+
and can_be_impersonator(user)
2633
):
27-
user_to_impersonate = get_user_by_id(request.session[IMPERSONATE_KEY])
34+
user_to_impersonate = get_user_by_id(session[IMPERSONATE_SESSION_KEY])
2835
if user_to_impersonate:
29-
if not can_impersonate_user(request.user, user_to_impersonate):
36+
if not can_impersonate_user(user, user_to_impersonate):
3037
# Can't impersonate this user, remove it and show an error
31-
del request.session[IMPERSONATE_KEY]
38+
del session[IMPERSONATE_SESSION_KEY]
3239
return ResponseForbidden()
3340

3441
# Finally, change the request user and keep a reference to the original
35-
request.impersonator = request.user
36-
request.user = user_to_impersonate
42+
set_request_impersonator(request, user)
43+
set_request_user(request, user_to_impersonate)
3744

3845
return self.get_response(request)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
from weakref import WeakKeyDictionary
5+
6+
if TYPE_CHECKING:
7+
from plain.auth import get_user_model
8+
from plain.http import Request
9+
10+
User = get_user_model()
11+
12+
_request_impersonators: WeakKeyDictionary[Request, User] = WeakKeyDictionary()
13+
14+
15+
def set_request_impersonator(request: Request, impersonator: User) -> None:
16+
"""Store the impersonator (original user) for this request."""
17+
_request_impersonators[request] = impersonator
18+
19+
20+
def get_request_impersonator(request: Request) -> User | None:
21+
"""Get the impersonator (original user) for this request, if any."""
22+
return _request_impersonators.get(request)
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1+
from plain.auth.views import AuthViewMixin
12
from plain.http import ResponseForbidden, ResponseRedirect
3+
from plain.sessions.views import SessionViewMixin
24
from plain.views import View
35

6+
from .constants import IMPERSONATE_SESSION_KEY
47
from .permissions import can_be_impersonator
8+
from .requests import get_request_impersonator
59

6-
IMPERSONATE_KEY = "impersonate"
710

8-
9-
class ImpersonateStartView(View):
11+
class ImpersonateStartView(AuthViewMixin, View):
1012
def get(self):
1113
# We *could* already be impersonating, so need to consider that
12-
impersonator = getattr(self.request, "impersonator", self.request.user)
14+
impersonator = get_request_impersonator(self.request) or self.user
1315
if impersonator and can_be_impersonator(impersonator):
14-
self.request.session[IMPERSONATE_KEY] = self.url_kwargs["id"]
16+
self.session[IMPERSONATE_SESSION_KEY] = self.url_kwargs["id"]
1517
return ResponseRedirect(self.request.query_params.get("next", "/"))
1618

1719
return ResponseForbidden()
1820

1921

20-
class ImpersonateStopView(View):
22+
class ImpersonateStopView(SessionViewMixin, View):
2123
def get(self):
22-
self.request.session.pop(IMPERSONATE_KEY)
24+
self.session.pop(IMPERSONATE_SESSION_KEY)
2325
return ResponseRedirect(self.request.query_params.get("next", "/"))

plain-admin/plain/admin/templates/admin/base.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@
166166
<div class="mt-8 flex flex-col text-sm pb-3 pt-3 text-stone-400 sticky bottom-0 bg-stone-950/95 pl-3.5 pr-5">
167167
<div class="flex items-center justify-between space-x-1.5">
168168
<div class="flex items-center truncate">
169-
{% set gravatar_url = get_gravatar_url(request.user) %}
169+
{% set gravatar_url = get_gravatar_url(user) %}
170170
{% if gravatar_url %}
171171
<img
172172
src="{{ gravatar_url }}"
173-
alt="{{ request.user }}"
173+
alt="{{ user }}"
174174
class="w-5 h-5 mr-1.5 flex-shrink-0 rounded-full"
175175
/>
176176
{% else %}
@@ -180,7 +180,7 @@
180180
</svg>
181181
{% endif %}
182182
<span class="truncate">
183-
{{ request.user }}
183+
{{ user }}
184184
</span>
185185
</div>
186186
<form method="POST" action="{{ url('logout') }}" class="flex items-center flex-shrink-0 ml-2">

plain-admin/plain/admin/templates/admin/toolbar/button.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="flex items-center space-x-1">
2-
{% if request.impersonator is defined %}
2+
{% if impersonator %}
33
<div class="flex items-center font-light">
4-
Impersonating&nbsp;<span class="font-medium">{{ request.user }}</span>
4+
Impersonating&nbsp;<span class="font-medium">{{ user }}</span>
55
<a href="{{ url('admin:impersonate:stop') }}" title="Stop impersonating" class="flex items-center px-1 ml-1 text-red-300 hover:text-white">
66
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4 bi bi-x-octagon-fill" viewBox="0 0 16 16">
77
<path d="M11.46.146A.5.5 0 0 0 11.107 0H4.893a.5.5 0 0 0-.353.146L.146 4.54A.5.5 0 0 0 0 4.893v6.214a.5.5 0 0 0 .146.353l4.394 4.394a.5.5 0 0 0 .353.146h6.214a.5.5 0 0 0 .353-.146l4.394-4.394a.5.5 0 0 0 .146-.353V4.893a.5.5 0 0 0-.146-.353L11.46.146zm-6.106 4.5L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 1 1 .708-.708z"/>

plain-admin/plain/admin/toolbar.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from plain.toolbar import ToolbarItem, register_toolbar_item
22

3+
from .impersonate import get_request_impersonator
34
from .views.registry import registry
45

56

@@ -15,4 +16,5 @@ def get_template_context(self):
1516
obj = context["object"]
1617
context["object_admin_url"] = registry.get_model_detail_url(obj)
1718
context["object_class_name"] = obj.__class__.__name__
19+
context["impersonator"] = get_request_impersonator(self.request)
1820
return context

0 commit comments

Comments
 (0)