diff options
| -rw-r--r-- | Biz/PodcastItLater/Web.py | 184 |
1 files changed, 106 insertions, 78 deletions
diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py index a6eb1f6..c1698f4 100644 --- a/Biz/PodcastItLater/Web.py +++ b/Biz/PodcastItLater/Web.py @@ -616,6 +616,86 @@ def index(request: Request) -> HomePage: ) +def _handle_test_login(email: str, request: Request) -> Response: + """Handle login in test mode.""" + user = Core.Database.get_user_by_email(email) + if not user: + user_id, token = Core.Database.create_user(email) + user = { + "id": user_id, + "email": email, + "token": token, + "status": "pending", + } + + # Check if user is active + if user.get("status") != "active": + return Response( + '<div style="color: #dc3545;">' + "Your account is pending approval. " + 'Please email <a href="mailto:ben@bensima.com">' + "ben@bensima.com</a> " + 'or message <a href="https://x.com/bensima" ' + 'target="_blank">@bensima on x.com</a> ' + "to get approved.</div>", + status_code=403, + ) + + # Set session with extended lifetime + request.session["user_id"] = user["id"] + request.session["permanent"] = True + + return Response( + '<div style="color: #28a745;">✓ Logged in (dev mode)</div>', + status_code=200, + headers={"HX-Redirect": "/"}, + ) + + +def _handle_production_login(email: str) -> Response: + """Handle login in production mode.""" + pending_message = ( + '<div style="color: #ffa500;">' + "Account created, currently pending. " + 'Email <a href="mailto:ben@bensima.com">ben@bensima.com</a> ' + 'or message <a href="https://x.com/bensima" ' + 'target="_blank">@bensima</a> ' + "to get your account activated.</div>" + ) + + # Get or create user + user = Core.Database.get_user_by_email(email) + if not user: + user_id, token = Core.Database.create_user(email) + user = { + "id": user_id, + "email": email, + "token": token, + "status": "pending", + } + # For new users, show the pending message + return Response(pending_message, status_code=200) + + # Check if user is active + if user.get("status") != "active": + return Response(pending_message, status_code=200) + + # Generate magic link token + magic_token = magic_link_serializer.dumps({ + "user_id": user["id"], + "email": email, + }) + + # Send email + send_magic_link(email, magic_token) + + return Response( + f'<div style="color: #28a745;">✓ Magic link sent to {email}. ' + f"Check your email!</div>", + status_code=200, + ) + + @app.post("/login") def login(request: Request, data: FormData) -> Response: """Handle login/registration.""" @@ -632,78 +712,8 @@ def login(request: Request, data: FormData) -> Response: area = App.from_env() if area == App.Area.Test: - # Development mode: instant login - user = Core.Database.get_user_by_email(email) - if not user: - user_id, token = Core.Database.create_user( - email, - ) - user = { - "id": user_id, - "email": email, - "token": token, - "status": "pending", - } - - # Check if user is active - if user.get("status") != "active": - return Response( - '<div style="color: #dc3545;">' - "Your account is pending approval. " - 'Please email <a href="mailto:ben@bensima.com">' - "ben@bensima.com</a> " - 'or message <a href="https://x.com/bensima" ' - 'target="_blank">@bensima on x.com</a> ' - "to get approved.</div>", - status_code=403, - ) - - # Set session with extended lifetime - request.session["user_id"] = user["id"] - request.session["permanent"] = True - - return Response( - '<div style="color: #28a745;">✓ Logged in (dev mode)</div>', - status_code=200, - headers={"HX-Redirect": "/"}, - ) - - # Production mode: send magic link - # Get or create user - user = Core.Database.get_user_by_email(email) - if not user: - user_id, token = Core.Database.create_user( - email, - ) - user = {"id": user_id, "email": email, "token": token} - - # Check if user is active - if user.get("status") != "active": - return Response( - '<div style="color: #dc3545;">' - "Your account is pending approval. " - 'Please email <a href="mailto:ben@bensima.com">' - "ben@bensima.com</a> " - 'or message <a href="https://x.com/bensima" ' - 'target="_blank">@bensima on x.com</a> ' - "to get approved.</div>", - status_code=403, - ) - - # Generate magic link token - magic_token = magic_link_serializer.dumps({ - "user_id": user["id"], - "email": email, - }) - - # Send email - send_magic_link(email, magic_token) - - return Response( - f'<div style="color: #28a745;">✓ Magic link sent to {email}. ' - f"Check your email!</div>", - status_code=200, - ) + return _handle_test_login(email, request) + return _handle_production_login(email) except Exception as e: logger.exception("Login error") @@ -952,10 +962,10 @@ class TestAuthentication(BaseWebTest): response = self.client.post("/login", data={"email": "new@example.com"}) - self.assertEqual(response.status_code, 403) - self.assertIn("Your account is pending approval", response.text) + self.assertEqual(response.status_code, 200) + self.assertIn("Account created, currently pending", response.text) self.assertIn("ben@bensima.com", response.text) - self.assertIn("@bensima on x.com", response.text) + self.assertIn("@bensima", response.text) # Verify user was created with pending status user = Core.Database.get_user_by_email( @@ -983,6 +993,24 @@ class TestAuthentication(BaseWebTest): self.assertEqual(response.status_code, 200) self.assertIn("HX-Redirect", response.headers) + def test_login_existing_pending_user(self) -> None: + """Existing pending users should see the pending message.""" + # Create a pending user + _user_id, _ = Core.Database.create_user( + "pending@example.com", + ) + # User is pending by default + + response = self.client.post( + "/login", + data={"email": "pending@example.com"}, + ) + + self.assertEqual(response.status_code, 200) + self.assertIn("Account created, currently pending", response.text) + self.assertIn("ben@bensima.com", response.text) + self.assertIn("@bensima", response.text) + def test_login_disabled_user(self) -> None: """Disabled users should not be able to login.""" # Create user and set to disabled @@ -999,8 +1027,8 @@ class TestAuthentication(BaseWebTest): data={"email": "disabled@example.com"}, ) - self.assertEqual(response.status_code, 403) - self.assertIn("Your account is pending approval", response.text) + self.assertEqual(response.status_code, 200) + self.assertIn("Account created, currently pending", response.text) def test_login_invalid_email(self) -> None: """Reject malformed emails.""" @@ -1030,7 +1058,7 @@ class TestAuthentication(BaseWebTest): "/login", data={"email": "pending@example.com"}, ) - self.assertEqual(response.status_code, 403) + self.assertEqual(response.status_code, 200) # Should not have session response = self.client.get("/") |
