diff --git a/app/assets/stylesheets/components/table.scss b/app/assets/stylesheets/components/table.scss index 79f5eae88..4342891e0 100644 --- a/app/assets/stylesheets/components/table.scss +++ b/app/assets/stylesheets/components/table.scss @@ -111,7 +111,12 @@ } -.table-field-heading { +.table-field-headings, +.table-field-headings-visible { + + th { + @include bold-19; + } .dashboard-table &-first { width: 52.5%; diff --git a/app/main/forms.py b/app/main/forms.py index 31ff09737..1c728a2b5 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -12,12 +12,14 @@ from wtforms import ( FileField, BooleanField, HiddenField, - IntegerField + IntegerField, + RadioField ) from wtforms.fields.html5 import EmailField, TelField from wtforms.validators import (DataRequired, Email, Length, Regexp) from app.main.validators import (Blacklist, CsvFileValidator, ValidEmailDomainRegex, NoCommasInPlaceHolders) +from app.notify_client.api_key_api_client import KEY_TYPE_NORMAL, KEY_TYPE_TEST, KEY_TYPE_TEAM def email_address(label='Email address'): @@ -291,6 +293,18 @@ class CreateKeyForm(Form): self.existing_key_names = [x.lower() for x in existing_key_names] super(CreateKeyForm, self).__init__(*args, **kwargs) + key_type = RadioField( + 'What should Notify do when you use this key?', + choices=[ + (KEY_TYPE_NORMAL, 'Send messages to anyone'), + (KEY_TYPE_TEST, 'Simulate sending messages to anyone'), + (KEY_TYPE_TEAM, 'Only send messages to members of your team') + ], + validators=[ + DataRequired() + ] + ) + key_name = StringField(u'Description of key', validators=[ DataRequired(message='You need to give the key a name') ]) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index aad602179..9dc1465f0 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -25,12 +25,16 @@ def create_api_key(service_id): ] form = CreateKeyForm(key_names) if form.validate_on_submit(): - secret = api_key_api_client.create_api_key(service_id=service_id, key_name=form.key_name.data) + secret = api_key_api_client.create_api_key( + service_id=service_id, + key_name=form.key_name.data, + key_type=form.key_type.data + ) return render_template('views/api-keys/show.html', secret=secret, key_name=form.key_name.data) return render_template( 'views/api-keys/create.html', - key_name=form.key_name + form=form ) diff --git a/app/notify_client/api_key_api_client.py b/app/notify_client/api_key_api_client.py index 1e67e34df..797678541 100644 --- a/app/notify_client/api_key_api_client.py +++ b/app/notify_client/api_key_api_client.py @@ -5,6 +5,7 @@ from app.notify_client import _attach_current_user # must match key types in notifications-api/app/models.py KEY_TYPE_NORMAL = 'normal' KEY_TYPE_TEAM = 'team' +KEY_TYPE_TEST = 'test' class ApiKeyApiClient(BaseAPIClient): @@ -24,10 +25,10 @@ class ApiKeyApiClient(BaseAPIClient): else: return self.get(url='/service/{}/api-keys'.format(service_id)) - def create_api_key(self, service_id, key_name): + def create_api_key(self, service_id, key_name, key_type): data = { 'name': key_name, - 'key_type': KEY_TYPE_NORMAL + 'key_type': key_type } _attach_current_user(data) key = self.post(url='/service/{}/api-key'.format(service_id), data=data) diff --git a/app/templates/components/radios.html b/app/templates/components/radios.html new file mode 100644 index 000000000..88beb1220 --- /dev/null +++ b/app/templates/components/radios.html @@ -0,0 +1,23 @@ +{% macro radios( + field, + hint=None +) %} +
+
+ + {{ field.label }} + {% if field.errors %} + + {{ field.errors[0] }} + + {% endif %} + + {% for option in field %} + + {% endfor %} +
+
+{% endmacro %} diff --git a/app/templates/main_nav.html b/app/templates/main_nav.html index 1fdfb461c..f812e1977 100644 --- a/app/templates/main_nav.html +++ b/app/templates/main_nav.html @@ -58,7 +58,7 @@
  • Team members
  • {% endif %} {% if current_user.has_permissions(['manage_api_keys']) %} -
  • API keys
  • +
  • API integration
  • {% endif %} diff --git a/app/templates/views/api-keys.html b/app/templates/views/api-keys.html index e44d5a718..34dac7304 100644 --- a/app/templates/views/api-keys.html +++ b/app/templates/views/api-keys.html @@ -11,7 +11,7 @@

    - API keys + API integration

    @@ -23,15 +23,29 @@ keys, empty_message="You haven’t created any API keys yet", caption="API keys", - caption_visible=False, - field_headings=['Key name', hidden_field_heading('Action')] + caption_visible=false, + field_headings=[ + 'API keys', + hidden_field_heading('Action') + ], ) %} {% call field() %} - {{ item.name }} +
    + {{ item.name }} + + {% if item.key_type == 'normal' %} + Normal + {% elif item.key_type == 'team' %} + Only sends to team members + {% elif item.key_type == 'test' %} + Simulates sending messages + {% endif %} + +
    {% endcall %} {% if item.expiry_date %} - {% call field(align='right', status='default') %} - Revoked {{ item.expiry_date|format_datetime }} + {% call field(align='right') %} + Revoked {{ item.expiry_date|format_datetime_short }} {% endcall %} {% else %} {% call field(align='right', status='error') %} @@ -44,10 +58,11 @@ {{ api_key(current_service.id, "Service ID", thing="service ID") }}
    +

    Documentation

    - API usage is described in the - - API documentation. + See the + + API documentation for clients and specfications.

    {% endblock %} diff --git a/app/templates/views/api-keys/create.html b/app/templates/views/api-keys/create.html index 1be4bf326..474475618 100644 --- a/app/templates/views/api-keys/create.html +++ b/app/templates/views/api-keys/create.html @@ -1,6 +1,7 @@ {% extends "withnav_template.html" %} {% from "components/page-footer.html" import page_footer %} {% from "components/textbox.html" import textbox %} +{% from "components/radios.html" import radios %} {% block page_title %} Add a new API key – GOV.UK Notify @@ -9,11 +10,12 @@ {% block maincolumn_content %}

    - Add a new API key + Create an API key

    - {{ textbox(key_name, hint='eg CRM application') }} + {{ radios(form.key_type) }} + {{ textbox(form.key_name, label='Name for this key') }} {{ page_footer('Continue') }}
    diff --git a/tests/app/main/test_create_api_key_form.py b/tests/app/main/test_create_api_key_form.py index c13fe9fe3..498edc504 100644 --- a/tests/app/main/test_create_api_key_form.py +++ b/tests/app/main/test_create_api_key_form.py @@ -1,3 +1,5 @@ +import pytest + from werkzeug.datastructures import MultiDict from app.main.forms import CreateKeyForm @@ -11,4 +13,20 @@ def test_return_validation_error_when_key_name_exists(app_): form = CreateKeyForm(_get_names(), formdata=MultiDict([('key_name', 'Some key')])) form.validate() - assert {'key_name': ['A key with this name already exists']} == form.errors + assert form.errors['key_name'] == ['A key with this name already exists'] + + +@pytest.mark.parametrize( + 'key_type, expected_error', [ + ('', 'This field is required.'), + ('invalid', 'Not a valid choice') + ] +) +def test_return_validation_error_when_key_type_not_chosen(app_, key_type, expected_error): + + with app_.test_request_context(): + form = CreateKeyForm( + [], + formdata=MultiDict([('key_name', 'Some key'), ('key_type', key_type)])) + form.validate() + assert form.errors['key_type'] == [expected_error] diff --git a/tests/app/main/views/test_api_keys.py b/tests/app/main/views/test_api_keys.py index a1807a380..1b2561566 100644 --- a/tests/app/main/views/test_api_keys.py +++ b/tests/app/main/views/test_api_keys.py @@ -39,7 +39,7 @@ def test_should_show_api_keys_page(app_, resp_data = response.get_data(as_text=True) assert 'some key name' in resp_data assert 'another key name' in resp_data - assert 'Revoked Thursday 01 January 1970 at 01:00' in resp_data + assert 'Revoked 1 January at 01:00' in resp_data mock_get_api_keys.assert_called_once_with(service_id=fake_uuid) @@ -72,8 +72,13 @@ def test_should_create_api_key_with_type_normal(app_, with app_.test_request_context(), app_.test_client() as client: client.login(api_user_active) - response = client.post(url_for('main.create_api_key', service_id=service_id), - data={'key_name': 'some default key name'}) + response = client.post( + url_for('main.create_api_key', service_id=service_id), + data={ + 'key_name': 'some default key name', + 'key_type': 'normal' + } + ) assert response.status_code == 200 assert 'some default key name' in response.get_data(as_text=True)