|
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