From b28fbc16d7bf715f8c3c283fef84d711c2615243 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Thu, 17 Mar 2016 10:46:47 +0000 Subject: [PATCH] A platform admin user is able to see a list of all services. Each service on the list is linked to the dashboard page of the service. The platform admin user can see/edit templates, see/invite users, see/edit service settings. The platform admin user can not send messages, see/edit api keys and developer docs. --- app/__init__.py | 6 +-- app/main/__init__.py | 3 +- app/main/dao/services_dao.py | 26 +++++------ app/main/dao/templates_dao.py | 12 ++--- app/main/views/add_service.py | 4 +- app/main/views/all_services.py | 15 ++++++ app/main/views/jobs.py | 1 - app/main/views/manage_users.py | 9 ++-- app/main/views/send.py | 2 +- app/main/views/service_settings.py | 17 ++++--- app/main/views/templates.py | 6 +-- app/notify_client/api_client.py | 26 ++--------- app/notify_client/models.py | 9 +++- app/templates/main_nav.html | 9 +++- app/templates/views/all-services.html | 16 +++++++ app/templates/views/choose-template.html | 8 ++-- app/templates/views/service_dashboard.html | 2 +- app/utils.py | 6 ++- tests/__init__.py | 4 +- tests/app/main/views/test_dashboard.py | 20 ++++++-- tests/app/main/views/test_sign_out.py | 3 +- tests/conftest.py | 54 +++++++++++++--------- 22 files changed, 154 insertions(+), 104 deletions(-) create mode 100644 app/main/views/all_services.py create mode 100644 app/templates/views/all-services.html diff --git a/app/__init__.py b/app/__init__.py index d0ce1d245..b7cd83520 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -12,7 +12,7 @@ from pygments.lexers import JavascriptLexer from pygments.formatters import HtmlFormatter from werkzeug.exceptions import abort -from app.notify_client.api_client import NotificationsAdminAPIClient +from app.notify_client.api_client import ServiceAPIClient from app.notify_client.api_key_api_client import ApiKeyApiClient from app.notify_client.user_api_client import UserApiClient from app.notify_client.job_api_client import JobApiClient @@ -29,7 +29,7 @@ from utils import logging login_manager = LoginManager() csrf = CsrfProtect() -notifications_api_client = NotificationsAdminAPIClient() +service_api_client = ServiceAPIClient() user_api_client = UserApiClient() api_key_api_client = ApiKeyApiClient() job_api_client = JobApiClient() @@ -48,7 +48,7 @@ def create_app(config_name, config_overrides=None): logging.init_app(application) init_csrf(application) - notifications_api_client.init_app(application) + service_api_client.init_app(application) user_api_client.init_app(application) api_key_api_client.init_app(application) job_api_client.init_app(application) diff --git a/app/main/__init__.py b/app/main/__init__.py index 39f95b71d..3a0af5a11 100644 --- a/app/main/__init__.py +++ b/app/main/__init__.py @@ -22,5 +22,6 @@ from app.main.views import ( choose_service, api_keys, manage_users, - invites + invites, + all_services ) diff --git a/app/main/dao/services_dao.py b/app/main/dao/services_dao.py index 39417fceb..69b8946b1 100644 --- a/app/main/dao/services_dao.py +++ b/app/main/dao/services_dao.py @@ -1,10 +1,10 @@ from flask import url_for, current_app -from app import notifications_api_client +from app import service_api_client from app.utils import BrowsableItem def update_service(service): - return notifications_api_client.update_service( + return service_api_client.update_service( service['id'], service['name'], service['active'], @@ -14,24 +14,24 @@ def update_service(service): def get_service_by_id(id_): - return notifications_api_client.get_service(id_) + return service_api_client.get_service(id_) def get_service_by_id_or_404(id_): - return notifications_api_client.get_service(id_)['data'] + return service_api_client.get_service(id_)['data'] def get_services(user_id=None): if user_id: - return notifications_api_client.get_services({'user_id': str(user_id)}) + return service_api_client.get_services({'user_id': str(user_id)}) else: - return notifications_api_client.get_services() + return service_api_client.get_services() def unrestrict_service(service_id): - resp = notifications_api_client.get_service(service_id) + resp = service_api_client.get_service(service_id) if resp['data']['restricted']: - resp = notifications_api_client.update_service( + resp = service_api_client.update_service( service_id, resp['data']['name'], resp['data']['active'], @@ -41,9 +41,9 @@ def unrestrict_service(service_id): def activate_service(service_id): - resp = notifications_api_client.get_service(service_id) + resp = service_api_client.get_service(service_id) if not resp['data']['active']: - resp = notifications_api_client.update_service( + resp = service_api_client.update_service( service_id, resp['data']['name'], True, @@ -54,7 +54,7 @@ def activate_service(service_id): # TODO Fix when functionality is added to the api. def find_service_by_service_name(service_name, user_id=None): - resp = notifications_api_client.get_services(user_id) + resp = service_api_client.get_services(user_id) retval = None for srv_json in resp['data']: if srv_json['name'] == service_name: @@ -64,11 +64,11 @@ def find_service_by_service_name(service_name, user_id=None): def delete_service(id_): - return notifications_api_client.delete_service(id_) + return service_api_client.delete_service(id_) def find_all_service_names(user_id=None): - resp = notifications_api_client.get_services(user_id) + resp = service_api_client.get_services(user_id) return [x['name'] for x in resp['data']] diff --git a/app/main/dao/templates_dao.py b/app/main/dao/templates_dao.py index c6a22ccf2..63e5466bf 100644 --- a/app/main/dao/templates_dao.py +++ b/app/main/dao/templates_dao.py @@ -1,28 +1,28 @@ from flask import url_for -from app import notifications_api_client +from app import service_api_client from app.utils import BrowsableItem def insert_service_template(name, type_, content, service_id, subject=None): - return notifications_api_client.create_service_template( + return service_api_client.create_service_template( name, type_, content, service_id, subject) def update_service_template(id_, name, type_, content, service_id, subject=None): - return notifications_api_client.update_service_template( + return service_api_client.update_service_template( id_, name, type_, content, service_id) def get_service_templates(service_id): - return notifications_api_client.get_service_templates(service_id) + return service_api_client.get_service_templates(service_id) def get_service_template_or_404(service_id, template_id): - return notifications_api_client.get_service_template(service_id, template_id) + return service_api_client.get_service_template(service_id, template_id) def delete_service_template(service_id, template_id): - return notifications_api_client.delete_service_template( + return service_api_client.delete_service_template( service_id, template_id) diff --git a/app/main/views/add_service.py b/app/main/views/add_service.py index 415ef4c30..4ab30ed55 100644 --- a/app/main/views/add_service.py +++ b/app/main/views/add_service.py @@ -15,7 +15,7 @@ from app.notify_client.models import InvitedUser from app import ( invite_api_client, user_api_client, - notifications_api_client) + service_api_client) @main.route("/add-service", methods=['GET', 'POST']) @@ -36,7 +36,7 @@ def add_service(): heading = 'Which service do you want to set up notifications for?' if form.validate_on_submit(): session['service_name'] = form.name.data - service_id = notifications_api_client.create_service( + service_id = service_api_client.create_service( session['service_name'], False, current_app.config['DEFAULT_SERVICE_LIMIT'], True, session['user_id']) return redirect(url_for('main.service_dashboard', service_id=service_id)) diff --git a/app/main/views/all_services.py b/app/main/views/all_services.py new file mode 100644 index 000000000..0efd1171d --- /dev/null +++ b/app/main/views/all_services.py @@ -0,0 +1,15 @@ +from flask import render_template +from flask_login import login_required + +from app import service_api_client +from app.main import main +from app.main.dao import services_dao +from app.utils import user_has_permissions + + +@main.route("/all-services") +@login_required +@user_has_permissions(None, admin_override=True) +def show_all_services(): + services = [services_dao.ServicesBrowsableItem(x) for x in service_api_client.get_services()['data']] + return render_template('views/all-services.html', services=services) diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py index 9847ef2cc..7bfe5247a 100644 --- a/app/main/views/jobs.py +++ b/app/main/views/jobs.py @@ -4,7 +4,6 @@ import time from flask import ( render_template, - abort, jsonify ) from flask_login import login_required diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index f40b81637..4ad38587c 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -2,7 +2,6 @@ from flask import ( request, render_template, redirect, - abort, url_for, flash) @@ -24,7 +23,7 @@ from app.utils import user_has_permissions @main.route("/services//users") @login_required -@user_has_permissions('manage_users', 'manage_templates', 'manage_settings') +@user_has_permissions('manage_users', 'manage_templates', 'manage_settings', admin_override=True) def manage_users(service_id): users = user_api_client.get_users_for_service(service_id=service_id) invited_users = invite_api_client.get_invites_for_service(service_id=service_id) @@ -41,7 +40,7 @@ def manage_users(service_id): @main.route("/services//users/invite", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_users', 'manage_templates', 'manage_settings') +@user_has_permissions('manage_users', 'manage_templates', 'manage_settings', admin_override=True) def invite_user(service_id): service = get_service_by_id(service_id) @@ -64,7 +63,7 @@ def invite_user(service_id): @main.route("/services//users/", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_users', 'manage_templates', 'manage_settings') +@user_has_permissions('manage_users', 'manage_templates', 'manage_settings', admin_override=True) def edit_user_permissions(service_id, user_id): # TODO we should probably using the service id here in the get user # call as well. eg. /user/?&service_id=service_id @@ -101,7 +100,7 @@ def edit_user_permissions(service_id, user_id): @main.route("/services//cancel-invited-user/", methods=['GET']) -@user_has_permissions('manage_users', 'manage_templates', 'manage_settings') +@user_has_permissions('manage_users', 'manage_templates', 'manage_settings', admin_override=True) def cancel_invited_user(service_id, invited_user_id): invite_api_client.cancel_invited_user(service_id=service_id, invited_user_id=invited_user_id) diff --git a/app/main/views/send.py b/app/main/views/send.py index aab52a6cf..ed5f6e02c 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -66,7 +66,7 @@ def get_page_headings(template_type): @main.route("/services//send/", methods=['GET']) @login_required -@user_has_permissions('send_texts', 'send_emails', 'send_letters', 'manage_templates', or_=True) +@user_has_permissions('send_texts', 'send_emails', 'send_letters', 'manage_templates', admin_override=True, or_=True) def choose_template(service_id, template_type): service = services_dao.get_service_by_id_or_404(service_id) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 6c7232e77..f596ee1dd 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -3,7 +3,6 @@ from flask import ( redirect, request, url_for, - abort, session, flash ) @@ -29,7 +28,7 @@ from app.main.forms import ConfirmPasswordForm, ServiceNameForm @main.route("/services//service-settings") @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_settings(service_id): service = get_service_by_id(service_id)['data'] @@ -42,7 +41,7 @@ def service_settings(service_id): @main.route("/services//service-settings/name", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_name_change(service_id): service = get_service_by_id(service_id)['data'] @@ -61,7 +60,7 @@ def service_name_change(service_id): @main.route("/services//service-settings/name/confirm", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_name_change_confirm(service_id): service = get_service_by_id(service_id)['data'] @@ -95,7 +94,7 @@ def service_name_change_confirm(service_id): @main.route("/services//service-settings/request-to-go-live", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_request_to_go_live(service_id): service = get_service_by_id(service_id)['data'] if request.method == 'GET': @@ -112,7 +111,7 @@ def service_request_to_go_live(service_id): @main.route("/services//service-settings/status", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_status_change(service_id): service = get_service_by_id(service_id)['data'] @@ -128,7 +127,7 @@ def service_status_change(service_id): @main.route("/services//service-settings/status/confirm", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_status_change_confirm(service_id): service = get_service_by_id(service_id)['data'] @@ -151,7 +150,7 @@ def service_status_change_confirm(service_id): @main.route("/services//service-settings/delete", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_delete(service_id): service = get_service_by_id(service_id)['data'] @@ -167,7 +166,7 @@ def service_delete(service_id): @main.route("/services//service-settings/delete/confirm", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_settings') +@user_has_permissions('manage_settings', admin_override=True) def service_delete_confirm(service_id): service = get_service_by_id(service_id)['data'] diff --git a/app/main/views/templates.py b/app/main/views/templates.py index f390ff9af..7e34cc79f 100644 --- a/app/main/views/templates.py +++ b/app/main/views/templates.py @@ -21,7 +21,7 @@ page_headings = { @main.route("/services//templates/add-", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_templates') +@user_has_permissions('manage_templates', admin_override=True) def add_service_template(service_id, template_type): service = sdao.get_service_by_id_or_404(service_id) @@ -54,7 +54,7 @@ def add_service_template(service_id, template_type): @main.route("/services//templates/", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_templates') +@user_has_permissions('manage_templates', admin_override=True) def edit_service_template(service_id, template_id): template = tdao.get_service_template_or_404(service_id, template_id)['data'] template['template_content'] = template['content'] @@ -83,7 +83,7 @@ def edit_service_template(service_id, template_id): @main.route("/services//templates//delete", methods=['GET', 'POST']) @login_required -@user_has_permissions('manage_templates') +@user_has_permissions('manage_templates', admin_override=True) def delete_service_template(service_id, template_id): template = tdao.get_service_template_or_404(service_id, template_id)['data'] diff --git a/app/notify_client/api_client.py b/app/notify_client/api_client.py index dbe66d2d4..6f703e622 100644 --- a/app/notify_client/api_client.py +++ b/app/notify_client/api_client.py @@ -2,14 +2,14 @@ from __future__ import unicode_literals from notifications_python_client.notifications import NotificationsAPIClient -class NotificationsAdminAPIClient(NotificationsAPIClient): +class ServiceAPIClient(NotificationsAPIClient): # Fudge assert in the super __init__ so # we can set those variables later. def __init__(self): - super(NotificationsAdminAPIClient, self).__init__("api_url", - "client", - "secret") + super(ServiceAPIClient, self).__init__("api_url", + "client", + "secret") def init_app(self, application): self.base_url = application.config['API_HOST_NAME'] @@ -128,21 +128,3 @@ class NotificationsAdminAPIClient(NotificationsAPIClient): """ endpoint = "/service/{0}/template/{1}".format(service_id, template_id) return self.delete(endpoint) - - # The implementation of these will change after the notifications-api - # functionality updates to include the ability to send notifications. - def send_sms(self, - mobile_number, - message, - job_id=None, - description=None): - self.send_sms_notification(mobile_number, message) - - def send_email(self, - email_address, - message, - from_address, - subject, - job_id=None, - description=None): - self.send_email_notification(email_address, message, from_address, subject) diff --git a/app/notify_client/models.py b/app/notify_client/models.py index 3c27c09e4..3a4c9e92b 100644 --- a/app/notify_client/models.py +++ b/app/notify_client/models.py @@ -13,6 +13,7 @@ class User(UserMixin): self._failed_login_count = fields.get('failed_login_count') self._state = fields.get('state') self.max_failed_login_count = max_failed_login_count + self.platform_admin = fields.get('platform_admin') def get_id(self): return self.id @@ -82,7 +83,9 @@ class User(UserMixin): def permissions(self, permissions): raise AttributeError("Read only property") - def has_permissions(self, permissions, service_id=None, or_=False): + def has_permissions(self, permissions, service_id=None, or_=False, admin_override=False): + if admin_override and self.platform_admin: + return True if service_id is None: service_id = session.get('service_id', '') if service_id in self._permissions: @@ -91,6 +94,10 @@ class User(UserMixin): return set(self._permissions[service_id]) >= set(permissions) return False + def has_platform_admin_permissions(self): + print('platform_permissions {}'.format(self.platform_admin)) + self.platform_admin + @property def failed_login_count(self): return self._failed_login_count diff --git a/app/templates/main_nav.html b/app/templates/main_nav.html index 96c1c372b..da78a1110 100644 --- a/app/templates/main_nav.html +++ b/app/templates/main_nav.html @@ -7,13 +7,13 @@
  • Send text messages
  • Send emails
  • - {% elif current_user.has_permissions(['manage_templates']) %} + {% elif current_user.has_permissions(['manage_templates'], admin_override=True) %} {% endif %} - {% if current_user.has_permissions(['manage_users', 'manage_settings']) %} + {% if current_user.has_permissions(['manage_users', 'manage_settings'], admin_override=True) %} {% endif %} + {% if current_user.has_permissions([], admin_override=True) %} + + {% endif %} diff --git a/app/templates/views/all-services.html b/app/templates/views/all-services.html new file mode 100644 index 000000000..c278c8c5b --- /dev/null +++ b/app/templates/views/all-services.html @@ -0,0 +1,16 @@ +{% extends "withoutnav_template.html" %} +{% from "components/browse-list.html" import browse_list %} + +{% block page_title %} + All service – GOV.UK Notify +{% endblock %} + +{% block maincolumn_content %} + +

    + All services +

    + + {{ browse_list(services) }} + +{% endblock %} \ No newline at end of file diff --git a/app/templates/views/choose-template.html b/app/templates/views/choose-template.html index a5d28fd88..5d061c3df 100644 --- a/app/templates/views/choose-template.html +++ b/app/templates/views/choose-template.html @@ -14,7 +14,7 @@

    {{ page_heading }}

    - {% if current_user.has_permissions(['manage_templates']) %} + {% if current_user.has_permissions(['manage_templates'], admin_override=True) %} Add a new template {% else %}

    You need to ask your service manager to add templates before you can send messages

    @@ -26,7 +26,7 @@

    {{ page_heading }}

    - {% if current_user.has_permissions(['manage_templates']) %} + {% if current_user.has_permissions(['manage_templates'], admin_override=True) %} @@ -54,7 +54,7 @@ name=template.name, edit_link=( url_for(".edit_service_template", service_id=service_id, template_id=template.id) - if current_user.has_permissions(['manage_templates']) else + if current_user.has_permissions(['manage_templates'], admin_override=True) else None ) ) }} @@ -64,7 +64,7 @@ name=template.name, edit_link=( url_for(".edit_service_template", service_id=service_id, template_id=template.id) - if current_user.has_permissions(['manage_templates']) else + if current_user.has_permissions(['manage_templates'], admin_override=True) else None ) ) }} diff --git a/app/templates/views/service_dashboard.html b/app/templates/views/service_dashboard.html index f7a6dc7fa..0a276915d 100644 --- a/app/templates/views/service_dashboard.html +++ b/app/templates/views/service_dashboard.html @@ -27,7 +27,7 @@ {% if not template_count and not jobs %} {% call banner_wrapper(subhead='Get started', type="tip") %}
      - {% if current_user.has_permissions(['manage_templates']) %} + {% if current_user.has_permissions(['manage_templates'], admin_override=True) %}
    1. Add a template
    2. diff --git a/app/utils.py b/app/utils.py index c6688a5bc..f83c6ad97 100644 --- a/app/utils.py +++ b/app/utils.py @@ -30,12 +30,14 @@ class BrowsableItem(object): pass -def user_has_permissions(*permissions, or_=False): +def user_has_permissions(*permissions, admin_override=False, or_=False): def wrap(func): @wraps(func) def wrap_func(*args, **kwargs): from flask_login import current_user - if current_user and current_user.has_permissions(permissions, or_=or_): + if current_user and admin_override and current_user.platform_admin: + return func(*args, **kwargs) + if current_user and current_user.has_permissions(permissions, admin_override=admin_override, or_=or_): return func(*args, **kwargs) else: abort(403) diff --git a/tests/__init__.py b/tests/__init__.py index a316c4342..557ff8108 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -141,11 +141,11 @@ def validate_route_permission(mocker, 'app.user_api_client.check_verify_code', return_value=(True, '')) mocker.patch( - 'app.notifications_api_client.get_services', + 'app.service_api_client.get_services', return_value={'data': []}) mocker.patch('app.user_api_client.get_user', return_value=usr) mocker.patch('app.user_api_client.get_user_by_email', return_value=usr) - mocker.patch('app.notifications_api_client.get_service', return_value={'data': service}) + mocker.patch('app.service_api_client.get_service', return_value={'data': service}) with app_.test_request_context(): with app_.test_client() as client: diff --git a/tests/app/main/views/test_dashboard.py b/tests/app/main/views/test_dashboard.py index 0902f6293..1362c08d5 100644 --- a/tests/app/main/views/test_dashboard.py +++ b/tests/app/main/views/test_dashboard.py @@ -1,5 +1,4 @@ -from flask import url_for, session -from bs4 import BeautifulSoup +from flask import url_for def test_should_show_recent_jobs_on_dashboard(app_, @@ -29,11 +28,11 @@ def _test_dashboard_menu(mocker, app_, usr, service, permissions): 'app.user_api_client.check_verify_code', return_value=(True, '')) mocker.patch( - 'app.notifications_api_client.get_services', + 'app.service_api_client.get_services', return_value={'data': []}) mocker.patch('app.user_api_client.get_user', return_value=usr) mocker.patch('app.user_api_client.get_user_by_email', return_value=usr) - mocker.patch('app.notifications_api_client.get_service', return_value={'data': service}) + mocker.patch('app.service_api_client.get_service', return_value={'data': service}) client.login(usr) return client.get(url_for('main.service_dashboard', service_id=service['id'])) @@ -111,3 +110,16 @@ def test_menu_manage_api_keys(mocker, app_, api_user_active, service_one, mock_g assert url_for('main.api_keys', service_id=service_one['id']) in page assert url_for('main.documentation', service_id=service_one['id']) in page + + +def test_menu_all_services_for_platform_admin_user(mocker, app_, platform_admin_user, service_one, + mock_get_service_templates, mock_get_jobs): + with app_.test_request_context(): + resp = _test_dashboard_menu( + mocker, + app_, + platform_admin_user, + service_one, + []) + page = resp.get_data(as_text=True) + assert url_for('main.show_all_services') in page diff --git a/tests/app/main/views/test_sign_out.py b/tests/app/main/views/test_sign_out.py index a6b8e5fcb..8717684cf 100644 --- a/tests/app/main/views/test_sign_out.py +++ b/tests/app/main/views/test_sign_out.py @@ -17,7 +17,8 @@ def test_sign_out_user(app_, mock_get_user_by_email, mock_get_service_templates, mock_login, - mock_get_jobs): + mock_get_jobs, + mock_has_permissions): with app_.test_request_context(): with app_.test_client() as client: client.login(api_user_active) diff --git a/tests/conftest.py b/tests/conftest.py index 9d5c88f39..38bb03903 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -45,12 +45,7 @@ def service_one(request, api_user_active): @pytest.fixture(scope='function') def mock_send_sms(request, mocker): - return mocker.patch("app.notifications_api_client.send_sms") - - -@pytest.fixture(scope='function') -def mock_send_email(request, mocker): - return mocker.patch("app.notifications_api_client.send_email", autospec=True) + return mocker.patch("app.service_api_client.send_sms") @pytest.fixture(scope='function') @@ -61,7 +56,7 @@ def mock_get_service(mocker, api_user_active): active=False, restricted=True) return {'data': service} - return mocker.patch('app.notifications_api_client.get_service', side_effect=_get) + return mocker.patch('app.service_api_client.get_service', side_effect=_get) @pytest.fixture(scope='function') @@ -73,7 +68,7 @@ def mock_create_service(mocker): return service['id'] return mocker.patch( - 'app.notifications_api_client.create_service', side_effect=_create) + 'app.service_api_client.create_service', side_effect=_create) @pytest.fixture(scope='function') @@ -90,7 +85,7 @@ def mock_update_service(mocker): return {'data': service} return mocker.patch( - 'app.notifications_api_client.update_service', side_effect=_update) + 'app.service_api_client.update_service', side_effect=_update) @pytest.fixture(scope='function') @@ -108,7 +103,7 @@ def mock_update_service_raise_httperror_duplicate_name(mocker): raise http_error return mocker.patch( - 'app.notifications_api_client.update_service', side_effect=_update) + 'app.service_api_client.update_service', side_effect=_update) SERVICE_ONE_ID = "596364a0-858e-42c8-9062-a8fe822260eb" @@ -128,7 +123,7 @@ def mock_get_services(mocker, user=None): return {'data': [service_one, service_two]} return mocker.patch( - 'app.notifications_api_client.get_services', side_effect=_create) + 'app.service_api_client.get_services', side_effect=_create) @pytest.fixture(scope='function') @@ -142,7 +137,7 @@ def mock_get_services_with_one_service(mocker, user=None): )]} return mocker.patch( - 'app.notifications_api_client.get_services', side_effect=_create) + 'app.service_api_client.get_services', side_effect=_create) @pytest.fixture(scope='function') @@ -151,7 +146,7 @@ def mock_delete_service(mocker, mock_get_service): return mock_get_service.side_effect(service_id) return mocker.patch( - 'app.notifications_api_client.delete_service', side_effect=_delete) + 'app.service_api_client.delete_service', side_effect=_delete) @pytest.fixture(scope='function') @@ -162,7 +157,7 @@ def mock_get_service_template(mocker): return {'data': template} return mocker.patch( - 'app.notifications_api_client.get_service_template', side_effect=_create) + 'app.service_api_client.get_service_template', side_effect=_create) @pytest.fixture(scope='function') @@ -173,7 +168,7 @@ def mock_get_service_email_template(mocker): return {'data': template} return mocker.patch( - 'app.notifications_api_client.get_service_template', side_effect=_create) + 'app.service_api_client.get_service_template', side_effect=_create) @pytest.fixture(scope='function') @@ -184,7 +179,7 @@ def mock_create_service_template(mocker): return {'data': template} return mocker.patch( - 'app.notifications_api_client.create_service_template', + 'app.service_api_client.create_service_template', side_effect=_create) @@ -196,7 +191,7 @@ def mock_update_service_template(mocker): return {'data': template} return mocker.patch( - 'app.notifications_api_client.update_service_template', + 'app.service_api_client.update_service_template', side_effect=_update) @@ -219,7 +214,7 @@ def mock_get_service_templates(mocker): ]} return mocker.patch( - 'app.notifications_api_client.get_service_templates', + 'app.service_api_client.get_service_templates', side_effect=_create) @@ -232,7 +227,7 @@ def mock_delete_service_template(mocker): return {'data': template} return mocker.patch( - 'app.notifications_api_client.delete_service_template', side_effect=_delete) + 'app.service_api_client.delete_service_template', side_effect=_delete) @pytest.fixture(scope='function') @@ -251,6 +246,23 @@ def api_user_pending(): return user +@pytest.fixture(scope='function') +def platform_admin_user(): + from app.notify_client.user_api_client import User + user_data = {'id': 222, + 'name': 'Platform admin user', + 'password': 'somepassword', + 'email_address': 'platform@admin.gov.uk', + 'mobile_number': '+4472341234', + 'state': 'active', + 'failed_login_count': 0, + 'permissions': {}, + 'platform_admin': True + } + user = User(user_data) + return user + + @pytest.fixture(scope='function') def api_user_active(): from app.notify_client.user_api_client import User @@ -498,7 +510,7 @@ def mock_login(mocker, mock_get_user, mock_update_user): side_effect=_verify_code ), mocker.patch( - 'app.notifications_api_client.get_services', + 'app.service_api_client.get_services', side_effect=_no_services ) ) @@ -590,7 +602,7 @@ def mock_get_notifications(mocker): @pytest.fixture(scope='function') def mock_has_permissions(mocker): - def _has_permission(permissions, service_id=None, or_=False): + def _has_permission(permissions, service_id=None, or_=False, admin_override=False): return True return mocker.patch( 'app.notify_client.user_api_client.User.has_permissions',