From 81e5cb41d621cc75215eaf46846ffb9ebc6c4e7b Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Sun, 28 Dec 2025 18:18:23 +0100 Subject: [PATCH] fix: admin logout clears only admin tokens + add signup token tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix admin header.html logout to not use localStorage.clear() which was clearing vendor/customer tokens too - Add tests for signup access_token generation - Test that token is returned in response - Test that token can authenticate API calls - Test that vendor_token cookie is set 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- app/templates/admin/partials/header.html | 6 +- .../api/v1/platform/test_signup.py | 122 ++++++++++++++++++ 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/app/templates/admin/partials/header.html b/app/templates/admin/partials/header.html index 9ce8f1a8..95779832 100644 --- a/app/templates/admin/partials/header.html +++ b/app/templates/admin/partials/header.html @@ -284,8 +284,10 @@ document.addEventListener('alpine:init', () => { console.error('Logout API error (continuing anyway):', error); }) .finally(() => { - // Clear all tokens - localStorage.clear(); + // Clear admin tokens only (not vendor or customer tokens) + localStorage.removeItem('admin_token'); + localStorage.removeItem('admin_user'); + // Note: Do NOT use localStorage.clear() - it would clear vendor/customer tokens too window.location.href = '/admin/login'; }); } diff --git a/tests/integration/api/v1/platform/test_signup.py b/tests/integration/api/v1/platform/test_signup.py index b5a2e9e6..1b38a609 100644 --- a/tests/integration/api/v1/platform/test_signup.py +++ b/tests/integration/api/v1/platform/test_signup.py @@ -463,6 +463,128 @@ class TestCompleteSignupAPI: assert "redirect_url" in data assert "trial_ends_at" in data + def test_complete_signup_returns_access_token( + self, client, signup_session, mock_stripe_service, db + ): + """Test that completing signup returns a valid JWT access token for auto-login.""" + # Create account + client.post( + "/api/v1/platform/signup/create-account", + json={ + "session_id": signup_session, + "email": "token_test@example.com", + "password": "SecurePass123!", + "first_name": "Token", + "last_name": "Test", + "company_name": "Token Test Co", + }, + ) + + # Setup payment + client.post( + "/api/v1/platform/signup/setup-payment", + json={"session_id": signup_session}, + ) + + # Complete signup + response = client.post( + "/api/v1/platform/signup/complete", + json={ + "session_id": signup_session, + "setup_intent_id": "seti_test_123", + }, + ) + + assert response.status_code == 200 + data = response.json() + + # Verify access_token is returned + assert "access_token" in data + assert data["access_token"] is not None + assert len(data["access_token"]) > 50 # JWT tokens are long + + def test_complete_signup_token_can_authenticate( + self, client, signup_session, mock_stripe_service, db + ): + """Test that the returned access token can be used to authenticate API calls.""" + # Create account + client.post( + "/api/v1/platform/signup/create-account", + json={ + "session_id": signup_session, + "email": "auth_test@example.com", + "password": "SecurePass123!", + "first_name": "Auth", + "last_name": "Test", + "company_name": "Auth Test Co", + }, + ) + + # Setup payment + client.post( + "/api/v1/platform/signup/setup-payment", + json={"session_id": signup_session}, + ) + + # Complete signup + complete_response = client.post( + "/api/v1/platform/signup/complete", + json={ + "session_id": signup_session, + "setup_intent_id": "seti_test_123", + }, + ) + + assert complete_response.status_code == 200 + access_token = complete_response.json()["access_token"] + + # Use the token to access a protected vendor endpoint + auth_response = client.get( + "/api/v1/vendor/onboarding/status", + headers={"Authorization": f"Bearer {access_token}"}, + ) + + # Should be able to access the onboarding endpoint + assert auth_response.status_code == 200 + + def test_complete_signup_sets_vendor_token_cookie( + self, client, signup_session, mock_stripe_service, db + ): + """Test that completing signup sets the vendor_token HTTP-only cookie.""" + # Create account + client.post( + "/api/v1/platform/signup/create-account", + json={ + "session_id": signup_session, + "email": "cookie_test@example.com", + "password": "SecurePass123!", + "first_name": "Cookie", + "last_name": "Test", + "company_name": "Cookie Test Co", + }, + ) + + # Setup payment + client.post( + "/api/v1/platform/signup/setup-payment", + json={"session_id": signup_session}, + ) + + # Complete signup + response = client.post( + "/api/v1/platform/signup/complete", + json={ + "session_id": signup_session, + "setup_intent_id": "seti_test_123", + }, + ) + + assert response.status_code == 200 + + # Check that vendor_token cookie is set + cookies = response.cookies + assert "vendor_token" in cookies + def test_complete_signup_invalid_session(self, client, mock_stripe_service): """Test completing signup with invalid session.""" response = client.post(