From 304f3ad56f3df8ae9dd35847fc8d21ea501fe3f8 Mon Sep 17 00:00:00 2001 From: gilesb Date: Fri, 9 Jan 2026 16:52:32 +0000 Subject: [PATCH] Remove login links from L1 - L1 doesn't know where L2 is L1 can't redirect users to login because it doesn't know which L2 server they use. Users must log in directly at their L2 server, and the shared cookie will authenticate them on L1. - Replace "Log in" links with "Not logged in" text - Remove /login and /register routes - Keep /logout to just clear cookie and redirect home - Remove unused DEFAULT_L2_SERVER config Co-Authored-By: Claude Opus 4.5 --- server.py | 56 +++++++++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/server.py b/server.py index 69797c8..850641e 100644 --- a/server.py +++ b/server.py @@ -66,9 +66,6 @@ def compute_run_id(input_hashes: list[str], recipe: str, recipe_hash: str = None json_str = json.dumps(data, sort_keys=True, separators=(",", ":")) return hashlib.sha3_256(json_str.encode()).hexdigest() -# Default L2 for login redirect when not logged in (user can login to any L2) -DEFAULT_L2_SERVER = os.environ.get("DEFAULT_L2_SERVER", "http://localhost:8200") - # IPFS gateway URL for public access to IPFS content IPFS_GATEWAY_URL = os.environ.get("IPFS_GATEWAY_URL", "") @@ -526,7 +523,7 @@ def render_home_html(actor_id: Optional[str] = None) -> str: Logged in as {actor_id} ''' else: - user_section = '''Login via L2''' + user_section = '''Not logged in''' return f""" @@ -967,7 +964,7 @@ async def run_detail(run_id: str, request: Request): if wants_html(request): ctx = await get_user_context_from_cookie(request) if not ctx: - content = '

Login via L2 to view run details.

' + content = '

Not logged in.

' return HTMLResponse(render_page("Login Required", content, None, active_tab="runs"), status_code=401) # Check user owns this run @@ -1219,7 +1216,7 @@ async def list_runs(request: Request, page: int = 1, limit: int = 20): if wants_html(request): if not ctx: - content = '

Login via L2 to see your runs.

' + content = '

Not logged in.

' return HTMLResponse(render_page("Runs", content, None, active_tab="runs")) if not runs_page: @@ -1402,7 +1399,7 @@ async def list_recipes_api(request: Request, page: int = 1, limit: int = 20): if not ctx: return HTMLResponse(render_page( "Recipes", - '

Login via L2 to see recipes.

', + '

Not logged in.

', None, active_tab="recipes" )) @@ -1895,7 +1892,7 @@ async def ui_recipes_list(request: Request): ctx = await get_user_context_from_cookie(request) if not ctx: - return '

Login via L2 to see recipes.

' + return '

Not logged in.

' all_recipes = list_all_recipes() @@ -2019,7 +2016,7 @@ async def get_cached(content_hash: str, request: Request): # Raw data is only served from /cache/{hash}/raw endpoint if True: # Always show HTML page, raw data via /raw endpoint if not ctx: - content = '

Login via L2 to view cached content.

' + content = '

Not logged in.

' return HTMLResponse(render_page("Login Required", content, None, active_tab="media"), status_code=401) # Check user has access @@ -2661,7 +2658,7 @@ async def list_media( if wants_html(request): # Require login for HTML media view if not ctx: - content = '

Login via L2 to see media.

' + content = '

Not logged in.

' return HTMLResponse(render_page("Media", content, None, active_tab="media")) # Get hashes owned by/associated with this user @@ -3727,8 +3724,8 @@ def render_page(title: str, content: str, actor_id: Optional[str] = None, active ''' else: user_info = ''' -
- Login via L2 +
+ Not logged in
''' @@ -3789,8 +3786,8 @@ def render_ui_html(actor_id: Optional[str] = None, tab: str = "runs") -> str: ''' else: user_info = ''' -
- Login via L2 +
+ Not logged in
''' @@ -3841,32 +3838,13 @@ def render_ui_html(actor_id: Optional[str] = None, tab: str = "runs") -> str: """ -# Auth routes - L1 never handles credentials, redirects to L2 -# L2 sets auth_token cookie with domain=.rose-ash.com for shared auth - -L1_PUBLIC_URL = os.environ.get("L1_PUBLIC_URL", "http://localhost:8100") - - -@app.get("/login") -async def login_page(): - """Redirect to L2 server for login. L1 never handles credentials.""" - # Redirect to default L2 with return URL so L2 can redirect back after login - return_url = f"{L1_PUBLIC_URL}/runs" - return RedirectResponse(url=f"{DEFAULT_L2_SERVER}/login?return_to={return_url}", status_code=302) - - -@app.get("/register") -async def register_page(): - """Redirect to L2 server for registration. L1 never handles credentials.""" - return_url = f"{L1_PUBLIC_URL}/runs" - return RedirectResponse(url=f"{DEFAULT_L2_SERVER}/register?return_to={return_url}", status_code=302) - +# Auth - L1 doesn't handle login (user logs in at their L2 server) +# Shared cookie authenticates across L1 and L2 @app.get("/logout") async def logout(): - """Logout - clear cookie and redirect to L2 logout.""" - # Clear local cookie and redirect to L2 to clear shared cookie - response = RedirectResponse(url=f"{DEFAULT_L2_SERVER}/logout?return_to={L1_PUBLIC_URL}/", status_code=302) + """Logout - clear local cookie and redirect to home.""" + response = RedirectResponse(url="/", status_code=302) response.delete_cookie("auth_token") return response @@ -3965,7 +3943,7 @@ async def ui_runs(request: Request): # Require login to see runs if not ctx: - return '

Login via L2 to see your runs.

' + return '

Not logged in.

' # Filter runs by user - match both plain username and ActivityPub format (@user@domain) runs = [r for r in runs if r.username in (ctx.username, ctx.actor_id)] @@ -4064,7 +4042,7 @@ async def ui_media_list( # Require login to see media if not ctx: - return '

Login via L2 to see media.

' + return '

Not logged in.

' # Get hashes owned by/associated with this user user_hashes = await get_user_cache_hashes(ctx.username, ctx.actor_id)