diff --git a/app/__init__.py b/app/__init__.py index 17b17c563..0fd40481c 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -127,10 +127,10 @@ def create_app(): application.after_request(save_service_after_request) application.before_request(load_service_before_request) + @application.context_processor def _attach_current_service(): return {'current_service': current_service} - application.context_processor(_attach_current_service) register_errorhandlers(application) setup_event_handlers() @@ -338,10 +338,7 @@ def load_service_before_request(): else session.get('service_id') from flask.globals import _request_ctx_stack if _request_ctx_stack.top is not None: - setattr( - _request_ctx_stack.top, - 'service', - service_api_client.get_service(service_id)['data'] if service_id else None) + _request_ctx_stack.top.service = service_api_client.get_service(service_id)['data'] if service_id else None def save_service_after_request(response): diff --git a/app/main/views/letters.py b/app/main/views/letters.py index 27f0a4bf1..0458493ea 100644 --- a/app/main/views/letters.py +++ b/app/main/views/letters.py @@ -5,8 +5,11 @@ from app import current_service from app.main import main from app.utils import user_has_permissions + @main.route("/services//letters") @login_required @user_has_permissions('manage_templates', admin_override=True) def letters(service_id): + if not current_service['can_send_letters']: + abort(403) return render_template('views/letters.html') diff --git a/tests/__init__.py b/tests/__init__.py index e23f597b5..c1ffb0d4f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -40,9 +40,9 @@ def created_by_json(id_, name='', email_address=''): def service_json( - id_, - name, - users, + id_='1234', + name='Test Service', + users=None, message_limit=1000, active=False, restricted=True, @@ -50,9 +50,12 @@ def service_json( reply_to_email_address=None, sms_sender=None, research_mode=False, - organisation='organisation-id', + can_send_letters=False, + organisation=None, branding='govuk' ): + if users is None: + users = [] return { 'id': id_, 'name': name, @@ -64,6 +67,7 @@ def service_json( 'reply_to_email_address': reply_to_email_address, 'sms_sender': sms_sender, 'research_mode': research_mode, + 'can_send_letters': can_send_letters, 'organisation': organisation, 'branding': branding, 'created_at': str(datetime.utcnow()) diff --git a/tests/app/main/views/test_letters.py b/tests/app/main/views/test_letters.py new file mode 100644 index 000000000..c2c6451a6 --- /dev/null +++ b/tests/app/main/views/test_letters.py @@ -0,0 +1,17 @@ +import pytest +from flask import url_for + +from tests import service_json + + +@pytest.mark.parametrize('can_send_letters, response_code', [ + (True, 200), + (False, 403) +]) +def test_letters_access_restricted(logged_in_client, mocker, can_send_letters, response_code): + service = service_json(can_send_letters=can_send_letters) + mocker.patch('app.service_api_client.get_service', return_value={"data": service}) + + response = logged_in_client.get(url_for('main.letters', service_id=service['id'])) + + assert response.status_code == response_code diff --git a/tests/app/main/views/test_main_nav.py b/tests/app/main/views/test_main_nav.py new file mode 100644 index 000000000..f0cf23870 --- /dev/null +++ b/tests/app/main/views/test_main_nav.py @@ -0,0 +1,26 @@ +from flask import url_for +from bs4 import BeautifulSoup + +from tests import service_json + + +def test_can_see_letters_if_allowed(logged_in_client, mocker): + service = service_json(can_send_letters=True) + mocker.patch('app.service_api_client.get_service', return_value={"data": service}) + + response = logged_in_client.get(url_for('main.service_settings', service_id=service['id'])) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + assert 'Letter templates' in page.find('nav', class_='navigation').text + + +def test_cant_see_letters_if_not_allowed(logged_in_client, mocker): + service = service_json(can_send_letters=False) + mocker.patch('app.service_api_client.get_service', return_value={"data": service}) + + response = logged_in_client.get(url_for('main.service_settings', service_id=service['id'])) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + assert 'Letter templates' not in page.find('nav', class_='navigation').text diff --git a/tests/app/main/views/test_service_settings.py b/tests/app/main/views/test_service_settings.py index cb26e0a9b..924cce7a2 100644 --- a/tests/app/main/views/test_service_settings.py +++ b/tests/app/main/views/test_service_settings.py @@ -1,12 +1,13 @@ +from unittest.mock import call, ANY, Mock + import pytest from flask import url_for +from bs4 import BeautifulSoup +from werkzeug.exceptions import InternalServerError import app from app.utils import email_safe from tests import validate_route_permission, service_json -from bs4 import BeautifulSoup -from unittest.mock import ANY, Mock -from werkzeug.exceptions import InternalServerError def test_should_show_overview( @@ -814,3 +815,25 @@ def test_should_set_branding_and_organisations( branding='org', organisation='organisation-id' ) + + +def test_switch_service_enable_letters(logged_in_client, service_one, mocker): + mocked_fn = mocker.patch('app.service_api_client.update_service_with_properties', return_value=service_one) + + response = logged_in_client.get(url_for('main.service_switch_can_send_letters', service_id=service_one['id'])) + + assert response.status_code == 302 + assert response.location == url_for('main.service_settings', service_id=service_one['id'], _external=True) + assert mocked_fn.call_args == call(service_one['id'], {'can_send_letters': True}) + + +def test_switch_service_disable_letters(logged_in_client, mocker): + service = service_json("1234", "Test Service", [], can_send_letters=True) + mocker.patch('app.service_api_client.get_service', return_value={"data": service}) + mocked_fn = mocker.patch('app.service_api_client.update_service_with_properties', return_value=service) + + response = logged_in_client.get(url_for('main.service_switch_can_send_letters', service_id=service['id'])) + + assert response.status_code == 302 + assert response.location == url_for('main.service_settings', service_id=service['id'], _external=True) + assert mocked_fn.call_args == call(service['id'], {"can_send_letters": False}) diff --git a/tests/conftest.py b/tests/conftest.py index d257e5c14..0e01266e6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1276,3 +1276,16 @@ def mock_update_whitelist(mocker): def client(app_): with app_.test_request_context(), app_.test_client() as client: yield client + + +@pytest.fixture(scope='function') +def logged_in_client( + client, + active_user_with_permissions, + mock_login, + mock_get_user, + mock_get_service, + mock_has_permissions +): + client.login(active_user_with_permissions) + yield client