|
1 | 1 | import os |
2 | 2 | from urllib.parse import parse_qs |
3 | 3 |
|
4 | | -from django.contrib.auth.models import AnonymousUser |
5 | 4 | from django.core.exceptions import SuspiciousOperation |
6 | 5 | from django.http import FileResponse, HttpRequest, HttpResponse, HttpResponseNotFound |
7 | 6 | from reactpy.config import REACTPY_WEB_MODULES_DIR |
@@ -48,35 +47,38 @@ async def view_to_iframe(request: HttpRequest, dotted_path: str) -> HttpResponse |
48 | 47 | async def switch_session(request: HttpRequest, uuid: str) -> HttpResponse: |
49 | 48 | """Switches the client's active session. |
50 | 49 |
|
51 | | - Django's authentication design requires HTTP cookies to persist login via cookies. |
| 50 | + This view exists because ReactPy is rendered via WebSockets, and browsers do not |
| 51 | + allow active WebSocket connections to modify HTTP cookies. Django's authentication |
| 52 | + design requires HTTP cookies to persist state changes. |
| 53 | + """ |
| 54 | + from reactpy_django.models import SwitchSession |
52 | 55 |
|
53 | | - This is problematic since ReactPy is rendered via WebSockets, and browsers do not |
54 | | - allow active WebSocket connections to modify HTTP cookies, which necessitates this |
55 | | - view to exist.""" |
56 | | - from reactpy_django.models import AuthSession |
| 56 | + # Find out what session the client wants to switch |
| 57 | + data = await SwitchSession.objects.aget(uuid=uuid) |
57 | 58 |
|
58 | | - # TODO: Maybe just relogin the user instead of switching sessions? |
59 | | - |
60 | | - # Find out what session we're switching to |
61 | | - auth_session = await AuthSession.objects.aget(uuid=uuid) |
62 | | - |
63 | | - # Validate the session |
64 | | - if auth_session.expired: |
| 59 | + # CHECK: Session has expired? |
| 60 | + if data.expired: |
65 | 61 | msg = "Session expired." |
| 62 | + await data.adelete() |
66 | 63 | raise SuspiciousOperation(msg) |
67 | | - if not request.session.exists(auth_session.session_key): |
68 | | - msg = "Session does not exist." |
| 64 | + |
| 65 | + # CHECK: Session does not exist? |
| 66 | + exists_method = getattr(request.session, "aexists", request.session.exists) |
| 67 | + if not await ensure_async(exists_method)(data.session_key): |
| 68 | + msg = "Attempting to switch to a session that does not exist." |
69 | 69 | raise SuspiciousOperation(msg) |
70 | 70 |
|
71 | | - # Delete the existing session |
72 | | - flush_method = getattr(request.session, "aflush", request.session.flush) |
73 | | - await ensure_async(flush_method)() |
74 | | - request.user = AnonymousUser() |
| 71 | + # CHECK: Client already using the correct session? |
| 72 | + if request.session.session_key == data.session_key: |
| 73 | + await data.adelete() |
| 74 | + return HttpResponse(status=204) |
75 | 75 |
|
76 | 76 | # Switch the client's session |
77 | | - request.session = type(request.session)(auth_session.session_key) |
| 77 | + request.session = type(request.session)(session_key=data.session_key) |
78 | 78 | load_method = getattr(request.session, "aload", request.session.load) |
79 | 79 | await ensure_async(load_method)() |
80 | | - await auth_session.adelete() |
81 | | - |
| 80 | + request.session.modified = True |
| 81 | + save_method = getattr(request.session, "asave", request.session.save) |
| 82 | + await ensure_async(save_method)() |
| 83 | + await data.adelete() |
82 | 84 | return HttpResponse(status=204) |
0 commit comments