from django.contrib.auth import get_user_model from django.test import Client, TestCase from django.utils import timezone from workflows.models import UserProfile from workflows.totp import generate_totp_token class AccountUISmokeTests(TestCase): def setUp(self): self.user = get_user_model().objects.create_user( username='profile-user', email='profile@example.com', password='secret-12345', first_name='Profile', last_name='User', ) self.client = Client() self.client.force_login(self.user) def test_account_profile_page_renders(self): response = self.client.get('/account/', HTTP_HOST='localhost') self.assertEqual(response.status_code, 200) self.assertContains(response, 'profile@example.com') self.assertContains(response, 'Passwort ändern') def test_password_change_page_renders(self): response = self.client.get('/accounts/password_change/', HTTP_HOST='localhost') self.assertEqual(response.status_code, 200) self.assertContains(response, 'Aktuelles Passwort') def test_user_profile_is_created_automatically(self): self.assertTrue(UserProfile.objects.filter(user=self.user).exists()) def test_account_profile_details_can_be_updated(self): response = self.client.post( '/account/', { 'account_form': 'details', 'first_name': 'Updated', 'last_name': 'User', 'email': 'updated@example.com', 'phone_number': '030 123456', 'mobile_number': '0176 123456', 'job_title': 'IT Manager', 'department': 'IT', 'location': 'Berlin', 'contact_notes': 'Available in the mornings', }, HTTP_HOST='localhost', follow=True, ) self.assertEqual(response.status_code, 200) self.user.refresh_from_db() profile = self.user.profile self.assertEqual(self.user.first_name, 'Updated') self.assertEqual(self.user.email, 'updated@example.com') self.assertEqual(profile.phone_number, '030 123456') self.assertEqual(profile.job_title, 'IT Manager') def test_totp_can_be_enabled_from_account(self): response = self.client.post( '/account/', { 'account_form': 'totp_enable', 'current_password': 'secret-12345', 'verification_code': '000000', }, HTTP_HOST='localhost', follow=True, ) self.assertEqual(response.status_code, 200) self.user.refresh_from_db() profile = self.user.profile pending_secret = self.client.session.get('account_totp_pending_secret') self.assertTrue(pending_secret) valid_code = generate_totp_token(pending_secret, int(timezone.now().timestamp())) response = self.client.post( '/account/', { 'account_form': 'totp_enable', 'current_password': 'secret-12345', 'verification_code': valid_code, }, HTTP_HOST='localhost', follow=True, ) self.assertEqual(response.status_code, 200) profile.refresh_from_db() self.assertTrue(profile.totp_enabled) self.assertTrue(profile.totp_secret) self.assertEqual(len(profile.totp_recovery_codes), 8) self.assertContains(response, 'Recovery-Codes') def test_login_requires_totp_when_enabled(self): profile = self.user.profile profile.totp_secret = 'JBSWY3DPEHPK3PXP' profile.totp_enabled = True profile.set_recovery_codes(['ABCDE-12345']) profile.save(update_fields=['totp_secret', 'totp_enabled', 'totp_recovery_codes', 'updated_at']) client = Client() response = client.post( '/accounts/login/', {'username': 'profile-user', 'password': 'secret-12345'}, HTTP_HOST='localhost', ) self.assertEqual(response.status_code, 200) self.assertContains(response, 'TOTP-Code') token = generate_totp_token(profile.totp_secret, int(timezone.now().timestamp())) response = client.post( '/accounts/login/', {'username': 'profile-user', 'password': 'secret-12345', 'otp_code': token}, HTTP_HOST='localhost', ) self.assertEqual(response.status_code, 302) client = Client() response = client.post( '/accounts/login/', {'username': 'profile-user', 'password': 'secret-12345', 'recovery_code': 'ABCDE-12345'}, HTTP_HOST='localhost', ) self.assertEqual(response.status_code, 302) profile.refresh_from_db() self.assertEqual(profile.totp_recovery_codes, [])