def test_does_not_sign_non_hawk_requests(self): """Test that a 403 is returned if the request is not authenticated using Hawk.""" from rest_framework.test import force_authenticate factory = APIRequestFactory() user = create_test_user() view = HawkViewWithScope.as_view() request = factory.get('/test-hawk-with-scope/') force_authenticate(request, user=user) response = view(request) assert response.status_code == status.HTTP_403_FORBIDDEN assert response.data == { 'detail': 'You do not have permission to perform this action.', }
def test_document_upload_status_no_status_without_permission(self): """Tests user without permission can't call upload status endpoint.""" entity_document = create_evidence_document() url = reverse( 'api-v3:investment:evidence-document:document-item-callback', kwargs={ 'project_pk': entity_document.investment_project.pk, 'entity_document_pk': entity_document.pk, }, ) user = create_test_user(permission_codenames=[], dit_team=TeamFactory()) api_client = self.create_api_client(user=user) response = api_client.post(url, data={}) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_permission_checking(self, permission_codenames, expected_status, api_client): """Test that the expected status is returned for various user permissions.""" user = create_test_user(permission_codenames=permission_codenames, dit_team=None) company_list = CompanyListFactory(adviser=user) url = _get_list_detail_url(company_list.pk) api_client = self.create_api_client(user=user) response = api_client.patch( url, data={ 'name': 'test list', }, ) assert response.status_code == expected_status
def test_delete_company_export_countries_check_history_tracks_correct_user( self): """ Check that history correctly tracks the user who deletes the export country """ company = CompanyFactory() country = CountryModel.objects.order_by('name')[0] adviser = AdviserFactory() export_country = CompanyExportCountryFactory( company=company, country=country, status=CompanyExportCountry.Status.FUTURE_INTEREST, created_by=adviser, ) CompanyExportCountryHistoryFactory( id=export_country.id, company=export_country.company, country=export_country.country, status=export_country.status, history_type=CompanyExportCountryHistory.HistoryType.INSERT, history_user=export_country.created_by, ) new_user = create_test_user(permission_codenames=( 'change_company', 'change_companyexportcountry', ), ) api_client = self.create_api_client(user=new_user) url = reverse('api-v4:company:update-export-detail', kwargs={'pk': company.pk}) response = api_client.patch( url, data={ 'export_countries': [], }, ) assert response.status_code == status.HTTP_204_NO_CONTENT company.refresh_from_db() assert company.export_countries.count() == 0 delete_history = CompanyExportCountryHistory.objects.filter( company=company, history_type=CompanyExportCountryHistory.HistoryType.DELETE, ) assert delete_history.count() == 1 assert delete_history[0].country == country assert delete_history[0].history_user == new_user
def test_user_without_permission_cannot_get_report(self): """Test that user without permission cannot get a report.""" report = SPIReportFactory() url = reverse( 'investment-report:download-spi-report', kwargs={ 'pk': report.pk, }, ) user = create_test_user( is_staff=True, password=self.PASSWORD, permission_codenames=(), ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_permission_denied_if_staff_and_without_change_permission(self): """ Test that the view returns a 403 response if the staff user does not have the change contact permission. """ url = reverse( admin_urlname(Contact._meta, 'load-email-marketing-opt-outs'), ) user = create_test_user( permission_codenames=(ContactPermission.view_contact,), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_view_returns_403(self): """ Tests view returns 403 """ user = create_test_user(dit_team=TeamFactory()) token = self.get_token(user=user) request = factory.get( '/', data={}, content_type='application/json', Authorization=f'Bearer {token}', ) my_view = PermissionModelViewset.as_view(actions={'get': 'list'}, ) response = my_view(request) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_restricted_users_cannot_see_other_teams_projects(self, setup_es): """Test that restricted users cannot see other teams' projects in the export.""" team = TeamFactory() team_other = TeamFactory() adviser_other = AdviserFactory(dit_team_id=team_other.id) adviser_same_team = AdviserFactory(dit_team_id=team.id) request_user = create_test_user( permission_codenames=( InvestmentProjectPermission.view_associated, InvestmentProjectPermission.export, ), dit_team=team, ) api_client = self.create_api_client(user=request_user) project_other = InvestmentProjectFactory() team_projects = [ InvestmentProjectFactory(), InvestmentProjectFactory(created_by=adviser_same_team), InvestmentProjectFactory(client_relationship_manager=adviser_same_team), InvestmentProjectFactory(project_manager=adviser_same_team), InvestmentProjectFactory(project_assurance_adviser=adviser_same_team), ] InvestmentProjectTeamMemberFactory(adviser=adviser_other, investment_project=project_other) InvestmentProjectTeamMemberFactory( adviser=adviser_same_team, investment_project=team_projects[0], ) setup_es.indices.refresh() url = reverse('api-v3:search:investment_project-export') response = api_client.post(url, {}) assert response.status_code == status.HTTP_200_OK response_text = response.getvalue().decode('utf-8-sig') reader = DictReader(StringIO(response_text)) actual_rows = [dict(item) for item in reader] assert len(actual_rows) == 5 expected_names = {project.name for project in team_projects} assert {row['Project name'] for row in actual_rows} == expected_names
def test_global_restricted_users_cannot_see_other_teams_projects(self, setup_es): """ Automatic filter to see only associated IP for a specific (leps) user """ team = TeamFactory() team_other = TeamFactory() adviser_other = AdviserFactory(dit_team_id=team_other.id) adviser_same_team = AdviserFactory(dit_team_id=team.id) request_user = create_test_user( permission_codenames=['view_associated_investmentproject'], dit_team=team, ) api_client = self.create_api_client(user=request_user) project_other = InvestmentProjectFactory() project_1 = InvestmentProjectFactory() project_2 = InvestmentProjectFactory(created_by=adviser_same_team) project_3 = InvestmentProjectFactory(client_relationship_manager=adviser_same_team) project_4 = InvestmentProjectFactory(project_manager=adviser_same_team) project_5 = InvestmentProjectFactory(project_assurance_adviser=adviser_same_team) InvestmentProjectTeamMemberFactory(adviser=adviser_other, investment_project=project_other) InvestmentProjectTeamMemberFactory(adviser=adviser_same_team, investment_project=project_1) setup_es.indices.refresh() url = reverse('api-v3:search:basic') response = api_client.get( url, data={ 'term': '', 'entity': 'investment_project', }, ) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert response_data['count'] == 5 results = response_data['results'] expected_ids = { str(project_1.id), str(project_2.id), str(project_3.id), str(project_4.id), str(project_5.id), } assert {result['id'] for result in results} == expected_ids
def test_adviser_report_download(self): """Test the download of a report.""" AdviserFactory.create_batch(5) url = reverse('admin_report:download-report', kwargs={'report_id': 'all-advisers'}) user = create_test_user( permission_codenames=('view_advisor',), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_200_OK # 7 = header + test user + the 5 test advisers assert len(response.getvalue().decode('utf-8').splitlines()) == 7
def test_restricted_user_cannot_update_company_interaction(self): """Test that a restricted user cannot update a company interaction.""" requester = create_test_user( permission_codenames=[InteractionPermission.change_associated_investmentproject], ) interaction = CompanyInteractionFactory(subject='I am a subject') api_client = self.create_api_client(user=requester) url = reverse('api-v3:interaction:item', kwargs={'pk': interaction.pk}) response = api_client.patch( url, data={ 'subject': 'I am another subject', }, ) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_import_link_does_not_exist_if_only_has_view_permission(self): """ Test that there is not a link to import interactions if the user only has the delete (but not change) permission for interactions. """ user = create_test_user( permission_codenames=(InteractionPermission.view_all, ), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(interaction_change_list_url) assert response.status_code == status.HTTP_200_OK assert f'Select {Interaction._meta.verbose_name} to view' in response.rendered_content assert import_interactions_url not in response.rendered_content
def test_document_delete_without_permission(self, delete_document): """Tests user can't delete document without permissions.""" entity_document = create_evidence_document() entity_document.document.mark_scan_scheduled() entity_document.document.mark_as_scanned(True, 'reason') url = reverse( 'api-v3:investment:evidence-document:document-item', kwargs={ 'project_pk': entity_document.investment_project.pk, 'entity_document_pk': entity_document.pk, }, ) user = create_test_user(permission_codenames=[], dit_team=TeamFactory()) api_client = self.create_api_client(user=user) response = api_client.delete(url) assert response.status_code == status.HTTP_403_FORBIDDEN assert delete_document.called is False
def test_non_restricted_user_cannot_get_non_existent_report(self): """Test user cannot get a report that doesn't exist.""" url = reverse( 'investment-report:download-spi-report', kwargs={ 'pk': uuid4(), }, ) user = create_test_user( is_staff=True, password=self.PASSWORD, permission_codenames=( SPIReportPermission.view, ), ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_404_NOT_FOUND
def test_add(self, permissions): """Test add a new interaction.""" adviser = create_test_user( permission_codenames=permissions, dit_team=TeamFactory(), ) contact = ContactFactory() communication_channel = random_obj_for_model(CommunicationChannel) service = Service.objects.get( pk=ServiceConstant.providing_investment_advice_and_information. value.id, ) url = reverse('api-v3:interaction:collection') request_data = { 'kind': Interaction.KINDS.interaction, 'communication_channel': communication_channel.pk, 'subject': 'whatever', 'date': date.today().isoformat(), 'dit_participants': [{ 'adviser': adviser.pk, }], 'company': contact.company.pk, 'contacts': [contact.pk], 'was_policy_feedback_provided': False, 'export_countries': [], 'service': service.pk, 'service_answers': { ServiceQuestionID.piai_what_did_you_give_advice_about.value: { ServiceAnswerOptionID.piai_banking_and_funding.value: {}, }, }, } api_client = self.create_api_client(user=adviser) response = api_client.post(url, request_data) assert response.status_code == status.HTTP_201_CREATED response_data = response.json() assert response_data['service'] == { 'id': str(service.id), 'name': service.name, } assert response_data['service_answers'] == request_data[ 'service_answers']
def test_filter_by_permission( self, permission_config, filter_by_permission, should_match, ): """Test the `has_permission` filter in various cases.""" user = create_test_user( permission_codenames=('view_advisor', ), is_superuser=permission_config.is_superuser, dit_team=TeamFactory(), ) if permission_config.user_permission: permission = _get_permission(permission_config.user_permission) user.user_permissions.add(permission) if permission_config.group_permission: group = _make_group('group 1', permission_config.group_permission) user.groups.add(group) if permission_config.team_role_permission: group = _make_group('group 2', permission_config.team_role_permission) user.dit_team.role.groups.add(group) api_client = self.create_api_client(user=user) url = reverse('api-v1:advisor-list') response = api_client.get( url, data={ 'permissions__has': filter_by_permission, }, ) assert response.status_code == status.HTTP_200_OK response_data = response.json() if should_match: assert response_data['count'] == 1 result = response_data['results'][0] assert result['id'] == str(user.pk) else: assert response_data['count'] == 0
def test_403_if_no_permissions(self): """Test 403 if user doesn't have enough permissions.""" order = OrderFactory() url = reverse('admin:order_order_cancel', args=(order.pk, )) # create user with all order permissions apart from change user = create_test_user( is_staff=True, password=self.PASSWORD, permission_codenames=( OrderPermission.add, OrderPermission.delete, OrderPermission.view, ), ) client = self.create_client(user=user) response = client.post(url, data={}) assert response.status_code == 403
def test_returns_error_if_adviser_has_no_sso_email_user_id(self): """If an adviser without an SSO email user ID is specified, an error should be returned.""" user = create_test_user(is_staff=True, is_superuser=True, password=self.PASSWORD) adviser = AdviserFactory(sso_email_user_id=None) client = self.create_client(user=user) data = { 'adviser': adviser.pk, 'expires_in_hours': 10, } response = client.post(add_access_token_url, data=data) assert response.status_code == status.HTTP_200_OK form = response.context['form'] assert form.errors == { 'adviser': [NO_SSO_EMAIL_USER_ID_MESSAGE], }
def test_all_with_view_document_permission(self): """Test getting all contacts with view document permission.""" ContactFactory.create_batch( 5, archived_documents_url_path='https://some-docs') user = create_test_user(permission_codenames=( 'view_contact', 'view_contact_document', ), ) api_client = self.create_api_client(user=user) url = reverse('api-v3:contact:list') response = api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 5 assert all( contact['archived_documents_url_path'] == 'https://some-docs' for contact in response.data['results'])
def test_draft_update_enforces_required_fields(self, permissions, data, error_response): """ Test that changing a draft to completed will enforce service and communication_channel to be set. """ requester = create_test_user(permission_codenames=permissions) draft_interaction = CompanyInteractionFactory( kind=Interaction.KINDS.interaction, status=Interaction.STATUSES.draft, service_id=None, communication_channel=None, ) api_client = self.create_api_client(user=requester) url = reverse('api-v3:interaction:item', kwargs={'pk': draft_interaction.pk}) data = resolve_data(data) response = api_client.patch(url, data=data) assert(response.status_code == status.HTTP_400_BAD_REQUEST) assert response.data == error_response
def test_adds_access_token_on_success(self, expires_in_hours): """The generated access token should be stored in the cache.""" user = create_test_user(is_staff=True, is_superuser=True, password=self.PASSWORD) sso_email_user_id = '*****@*****.**' adviser = AdviserFactory(sso_email_user_id=sso_email_user_id) client = self.create_client(user=user) frozen_time = now() with freeze_time(frozen_time): data = { 'adviser': adviser.pk, 'expires_in_hours': expires_in_hours, } response = client.post(add_access_token_url, data=data, follow=True) assert response.status_code == status.HTTP_200_OK assert response.redirect_chain == [ (admin_index_url, status.HTTP_302_FOUND), ] messages = list(response.context['messages']) assert len(messages) == 1 success_message_text = messages[0].message search_pattern = r'<code style="user-select: all">(?P<token>[0-9a-zA-Z_-]+)</code>' match = re.search(search_pattern, success_message_text) assert match token = match.group('token') expected_expiry_time = frozen_time + timedelta(hours=expires_in_hours) with freeze_time(expected_expiry_time - timedelta(seconds=1)): assert cache.get(f'access_token:{token}') == { 'email': adviser.email, 'sso_email_user_id': sso_email_user_id, } with freeze_time(expected_expiry_time): assert cache.get(f'access_token:{token}') is None
def test_link_does_not_exist_with_only_view_permission(self): """Test that the link does not exist for a user with only the view company permission.""" company = CompanyFactory() change_route_name = admin_urlname(Company._meta, 'change') change_url = reverse(change_route_name, args=(company.pk,)) user = create_test_user( permission_codenames=(CompanyPermission.view_company,), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(change_url) assert response.status_code == status.HTTP_200_OK select_other_route_name = admin_urlname(Company._meta, 'merge-select-other-company') select_other_url = reverse(select_other_route_name) assert select_other_url not in response.rendered_content
def test_permission_checking(self, permission_codenames, expected_status, api_client): """ Test that the expected status is returned depending on the permissions the user has. """ user = create_test_user(permission_codenames=permission_codenames) api_client = self.create_api_client(user=user) request_data = { 'subject': 'Test referral', 'company': { 'id': CompanyFactory().pk, }, 'recipient': { 'id': AdviserFactory().pk, }, } response = api_client.post(collection_url, data=request_data) assert response.status_code == expected_status
def test_who_am_i_active_features(self): """Active features should include the user's selected active features.""" feature_flag = UserFeatureFlagFactory(code='test-feature', is_active=True) inactive_feature_flag = UserFeatureFlagFactory(code='inactive-feature', is_active=False) UserFeatureFlagFactory(code='another-feature', is_active=True) user = create_test_user() user.features.add(feature_flag, inactive_feature_flag) api_client = self.create_api_client(user=user) url = reverse('who_am_i') response = api_client.get(url) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert 'active_features' in response_data assert response_data['active_features'] == ['test-feature']
def test_add_adviser_link_existence( self, permission_codenames, should_link_exist, ): """Test that there is a link to add an adviser from SSO if the user has the correct permissions. """ user = create_test_user( permission_codenames=permission_codenames, password=self.PASSWORD, is_staff=True, ) client = self.create_client(user) response = client.get(changelist_url) assert response.status_code == status.HTTP_200_OK assert (add_from_sso_url in response.rendered_content) == should_link_exist
def test_user_with_permission_can_get_report(self): """Test get report by a user with permission.""" report = SPIReportFactory() url = reverse( 'investment-report:download-spi-report', kwargs={ 'pk': report.pk, }, ) user = create_test_user( is_staff=True, password=self.PASSWORD, permission_codenames=(SPIReportPermission.change, ), ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_302_FOUND assert report.s3_key in response.url
def test_link_does_not_exist_with_only_view_permission(self): """ Test that the link does not exist for a user with only the view company permission. """ list_route_name = admin_urlname(Company._meta, 'changelist') list_url = reverse(list_route_name) user = create_test_user( permission_codenames=(CompanyPermission.view_company,), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(list_url) assert response.status_code == status.HTTP_200_OK company_link_route_name = admin_urlname(Company._meta, 'dnb-link-select-ids') company_link_url = reverse(company_link_route_name) assert company_link_url not in response.rendered_content
def test_one_list_download(self): """Test the download of the One List.""" CompanyFactory.create_batch( 2, headquarter_type_id=constants.HeadquarterType.ghq.value.id, classification=random_obj_for_model(CompanyClassification), one_list_account_owner=AdviserFactory(), ) # ignored because headquarter_type is None CompanyFactory( headquarter_type=None, classification=random_obj_for_model(CompanyClassification), one_list_account_owner=AdviserFactory(), ) # ignored because classification is None CompanyFactory( headquarter_type_id=constants.HeadquarterType.ghq.value.id, classification=None, one_list_account_owner=AdviserFactory(), ) # ignored because one_list_account_owner is None CompanyFactory( headquarter_type_id=constants.HeadquarterType.ghq.value.id, classification=random_obj_for_model(CompanyClassification), one_list_account_owner=None, ) url = reverse('admin-report:download-report', kwargs={'report_id': 'one-list'}) user = create_test_user( permission_codenames=('view_company', ), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_200_OK # 3 = header + the first 2 companies assert len(response.getvalue().decode('utf-8').splitlines()) == 3
def test_load_opt_outs_link_does_not_exist_if_only_has_view_permission(self): """ Test that there is not a link to load email marketing opt outs if the user only has view (but not change) permission for contacts. """ change_list_url = reverse(admin_urlname(Contact._meta, 'changelist')) user = create_test_user( permission_codenames=(ContactPermission.view_contact,), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(change_list_url) assert response.status_code == status.HTTP_200_OK load_opt_outs_url = reverse( admin_urlname(Contact._meta, 'load-email-marketing-opt-outs'), ) assert f'Select {Contact._meta.verbose_name} to view' in response.rendered_content assert load_opt_outs_url not in response.rendered_content
def test_non_restricted_user_can_only_list_relevant_interactions(self, permissions): """Test that a non-restricted user can list all interactions""" requester = create_test_user(permission_codenames=permissions) api_client = self.create_api_client(user=requester) project = InvestmentProjectFactory() company = CompanyFactory() company_interactions = CompanyInteractionFactory.create_batch(3, company=company) project_interactions = CompanyInteractionFactory.create_batch( 3, investment_project=project, ) url = reverse('api-v3:interaction:collection') response = api_client.get(url) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert response_data['count'] == 6 actual_ids = {i['id'] for i in response_data['results']} expected_ids = {str(i.id) for i in chain(project_interactions, company_interactions)} assert actual_ids == expected_ids