Skip to content

Commit 8fe8d74

Browse files
committed
handle join mechanism with cookie
1 parent ecb1938 commit 8fe8d74

File tree

2 files changed

+59
-43
lines changed

2 files changed

+59
-43
lines changed

src/backend/main.py

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,21 @@ async def lifespan(app: FastAPI):
7676
app.mount("/assets", StaticFiles(directory=ASSETS_DIR), name="assets")
7777
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
7878

79-
async def serve_index_html(request: Request = None):
79+
async def serve_index_html(request: Request = None, response: Response = None, pad_id: Optional[UUID] = None):
8080
"""
8181
Helper function to serve the index.html file or proxy to dev server based on PAD_DEV_MODE.
82+
Optionally sets a pending_pad_id cookie if pad_id is provided.
8283
"""
84+
# Set cookie if pad_id is provided
85+
if pad_id is not None and response is not None:
86+
response.set_cookie(
87+
key="pending_pad_id",
88+
value=str(pad_id),
89+
httponly=True,
90+
secure=True,
91+
samesite="lax"
92+
)
93+
8394
if PAD_DEV_MODE:
8495
try:
8596
# Proxy the request to the development server's root URL
@@ -89,72 +100,46 @@ async def serve_index_html(request: Request = None):
89100
url = f"{DEV_FRONTEND_URL}{request.url.path}"
90101

91102
async with httpx.AsyncClient() as client:
92-
response = await client.get(url)
93-
return Response(
94-
content=response.content,
95-
status_code=response.status_code,
96-
media_type=response.headers.get("content-type")
97-
)
103+
proxy_response = await client.get(url)
104+
response.body = proxy_response.content
105+
response.status_code = proxy_response.status_code
106+
response.media_type = proxy_response.headers.get("content-type")
107+
return response
98108
except Exception as e:
99109
error_message = f"Error proxying to dev server: {e}"
100110
print(error_message)
101-
return Response(
102-
status_code=500,
103-
)
111+
response.status_code = 500
112+
return response
104113
else:
105114
# For production, serve the static build
106-
return FileResponse(os.path.join(STATIC_DIR, "index.html"))
115+
return FileResponse(os.path.join(STATIC_DIR, "index.html"), background=response)
107116

108117
@app.get("/pad/{pad_id}")
109118
async def read_pad(
110119
pad_id: UUID,
111120
request: Request,
121+
response: Response,
112122
user: Optional[UserSession] = Depends(optional_auth),
113123
session: AsyncSession = Depends(get_session)
114124
):
115125
if not user:
116-
print("No user found")
117-
return await serve_index_html(request)
126+
return await serve_index_html(request, response, pad_id)
118127

119128
try:
120129
pad = await Pad.get_by_id(session, pad_id)
121130
if not pad:
122131
print("No pad found")
123-
return await serve_index_html(request)
132+
return await serve_index_html(request, response)
124133

125-
# Check access permissions
126134
if not pad.can_access(user.id):
127135
print("No access to pad")
128-
return await serve_index_html(request)
129-
130-
# Worker assignment is now handled automatically in Pad.get_by_id()
131-
print(f"Pad {pad_id} accessed by user {user.id}, worker: {pad.worker_id[:8] if pad.worker_id else 'None'}")
136+
return await serve_index_html(request, response)
132137

133-
# Add pad to user's open pads if not already there and update last selected pad
134-
user_obj = await User.get_by_id(session, user.id)
135-
if user_obj:
136-
# Convert all UUIDs to strings for comparison
137-
open_pads_str = [str(pid) for pid in user_obj._store.open_pads]
138-
if str(pad_id) not in open_pads_str:
139-
# Convert back to UUIDs for storage
140-
user_obj._store.open_pads = [UUID(pid) for pid in open_pads_str] + [pad_id]
141-
try:
142-
await user_obj.save(session)
143-
except Exception as e:
144-
print(f"Error updating user's open pads: {e}")
145-
# Continue even if update fails - don't block pad access
146-
147-
# Update last selected pad
148-
try:
149-
await user_obj.set_last_selected_pad(session, pad_id)
150-
except Exception as e:
151-
print(f"Error updating last selected pad: {e}")
152-
# Continue even if update fails - don't block pad access
153-
154-
return await serve_index_html(request)
138+
# Just serve the page if user has access
139+
return await serve_index_html(request, response, pad_id)
155140
except Exception as e:
156141
print(f"Error in read_pad endpoint: {e}")
157-
return await serve_index_html(request)
142+
return await serve_index_html(request, response, pad_id)
158143

159144
@app.get("/")
160145
async def read_root(request: Request, auth: Optional[UserSession] = Depends(optional_auth)):

src/backend/routers/users_router.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@
44

55
import posthog
66
import jwt
7-
from fastapi import APIRouter, Depends, HTTPException
7+
from fastapi import APIRouter, Depends, HTTPException, Request, Response
88
from sqlalchemy.ext.asyncio import AsyncSession
99

1010
from cache import RedisClient
1111
from config import get_jwks_client, OIDC_CLIENT_ID, FRONTEND_URL
1212
from dependencies import UserSession, require_admin, require_auth
1313
from database.database import get_session
1414
from domain.user import User
15+
from domain.pad import Pad
1516

1617
users_router = APIRouter()
1718

1819

1920
@users_router.get("/me")
2021
async def get_user_info(
22+
request: Request,
23+
response: Response,
2124
user: UserSession = Depends(require_auth),
2225
session: AsyncSession = Depends(get_session),
2326
):
@@ -26,6 +29,34 @@ async def get_user_info(
2629
# Get the user from database to access last_selected_pad
2730
user_obj = await User.get_by_id(session, user.id)
2831

32+
# Check for pending pad cookie
33+
pending_pad_id = request.cookies.get("pending_pad_id")
34+
if pending_pad_id:
35+
try:
36+
pad_id = UUID(pending_pad_id)
37+
pad = await Pad.get_by_id(session, pad_id)
38+
39+
if pad and pad.can_access(user.id):
40+
# Convert all UUIDs to strings for comparison
41+
open_pads_str = [str(pid) for pid in user_obj._store.open_pads]
42+
if str(pad_id) not in open_pads_str:
43+
user_obj._store.open_pads = [UUID(pid) for pid in open_pads_str] + [pad_id]
44+
await user_obj.save(session)
45+
46+
# Update last selected pad
47+
await user_obj.set_last_selected_pad(session, pad_id)
48+
49+
except (ValueError, Exception) as e:
50+
print(f"Error processing pending pad: {e}")
51+
finally:
52+
# Always clear the cookie with same settings as when setting it
53+
response.delete_cookie(
54+
key="pending_pad_id",
55+
secure=True,
56+
httponly=False,
57+
samesite="lax"
58+
)
59+
2960
# Create token data dictionary from UserSession properties
3061
token_data = {
3162
"id": user.id,

0 commit comments

Comments
 (0)