class DirectoryEntryAuthTest(TestCase): def setUp(self): User = get_user_model() self.client = Client() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password, is_active=True) self.user.save() # Create a verified email address object for this user via allauth EmailAddress.objects.create(user=self.user, email=self.email, verified=True) # Setup pages. Site is needed for valid urls. site = Site.objects.get() directory = DirectoryPageFactory(parent=site.root_page) self.unowned_sd_page = DirectoryEntryFactory(live=True, parent=directory) self.unowned_sd_page.save() self.user_owned_sd_page = DirectoryEntryFactory(live=True, parent=directory) self.user_owned_sd_page.save() SecuredropOwner(owner=self.user, page=self.user_owned_sd_page).save() def test_logged_in_user_should_see_edit_on_owned_pages(self): # Login self.client.post(reverse_lazy('account_login'), {'login': self.email, 'password': self.password}) response = self.client.get(self.user_owned_sd_page.url) self.assertTrue(response.context['page'].editable) def test_logged_out_user_should_not_see_edit(self): response = self.client.get(self.user_owned_sd_page.url) self.assertFalse(response.context['page'].editable) def test_logged_in_user_should_not_see_edit_on_unowned_pages(self): self.client.post(reverse_lazy('account_login'), {'login': self.email, 'password': self.password}) response = self.client.get(self.unowned_sd_page.url) self.assertFalse(response.context['page'].editable)
class DirectoryLanguageFilterTest(TestCase): def setUp(self): self.directory = DirectoryPageFactory() # set up languages spanish = LanguageFactory(title='Spanish') chinese = LanguageFactory(title='Chinese') spanish.save() chinese.save() # set up instances that are children of the directory and have those languages self.spanish_instance = DirectoryEntryFactory(parent=self.directory) self.spanish_instance.languages.add(spanish) self.spanish_instance.save() self.chinese_instance = DirectoryEntryFactory(parent=self.directory) self.chinese_instance.languages.add(chinese) self.chinese_instance.save() self.lang_filter = {'languages': spanish} def test_language_filtered_for_is_in_queryset(self): filtered_instances = self.directory.get_instances( filters=self.lang_filter) self.assertIn(self.spanish_instance, filtered_instances) def test_langauge_not_filtered_for_is_not_in_queryset(self): filtered_instances = self.directory.get_instances( filters=self.lang_filter) self.assertNotIn(self.chinese_instance, filtered_instances)
def test_securedrop_can_save_expected_urls(self): securedrop = DirectoryEntryFactory( landing_page_url='https://www.something.org', onion_address='https://notreal.onion', ) securedrop.save() self.assertIn(securedrop, DirectoryEntry.objects.all())
class DirectoryCountryFilterTest(TestCase): def setUp(self): self.directory = DirectoryPageFactory() # set up countries mexico = CountryFactory(title='Mexico') azerbaijan = CountryFactory(title='Azerbaijan') mexico.save() azerbaijan.save() # set up instances that are children of the directory and have those countries self.mexico_instance = DirectoryEntryFactory(parent=self.directory) self.mexico_instance.countries.add(mexico) self.mexico_instance.save() self.azerbaijan_instance = DirectoryEntryFactory(parent=self.directory) self.azerbaijan_instance.countries.add(azerbaijan) self.azerbaijan_instance.save() self.country_filter = {'countries': mexico} def test_country_filtered_for_is_in_queryset(self): filtered_instances = self.directory.get_instances( filters=self.country_filter) self.assertIn(self.mexico_instance, filtered_instances) def test_country_not_filtered_for_is_not_in_queryset(self): filtered_instances = self.directory.get_instances( filters=self.country_filter) self.assertNotIn(self.azerbaijan_instance, filtered_instances)
class DirectoryTopicFilterTest(TestCase): def setUp(self): self.directory = DirectoryPageFactory() # set up topics pf = TopicFactory(title='Press Freedom') irs = TopicFactory(title='IRS') pf.save() irs.save() # set up instances that are children of the directory and have those topics self.pf_instance = DirectoryEntryFactory(parent=self.directory) self.pf_instance.topics.add(pf) self.pf_instance.save() self.irs_instance = DirectoryEntryFactory(parent=self.directory) self.irs_instance.topics.add(irs) self.irs_instance.save() self.topic_filter = {'topics': pf} def test_topic_filtered_for_is_in_queryset(self): filtered_instances = self.directory.get_instances( filters=self.topic_filter) self.assertIn(self.pf_instance, filtered_instances) def test_topic_not_filtered_for_is_not_in_queryset(self): filtered_instances = self.directory.get_instances( filters=self.topic_filter) self.assertNotIn(self.irs_instance, filtered_instances)
class DirectorySevereWarningTest(TestCase): def setUp(self): site = Site.objects.get() self.entry = DirectoryEntryFactory(parent=DirectoryPageFactory( parent=site.root_page)) self.result = ScanResultFactory( securedrop=self.entry, landing_page_url=self.entry.landing_page_url, severe_warning=True, ) self.result.save() self.entry.save() self.client = Client() def test_warning_presence(self): """warning should be displayed if warnings flag in request""" response = self.client.get(self.entry.url) self.assertContains( response, 'We strongly advise you to only visit this landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>, with the <a href="https://tb-manual.torproject.org/en-US/security-slider.html">security slider</a> set to "safest".', status_code=200, ) def test_warning_message_suppressed_if_page_ignores_all_triggered_warnings( self): self.entry.warnings_ignored = ['no_third_party_assets'] self.entry.save() self.entry.refresh_from_db() response = self.client.get(self.entry.url) self.assertNotContains( response, 'We strongly advise you to only visit this landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>, with the <a href="https://tb-manual.torproject.org/en-US/security-slider.html">security slider</a> set to "safest".', status_code=200, )
def handle(self, *args, **options): number_of_instances = options['number_of_instances'] home_page = HomePage.objects.get(slug='home') directory = DirectoryPage.objects.first() if not directory: directory = DirectoryPageFactory(parent=home_page, title="Directory") directory.save() for i in range(number_of_instances): instance = DirectoryEntryFactory(parent=directory) if i % 3 == 0: scan = ScanResultFactory( securedrop=instance, landing_page_url=instance.landing_page_url, no_failures=True, ) elif i % 3 == 1: scan = ScanResultFactory( securedrop=instance, landing_page_url=instance.landing_page_url, severe_warning=True, ) else: scan = ScanResultFactory( securedrop=instance, landing_page_url=instance.landing_page_url, moderate_warning=True, ) scan.save() instance.save()
def test_save_associates_results(self): landing_page_url = 'https://www.something.org' result = ScanResult( live=True, hsts=True, hsts_max_age=True, securedrop=None, landing_page_url=landing_page_url, ) result.save() securedrop = DirectoryEntryFactory( landing_page_url=landing_page_url, onion_address='https://notreal.onion', ) securedrop.save() result.refresh_from_db() self.assertEqual(result.securedrop, securedrop)
class DirectoryNoWarningTest(TestCase): def setUp(self): site = Site.objects.get() self.entry = DirectoryEntryFactory(parent=DirectoryPageFactory( parent=site.root_page)) self.result = ScanResultFactory( securedrop=self.entry, landing_page_url=self.entry.landing_page_url, no_failures=True, ) self.result.save() self.entry.save() self.client = Client() def test_page_request_should_succeed_if_no_warnings_on_result(self): response = self.client.get(self.entry.url) self.assertEqual(response.status_code, 200)
class AuthenticatedTest(TestCase): @classmethod def setUpTestData(self): turn_on_instance_management() def setUp(self): User = get_user_model() self.client = Client() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password, is_active=True) self.user.save() # Create a verified email address object for this user via allauth EmailAddress.objects.create(user=self.user, email=self.email, verified=True) self.unowned_sd_page = DirectoryEntryFactory() self.unowned_sd_page.save() self.user_owned_sd_page = DirectoryEntryFactory() self.user_owned_sd_page.save() SecuredropOwner(owner=self.user, page=self.user_owned_sd_page).save() # Login self.client.post(reverse('account_login'), {'login': self.email, 'password': self.password}) def test_authenticated_login_should_redirect_to_2fa_setup(self): """login without setting up a device should redirect to 2FA setup page""" response = self.client.post( reverse('account_login'), {'login': self.email, 'password': self.password}, ) self.assertEqual(response.status_code, 302) self.assertEqual(response.url, reverse('two-factor-setup')) def test_authenticated_user_cannot_view_dashboard(self): """dashboard should redirect unverified users users to the login page""" response = self.client.get(reverse('dashboard')) self.assertEqual(response.status_code, 302) self.assertEqual(response.url, reverse('account_login'))
class DirectoryModerateWarningTest(TestCase): def setUp(self): site = Site.objects.get() self.entry = DirectoryEntryFactory(parent=DirectoryPageFactory( parent=site.root_page)) self.result = ScanResultFactory( securedrop=self.entry, landing_page_url=self.entry.landing_page_url, moderate_warning=True, ) self.result.save() self.entry.save() self.client = Client() def test_warning_presence(self): """warning should always be displayed""" response = self.client.get(self.entry.url) self.assertContains( response, 'We recommend only visiting this SecureDrop landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>.', status_code=200, ) def test_warning_message_suppressed_if_page_ignores_all_triggered_warnings( self): self.entry.warnings_ignored = ['safe_onion_address'] self.entry.save() response = self.client.get(self.entry.url) self.assertNotContains( response, 'We recommend only visiting this SecureDrop landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>.', status_code=200, ) def test_single_warning_message_suppressed_if_page_ignores_that_warning( self): self.result.subdomain = True self.result.save() self.entry.warnings_ignored = ['safe_onion_address'] self.entry.save() response = self.client.get(self.entry.url) self.assertContains( response, 'is hosted on a subdomain', status_code=200, ) self.assertNotContains( response, 'includes a clickable link to a Tor Onion Service', status_code=200, )
class DirectoryMultipleFiltersTest(TestCase): def setUp(self): self.directory = DirectoryPageFactory() # set up languages spanish = LanguageFactory(title='Spanish') chinese = LanguageFactory(title='Chinese') spanish.save() chinese.save() # set up countries mexico = CountryFactory(title='Mexico') azerbaijan = CountryFactory(title='Azerbaijan') mexico.save() azerbaijan.save() # set up topics pf = TopicFactory(title='Press Freedom') irs = TopicFactory(title='IRS') pf.save() irs.save() # set up instances that are children of the directory and have multiple categories self.sp_mx_instance = DirectoryEntryFactory(parent=self.directory) self.sp_mx_instance.languages.add(spanish) self.sp_mx_instance.countries.add(mexico) self.sp_mx_instance.save() self.az_pf_instance = DirectoryEntryFactory(parent=self.directory) self.az_pf_instance.countries.add(azerbaijan) self.az_pf_instance.topics.add(pf) self.az_pf_instance.save() self.other_instance = DirectoryEntryFactory(parent=self.directory) self.other_instance.languages.add(spanish) self.other_instance.topics.add(pf) self.other_instance.save() # filters self.lang_country_filter = { 'languages': spanish, 'countries': mexico } self.country_topic_filter = { 'countries': azerbaijan, 'topics': pf } def test_country_and_language_filter(self): filtered_instances = self.directory.get_instances(filters=self.lang_country_filter) self.assertIn(self.sp_mx_instance, filtered_instances) self.assertNotIn(self.other_instance, filtered_instances) def test_country_and_topic_filter(self): filtered_instances = self.directory.get_instances(filters=self.country_topic_filter) self.assertIn(self.az_pf_instance, filtered_instances) self.assertNotIn(self.other_instance, filtered_instances)
class ScanResultTest(TestCase): def setUp(self): self.securedrop = DirectoryEntryFactory() self.securedrop.save() def test_instance_on_subdomain_gets_moderate_warning(self): result = ScanResultFactory(no_failures=True, subdomain=True) self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.MODERATE) def test_instance_with_incorrect_referrer_policy_gets_moderate_warning(self): result = ScanResultFactory(no_failures=True, referrer_policy_set_to_no_referrer=False) self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.MODERATE) def test_instance_with_unsafe_onion_addresses_gets_moderate_warning(self): result = ScanResultFactory(no_failures=True, safe_onion_address=False) self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.MODERATE) def test_instance_with_third_party_cookies_gets_no_warning(self): result = ScanResultFactory(no_failures=True, no_cookies=False) self.assertEqual(self.securedrop.get_warnings(result), []) def test_instance_with_analytics_gets_severe_warning(self): result = ScanResultFactory(no_failures=True, no_analytics=False) self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.SEVERE) def test_instance_with_cdn_gets_no_warning(self): result = ScanResultFactory(no_failures=True, no_cdn=False) self.assertEqual(self.securedrop.get_warnings(result), []) def test_instance_with_cross_domain_assets_gets_severe_warning(self): result = ScanResultFactory(no_failures=True, no_cross_domain_assets=False) self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.SEVERE) def test_grade_computed_on_save(self): result = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop) self.assertEqual(result.grade, '?') result.save() self.assertEqual(result.grade, 'A') def test_an_instance_using_cookies_gets_an_F(self): result = ScanResult(live=True, no_cookies=False, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'F') def test_an_instance_using_a_cdn_gets_a_D(self): result = ScanResult(live=True, no_cdn=False, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'D') def test_an_instance_using_a_subdomain_gets_a_D(self): result = ScanResult(live=True, subdomain=True, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'D') def test_an_instance_showing_server_software_in_headers_gets_a_D(self): result = ScanResult(live=True, no_server_info=False, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'D') def test_an_instance_showing_server_version_in_headers_gets_a_D(self): result = ScanResult(live=True, no_server_version=False, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'D') def test_an_instance_with_expires_not_set_gets_a_C(self): result = ScanResult(live=True, expires_set=False, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'C') def test_an_instance_with_cache_control_nostore_not_set_gets_a_B(self): result = ScanResult(live=True, cache_control_nostore_set=False, hsts_max_age=True, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, 'B') def test_a_down_instance_gets_a_null_grade(self): result = ScanResult(live=False, securedrop=self.securedrop) result.save() self.assertEqual(result.grade, '?') def test_securedrop_can_get_most_recent_scan(self): result1 = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop, landing_page_url=self.securedrop.landing_page_url) result1.save() result2 = ScanResult(live=True, hsts=False, hsts_max_age=True, securedrop=self.securedrop, landing_page_url=self.securedrop.landing_page_url) result2.save() securedrop = DirectoryEntry.objects.get(id=self.securedrop.pk) most_recent = securedrop.results.latest() self.assertEqual(most_recent.grade, 'C') def test_result_string_representation(self): result1 = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop, landing_page_url=self.securedrop.landing_page_url) self.assertIn(result1.landing_page_url, result1.__str__()) def test_is_equal_to_compares_only_scan_attributes__same_result(self): """Test is_equal_to does not compare pk, _state, etc.""" result1 = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop) result2 = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop) self.assertTrue(result1.is_equal_to(result2)) def test_is_equal_to_compares_only_scan_attributes__new_result(self): result1 = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop) result2 = ScanResult(live=False, securedrop=self.securedrop) self.assertFalse(result1.is_equal_to(result2)) def test_save_associates_results(self): result = ScanResult( live=True, hsts=True, hsts_max_age=True, securedrop=None, landing_page_url=self.securedrop.landing_page_url, ) result.save() self.assertEqual(result.securedrop, self.securedrop)
class VerifiedTest(TestCase): @classmethod def setUpTestData(self): turn_on_instance_management() def setUp(self): User = get_user_model() self.client = Client() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password, is_active=True) self.site = Site.objects.get() self.directory = DirectoryPageFactory( parent=self.site.root_page, ) self.unowned_sd_page = DirectoryEntryFactory() self.unowned_sd_page.save() self.user_owned_sd_page = DirectoryEntryFactory() self.user_owned_sd_page.save() SecuredropOwner(owner=self.user, page=self.user_owned_sd_page).save() # Create a verified email address object for this user via allauth EmailAddress.objects.create(user=self.user, email=self.email, verified=True) # Create a device with pre-determined parameters to allow 2FA # token verification. Numbers copied from django_otp unit # tests. device = TOTPDevice.objects.create( user=self.user, confirmed=True, key='2a2bbba1092ffdd25a328ad1a0a5f5d61d7aacc4', step=30, t0=int(time() - (30 * 3)), digits=6, tolerance=0, drift=0, ) self.client.post( reverse('account_login'), {'login': self.email, 'password': self.password}, ) self.client.post( reverse('two-factor-authenticate'), # The token below corresponds to the parameters on the # device just created. {'otp_device': device.id, 'otp_token': '154567'}, ) def test_verified_user_can_view_dashboard(self): response = self.client.get(reverse('dashboard')) self.assertEqual(response.status_code, 200) def test_verified_user_can_view_their_instances(self): slug = self.user_owned_sd_page.slug response = self.client.get(reverse('securedroppage_edit', kwargs={'slug': slug})) self.assertEqual(response.status_code, 200) def test_verified_user_cannot_view_other_instances(self): slug = self.unowned_sd_page.slug response = self.client.get(reverse('securedroppage_edit', kwargs={'slug': slug})) self.assertEqual(response.status_code, 403) def test_verified_user_can_edit_their_instances(self): new_title = 'New' slug = self.user_owned_sd_page.slug response = self.client.post( reverse('securedroppage_edit', kwargs={'slug': slug}), { 'title': new_title, # The autocomplete widget parses the below form values # as JSON, and 'null' is the least obtrusive value to # send. 'languages': 'null', 'topics': 'null', 'countries': 'null', }, ) self.assertEqual(response.status_code, 200) def test_verified_user_cannot_edit_other_instances(self): new_title = 'New' slug = self.unowned_sd_page.slug response = self.client.post( reverse('securedroppage_edit', kwargs={'slug': slug}), { 'title': new_title, # The autocomplete widget parses the below form values # as JSON, and 'null' is the least obtrusive value to # send. 'languages': 'null', 'topics': 'null', 'countries': 'null', } ) self.assertEqual(response.status_code, 403)