fix: admin logout clears only admin tokens + add signup token tests
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -284,8 +284,10 @@ document.addEventListener('alpine:init', () => {
|
|||||||
console.error('Logout API error (continuing anyway):', error);
|
console.error('Logout API error (continuing anyway):', error);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
// Clear all tokens
|
// Clear admin tokens only (not vendor or customer tokens)
|
||||||
localStorage.clear();
|
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';
|
window.location.href = '/admin/login';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,6 +463,128 @@ class TestCompleteSignupAPI:
|
|||||||
assert "redirect_url" in data
|
assert "redirect_url" in data
|
||||||
assert "trial_ends_at" 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):
|
def test_complete_signup_invalid_session(self, client, mock_stripe_service):
|
||||||
"""Test completing signup with invalid session."""
|
"""Test completing signup with invalid session."""
|
||||||
response = client.post(
|
response = client.post(
|
||||||
|
|||||||
Reference in New Issue
Block a user