diff --git a/app/__init__.py b/app/__init__.py index b5337f95f..1495772fa 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -11,12 +11,15 @@ from flask import ( render_template, make_response, current_app, - request) + request, + g) from flask._compat import string_types from flask.globals import _lookup_req_object from flask_login import LoginManager from flask_wtf import CsrfProtect from functools import partial + +from monotonic import monotonic from notifications_python_client.errors import HTTPError from notifications_utils import logging from notifications_utils.recipients import validate_phone_number, InvalidPhoneError @@ -141,6 +144,11 @@ def init_csrf(application): def init_app(application): + + @application.before_request + def record_start_time(): + g.start = monotonic() + @application.context_processor def inject_global_template_variables(): return { diff --git a/app/assets/stylesheets/views/documenation.scss b/app/assets/stylesheets/views/documenation.scss index 62ff03ed8..5427a2c42 100644 --- a/app/assets/stylesheets/views/documenation.scss +++ b/app/assets/stylesheets/views/documenation.scss @@ -57,9 +57,19 @@ margin: 0 0 20px 0; } + pre, + code { + font-size: 16px; + } + + code { + background: $highlight-colour; + padding: 2px 5px; + } + .highlight { margin: 0 0 20px 0; - background: #F8F8F8; + background: $highlight-colour; } strong, diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py index 265503264..05785a6b1 100644 --- a/app/main/views/jobs.py +++ b/app/main/views/jobs.py @@ -57,7 +57,7 @@ def view_jobs(service_id): @user_has_permissions('view_activity', admin_override=True) def view_job(service_id, job_id): job = job_api_client.get_job(service_id, job_id)['data'] - template = service_api_client.get_service_template(service_id, job['template'])['data'] + template = service_api_client.get_service_template(service_id, job['template'], job['template_version'])['data'] notifications = notification_api_client.get_notifications_for_service(service_id, job_id) finished = job['status'] == 'finished' return render_template( diff --git a/app/main/views/send.py b/app/main/views/send.py index 20edf513b..f8f165e00 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -175,7 +175,7 @@ def send_test(service_id, template_id): get_example_csv_rows(template, use_example_as_example=False, submitted_fields=request.form) ]) filedata = { - 'file_name': 'Test run', + 'file_name': 'Test message', 'data': output.getvalue() } upload_id = str(uuid.uuid4()) diff --git a/app/notify_client/api_client.py b/app/notify_client/api_client.py index 52e106bde..d599db5ae 100644 --- a/app/notify_client/api_client.py +++ b/app/notify_client/api_client.py @@ -141,7 +141,7 @@ class ServiceAPIClient(NotificationsAPIClient): """ Retrieve a list of versions for a template """ - endpoint = '/service/{service_id}/template/{template_id}/version'.format( + endpoint = '/service/{service_id}/template/{template_id}/versions'.format( service_id=service_id, template_id=template_id ) diff --git a/app/templates/views/notifications.html b/app/templates/views/notifications.html index 52017694d..3e9b87438 100644 --- a/app/templates/views/notifications.html +++ b/app/templates/views/notifications.html @@ -81,7 +81,7 @@ {{ item.to }}

- {{ item.template.name }} + {{ item.template.name }} sent from {% if item.job %} {{ item.job.original_file_name }} diff --git a/app/templates/views/templates/_template_history.html b/app/templates/views/templates/_template_history.html index 7bbb71f26..d4bb80fa1 100644 --- a/app/templates/views/templates/_template_history.html +++ b/app/templates/views/templates/_template_history.html @@ -31,6 +31,10 @@

Edited by {{ template.get_raw('created_by').name }}

-

Edited on {{ template.get_raw('created_at')|format_datetime }}

+

Created on {{ template.get_raw('created_at')|format_datetime }}

+

Edited on + {% if template.get_raw('updated_at') %} + {{ template.get_raw('updated_at')|format_datetime }}

+ {% endif %}
\ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 02edbde33..1a0ec5fb1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -32,14 +32,14 @@ To find out more about GOV.UK Notify, see the [Government as a Platform](https:/

Before you start

- 1. Register for a [GOV.UK Notify](https://www.notifications.service.gov.uk/) account. - + 1. Register for a [GOV.UK Notify](https://www.notifications.service.gov.uk/) account. + You'll need an email address from a local or central government organisation and your mobile phone for 2-factor authentication. - 2. Add a template so you can send text and email notifications. + 2. Add a template so you can send text and email notifications. **Note:** A template is required even if you send notifications with the GOV.UK Notify API. - + You can personalise the template using double brackets for placeholders. For example: > Dear ((name)), @@ -49,8 +49,8 @@ To find out more about GOV.UK Notify, see the [Government as a Platform](https:/ 3. Create an API key. This will be used to connect to the GOV.UK Notify API. Each service can have multiple API keys. This allows you to integrate several systems, each with its own key. You can also have separate keys for your development and test environments. - - **Important:** API keys are secret, so save them somewhere safe. Don't commit API keys to public source code repositories. + + **Important:** API keys are secret, so save them somewhere safe. Don't commit API keys to public source code repositories.

Integrate the GOV.UK Notify API into your service

@@ -58,13 +58,13 @@ There are 2 ways to integrate the API into your service: * use one of the client libraries provided by GOV.UK Notify (see the Usage section in the Readme files): * [Python library](https://github.com/alphagov/notifications-python-client) - * [PHP library] (https://github.com/alphagov/notifications-php-client) - * [Java library] (https://github.com/alphagov/notifications-java-client) + * [PHP library](https://github.com/alphagov/notifications-php-client) + * [Java library](https://github.com/alphagov/notifications-java-client) * develop your own integration to produce requests in the correct format

Authenticate requests

-GOV.UK Notify uses [JSON Web Tokens (JWT)](https://jwt.io/introduction/) for authentication and identification. The GOV.UK Notify client libraries encode and decode JSON Web Tokens when making requests to the GOV.UK Notify API. If you don’t use one of these libraries, you must manually create tokens yourself. +GOV.UK Notify uses [JSON Web Tokens (JWT)](https://jwt.io/introduction/) for authentication and identification. The GOV.UK Notify client libraries encode and decode JSON Web Tokens when making requests to the GOV.UK Notify API. If you don’t use one of these libraries, you must manually create tokens yourself. For examples of how to encode and decode JSON Web Tokens, see [authentication.py](https://github.com/alphagov/notifications-python-client/blob/master/notifications_python_client/authentication.py) in the GOV.UK Notify Python client library, or the appropriate [PHP] (https://github.com/alphagov/notifications-php-client) or [Java] (https://github.com/alphagov/notifications-java-client) client library. @@ -95,7 +95,7 @@ GOV.UK Notify application-specific claims (these form the JSON Web Token payload } ``` -The header and payload are Base64Url encoded. +The header and payload are Base64Url encoded. The verify signature is created using the HMAC SHA256 hashing algorithm. @@ -103,7 +103,7 @@ The verify signature is created using the HMAC SHA256 hashing algorithm. GOV.UK Notify supports the following client libraries: - * [GOV.UK Notify Python library](https://github.com/alphagov/notifications-python-client) + * [GOV.UK Notify Python library](https://github.com/alphagov/notifications-python-client) * [GOV.UK Notify PHP library] (https://github.com/alphagov/notifications-php-client) * [GOV.UK Notify Java library] (https://github.com/alphagov/notifications-java-client) @@ -113,8 +113,8 @@ These provide example code for calling the API and for creating API tokens. You can use the GOV.UK Notify API to: -* send a [text](#sendtext) or [email](#sendemail) notification -* [retrieve the status of one notification](#get_single_notif) +* send a [text](#sendtext) or [email](#sendemail) notification +* [retrieve the status of one notification](#get_single_notif) * [retrieve the status of all notifications](#get_all_notif)

Send notifications: POST

@@ -128,7 +128,7 @@ POST /notifications/sms ``` { 'to': '+447700900404', - 'template': f6895ff7-86e0-4d38-80ab-c9525856c3ff, + 'template': f6895ff7-86e0-4d38-80ab-c9525856c3ff, 'personalisation': { 'name': 'myname', 'date': '2016' @@ -158,7 +158,7 @@ where: * `to` is a required string that indicates the recipient's phone number or email address * `template` is a required string that indicates the Template ID to use - + **Note:** To access the Template ID from the [GOV.UK Notify](https://www.notifications.service.gov.uk/) web application, go to **Text message templates** or **Email templates** and click on **API info**. * `personalisation` is an optional array that specifies the placeholders and values in your templates @@ -169,11 +169,11 @@ where: The response (status code 201) will be: ``` { - 'data':{ - 'notification': { - 'id':1 - } - } + 'data':{ + 'notification': { + 'id':1 + } + } } ``` @@ -190,31 +190,34 @@ The response (status code 200) will be: ``` { - 'notification': - { - 'status': 'delivered', - 'to': '07515 987 456', - 'template': {'id': '5e427b42-4e98-46f3-a047-32c4a87d26bb', - 'name': 'First template', - 'template_type': 'sms'}, - 'created_at': '2016-04-26T15:29:36.891512+00:00', - 'updated_at': '2016-04-26T15:29:38.724808+00:00', - 'sent_at': '2016-04-26T15:29:37.230976+00:00', - 'job': {'id': 'f9043884-acac-46db-b2ea-f08cd8ec6d67', - 'original_file_name': 'Test run'}, - 'sent_at': '2016-04-26T15:29:37.230976+00:00', - 'id': 'f163deaf-2d3f-4ec6-98fc-f23fa511518f', - 'content_char_count': 490, - 'service': '5cf87313-fddd-4482-a2ea-48e37320efd1', - 'reference': None, - 'sent_by': 'mmg' - } + 'notification': { + 'status': 'delivered', + 'to': '07515 987 456', + 'template': { + 'id': '5e427b42-4e98-46f3-a047-32c4a87d26bb', + 'name': 'First template', + 'template_type': 'sms' + }, + 'created_at': '2016-04-26T15:29:36.891512+00:00', + 'updated_at': '2016-04-26T15:29:38.724808+00:00', + 'sent_at': '2016-04-26T15:29:37.230976+00:00', + 'job': { + 'id': 'f9043884-acac-46db-b2ea-f08cd8ec6d67', + 'original_file_name': 'Test run' + }, + 'sent_at': '2016-04-26T15:29:37.230976+00:00', + 'id': 'f163deaf-2d3f-4ec6-98fc-f23fa511518f', + 'content_char_count': 490, + 'service': '5cf87313-fddd-4482-a2ea-48e37320efd1', + 'reference': None, + 'sent_by': 'mmg' + } } ``` See [below](#fieldsforGET) for explanations of the fields. -To retrieve the status of all notifications: +To retrieve the status of all notifications: ``` GET /notifications ``` @@ -222,54 +225,63 @@ GET /notifications The response (status code 200) will be: ``` -{'notifications': - [{ - 'status': 'delivered', - 'to': '07515 987 456', - 'template': {'id': '5e427b42-4e98-46f3-a047-32c4a87d26bb', - 'name': 'First template', - 'template_type': 'sms'}, - - 'job': {'id': '5cc9d7ae-ceb7-4565-8345-4931d71f8c2e', - 'original_file_name': 'Test run'}, - 'created_at': '2016-04-26T15:30:49.968969+00:00', - 'updated_at': '2016-04-26T15:30:50.853844+00:00', - 'sent_at': '2016-04-26T15:30:50.383634+00:00', - 'id': '04ae9bdc-92aa-4d6c-a0da-48587c03d4c7', - 'content_char_count': 446, - 'service': '5cf87313-fddd-4482-a2ea-48e37320efd1', - 'reference': None, - 'sent_by': 'mmg' - }, - { - 'status': 'delivered', - 'to': '07515 987 456', - 'template': {'id': '5e427b42-4e98-46f3-a047-32c4a87d26bb', - 'name': 'First template', - 'template_type': 'sms'}, - 'job': {'id': 'f9043884-acac-46db-b2ea-f08cd8ec6d67', - 'original_file_name': 'Test run'}, - 'created_at': '2016-04-26T15:29:36.891512+00:00', - 'updated_at': '2016-04-26T15:29:38.724808+00:00', - 'sent_at': '2016-04-26T15:29:37.230976+00:00', - 'id': 'f163deaf-2d3f-4ec6-98fc-f23fa511518f', - 'content_char_count': 490, - 'service': '5cf87313-fddd-4482-a2ea-48e37320efd1', - 'reference': None, - 'sent_by': 'mmg' - }, - ... - ] - 'links': {'last': '/notifications?page=3&template_type=sms&status=delivered', - 'next': '/notifications?page=2&template_type=sms&status=delivered'}, - 'total': 162, - 'page_size': 50 - } +{'notifications': + [{ + 'status': 'delivered', + 'to': '07515 987 456', + 'template': { + 'id': '5e427b42-4e98-46f3-a047-32c4a87d26bb', + 'name': 'First template', + 'template_type': 'sms' + }, + 'job': { + 'id': '5cc9d7ae-ceb7-4565-8345-4931d71f8c2e', + 'original_file_name': 'Test run' + }, + 'created_at': '2016-04-26T15:30:49.968969+00:00', + 'updated_at': '2016-04-26T15:30:50.853844+00:00', + 'sent_at': '2016-04-26T15:30:50.383634+00:00', + 'id': '04ae9bdc-92aa-4d6c-a0da-48587c03d4c7', + 'content_char_count': 446, + 'service': '5cf87313-fddd-4482-a2ea-48e37320efd1', + 'reference': None, + 'sent_by': 'mmg' + }, + { + 'status': 'delivered', + 'to': '07515 987 456', + 'template': { + 'id': '5e427b42-4e98-46f3-a047-32c4a87d26bb', + 'name': 'First template', + 'template_type': 'sms' + }, + 'job': { + 'id': 'f9043884-acac-46db-b2ea-f08cd8ec6d67', + 'original_file_name': 'Test run' + }, + 'created_at': '2016-04-26T15:29:36.891512+00:00', + 'updated_at': '2016-04-26T15:29:38.724808+00:00', + 'sent_at': '2016-04-26T15:29:37.230976+00:00', + 'id': 'f163deaf-2d3f-4ec6-98fc-f23fa511518f', + 'content_char_count': 490, + 'service': '5cf87313-fddd-4482-a2ea-48e37320efd1', + 'reference': None, + 'sent_by': 'mmg' + }, + … + ], + 'links': { + 'last': '/notifications?page=3&template_type=sms&status=delivered', + 'next': '/notifications?page=2&template_type=sms&status=delivered' + }, + 'total': 162, + 'page_size': 50 +} ``` where: -* `status` is the status of the notification; this can be `sending`, `delivered`, or `failed` +* `status` is the status of the notification; this can be `sending`, `delivered`, or `failed` * `to` is the recipient's phone number or email address * `template`: * `id` is the Template ID @@ -280,13 +292,13 @@ where: * `sent_at` is the full timestamp, in Coordinated Universal Time (UTC), at which GOV.UK Notify sent the notification * `job` is empty if you are using the API to send notifications: * `id` is the job ID - * `original_file_name` is the name of the CSV file, if used + * `original_file_name` is the name of the CSV file, if used * `id` is the unique identifier for the process of sending and retrieving one or more notifications * `content_char_count` indicates the full character count of the text notification, including placeholders (populated for text notifications only) * `service` is your Service ID * `reference` is used in the Notifications API so you can ignore it (populated for email notifications only) * `sent_by` is the name of the provider -* `links`: +* `links`: * `last` is the url of the last page of notifications * `next` is the url of the next page of notifications * `total` is the total number of notifications sent by the service using the given template type @@ -326,10 +338,4 @@ Error code | Body | Meaning The GOV.UK Notify API code is open sourced at: -[GOV.UK Notify API](https://github.com/alphagov/notifications-api) - - - - - - +[GOV.UK Notify API](https://github.com/alphagov/notifications-api) diff --git a/requirements.txt b/requirements.txt index ebc4fbe15..a3fbb420e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,8 @@ boto3==1.3.0 Pygments==2.0.2 py-gfm==0.1.2 blinker==1.4 +monotonic==0.3 git+https://github.com/alphagov/notifications-python-client.git@1.0.0#egg=notifications-python-client==1.0.0 -git+https://github.com/alphagov/notifications-utils.git@5.2.1#egg=notifications-utils==5.2.1 +git+https://github.com/alphagov/notifications-utils.git@5.2.3#egg=notifications-utils==5.2.3 diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py index 7ee2de4ff..0dc1ebf45 100644 --- a/tests/app/main/views/test_send.py +++ b/tests/app/main/views/test_send.py @@ -91,7 +91,7 @@ def test_send_test_sms_message( fake_uuid ): - expected_data = {'data': 'phone number\r\n07700 900 762\r\n', 'file_name': 'Test run'} + expected_data = {'data': 'phone number\r\n07700 900 762\r\n', 'file_name': 'Test message'} mocker.patch('app.main.views.send.s3download', return_value='phone number\r\n+4412341234') with app_.test_request_context(): @@ -119,7 +119,7 @@ def test_send_test_email_message( fake_uuid ): - expected_data = {'data': 'email address\r\ntest@user.gov.uk\r\n', 'file_name': 'Test run'} + expected_data = {'data': 'email address\r\ntest@user.gov.uk\r\n', 'file_name': 'Test message'} mocker.patch('app.main.views.send.s3download', return_value='email address\r\ntest@user.gov.uk') with app_.test_request_context(): @@ -149,7 +149,7 @@ def test_send_test_sms_message_with_placeholders( expected_data = { 'data': 'phone number,name\r\n07700 900 762,Jo\r\n', - 'file_name': 'Test run' + 'file_name': 'Test message' } mocker.patch('app.main.views.send.s3download', return_value='phone number\r\n+4412341234')