import uuid from allauth.account.models import EmailAddress from django.contrib.auth import get_user, get_user_model from django.core import mail from django.core.cache import cache from django.test import Client, TestCase, override_settings from apps.billing.models import PointsLedger from apps.users.models import UserWallet @override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend") class PortalAccountFlowTests(TestCase): password = "Strong-pass-123" def setUp(self): cache.clear() def create_verified_user(self): suffix = uuid.uuid4().hex[:8] user = get_user_model().objects.create_user( username=f"portal-user-{suffix}", email=f"portal-user-{suffix}@example.com", password=self.password, ) EmailAddress.objects.create( user=user, email=user.email, verified=True, primary=True, ) return user def test_signup_creates_unverified_user_wallet_with_zero_points_and_no_ledger(self): suffix = uuid.uuid4().hex[:8] email = f"signup-{suffix}@example.com" response = self.client.post( "/signup", { "username": f"signup-{suffix}", "email": email, "password1": self.password, "password2": self.password, }, ) self.assertEqual(response.status_code, 302) user = get_user_model().objects.get(email=email) email_address = EmailAddress.objects.get(user=user, email=email) wallet = UserWallet.objects.get(user=user) self.assertFalse(email_address.verified) self.assertTrue(email_address.primary) self.assertEqual(wallet.points_balance, 0) self.assertFalse(PointsLedger.objects.filter(user=user).exists()) self.assertEqual(len(mail.outbox), 1) def test_unverified_email_cannot_establish_login_session(self): suffix = uuid.uuid4().hex[:8] user = get_user_model().objects.create_user( username=f"unverified-{suffix}", email=f"unverified-{suffix}@example.com", password=self.password, ) EmailAddress.objects.create( user=user, email=user.email, verified=False, primary=True, ) self.client.post("/login", {"login": user.email, "password": self.password}) self.assertFalse(get_user(self.client).is_authenticated) def test_verified_user_can_login_view_dashboard_and_logout(self): user = self.create_verified_user() UserWallet.objects.create(user=user, points_balance=42) login_response = self.client.post( "/login", {"login": user.email, "password": self.password}, ) self.assertEqual(login_response.status_code, 302) self.assertEqual(login_response["Location"], "/dashboard") self.assertTrue(get_user(self.client).is_authenticated) dashboard_response = self.client.get("/dashboard") self.assertEqual(dashboard_response.status_code, 200) self.assertContains(dashboard_response, user.email) self.assertContains(dashboard_response, "42") logout_response = self.client.post("/logout") self.assertEqual(logout_response.status_code, 302) self.assertEqual(logout_response["Location"], "/login") self.assertFalse(get_user(self.client).is_authenticated) def test_dashboard_requires_session_login(self): response = self.client.get("/dashboard") self.assertEqual(response.status_code, 302) self.assertTrue(response["Location"].startswith("/login?next=")) def test_login_post_is_csrf_protected(self): csrf_client = Client(enforce_csrf_checks=True) response = csrf_client.post( "/login", {"login": "nobody@example.com", "password": "password"}, ) self.assertEqual(response.status_code, 403)