|
4 | 4 | from django.urls import reverse |
5 | 5 | from json import JSONDecodeError |
6 | 6 | from unittest.mock import MagicMock, patch |
| 7 | +from waffle.models import Flag |
7 | 8 | import uuid |
8 | 9 |
|
9 | 10 | from django.conf import settings |
| 11 | +from django.core.exceptions import SuspiciousOperation |
10 | 12 | from urllib.parse import quote |
11 | 13 | from django.test import Client as RequestClient, override_settings |
12 | 14 | from rest_framework.test import APITestCase, APIClient |
@@ -399,3 +401,85 @@ def test_missing_emails_just_error_out(self): |
399 | 401 | self.assertEqual('no-email', resp_data.get('type')) |
400 | 402 | test_entry = AllowListEntry.objects.filter(email=email).first() |
401 | 403 | self.assertIsNone(test_entry) |
| 404 | + |
| 405 | + |
| 406 | +class WaffleFlagsTestcase(APITestCase): |
| 407 | + def setUp(self): |
| 408 | + self.client = APIClient() |
| 409 | + self.url = reverse('api_waffle_flags') |
| 410 | + self.user = User.objects.create( |
| 411 | + oidc_id=str(uuid.uuid4()), |
| 412 | + recovery_email=f'{uuid.uuid4()}@example.com', |
| 413 | + username=f'{uuid.uuid4()}@example.org', |
| 414 | + ) |
| 415 | + |
| 416 | + Flag.objects.create(name='flag-on-for-everyone', everyone=True) |
| 417 | + Flag.objects.create(name='flag-off-for-everyone', everyone=False) |
| 418 | + Flag.objects.create(name='flag-on-for-authenticated', authenticated=True) |
| 419 | + |
| 420 | + # Due to the endpoint being gated by OIDCAuthentication |
| 421 | + patcher = patch( |
| 422 | + 'thunderbird_accounts.authentication.middleware.AccountsOIDCBackend.get_userinfo', |
| 423 | + side_effect=self._fake_userinfo, |
| 424 | + ) |
| 425 | + patcher.start() |
| 426 | + self.addCleanup(patcher.stop) |
| 427 | + |
| 428 | + @staticmethod |
| 429 | + def _fake_userinfo(access_token, id_token, payload): |
| 430 | + # Mimic a real OIDC provider, which would reject unrecognized/invalid |
| 431 | + # access tokens rather than happily returning userinfo for anything. |
| 432 | + if not User.objects.filter(oidc_id=access_token).exists(): |
| 433 | + raise SuspiciousOperation('invalid access token') |
| 434 | + |
| 435 | + return { |
| 436 | + 'sub': access_token, |
| 437 | + 'email': f'{access_token}@example.org', |
| 438 | + 'email_verified': True, |
| 439 | + 'preferred_username': f'{access_token}@example.org', |
| 440 | + } |
| 441 | + |
| 442 | + def test_returns_active_flags_for_authenticated_user(self): |
| 443 | + response = self.client.get(self.url, headers={'authorization': f'Bearer {self.user.oidc_id}'}) |
| 444 | + self.assertEqual(200, response.status_code, response.content) |
| 445 | + |
| 446 | + flags = response.json().get('flags') |
| 447 | + self.assertEqual( |
| 448 | + { |
| 449 | + 'flag-on-for-everyone', |
| 450 | + 'flag-off-for-everyone', |
| 451 | + 'flag-on-for-authenticated', |
| 452 | + }, |
| 453 | + flags.keys(), |
| 454 | + ) |
| 455 | + self.assertTrue(flags['flag-on-for-everyone']['is_active']) |
| 456 | + self.assertFalse(flags['flag-off-for-everyone']['is_active']) |
| 457 | + self.assertTrue(flags['flag-on-for-authenticated']['is_active']) |
| 458 | + |
| 459 | + def test_returns_active_flag_for_specific_user_only(self): |
| 460 | + other_user = User.objects.create( |
| 461 | + oidc_id=str(uuid.uuid4()), |
| 462 | + recovery_email=f'{uuid.uuid4()}@example.com', |
| 463 | + username=f'{uuid.uuid4()}@example.org', |
| 464 | + ) |
| 465 | + |
| 466 | + flag = Flag.objects.create(name='flag-on-for-specific-user') |
| 467 | + flag.users.add(self.user) |
| 468 | + |
| 469 | + # Authenticate as the user created in the setup step and check that the flag is active |
| 470 | + response = self.client.get(self.url, headers={'authorization': f'Bearer {self.user.oidc_id}'}) |
| 471 | + self.assertEqual(200, response.status_code, response.content) |
| 472 | + self.assertTrue(response.json()['flags']['flag-on-for-specific-user']['is_active']) |
| 473 | + |
| 474 | + # Authenticate as the other user and check that the flag is not active |
| 475 | + response = self.client.get(self.url, headers={'authorization': f'Bearer {other_user.oidc_id}'}) |
| 476 | + self.assertEqual(200, response.status_code, response.content) |
| 477 | + self.assertFalse(response.json()['flags']['flag-on-for-specific-user']['is_active']) |
| 478 | + |
| 479 | + def test_requires_authentication(self): |
| 480 | + response = self.client.get(self.url) |
| 481 | + self.assertEqual(401, response.status_code) |
| 482 | + |
| 483 | + def test_returns_401_for_invalid_token(self): |
| 484 | + response = self.client.get(self.url, headers={'authorization': 'Bearer invalid-token'}) |
| 485 | + self.assertEqual(401, response.status_code) |
0 commit comments