From f3459847f14cd059342cd74d6f316da556e6d5a1 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Sat, 16 Jan 2016 10:59:16 +0000 Subject: [PATCH 1/5] Move view function into own file, add test --- app/main/__init__.py | 2 +- app/main/views/api_keys.py | 9 +++++++++ app/main/views/index.py | 6 ------ app/templates/main_nav.html | 2 +- tests/app/main/views/test_api_keys.py | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 app/main/views/api_keys.py create mode 100644 tests/app/main/views/test_api_keys.py diff --git a/app/main/__init__.py b/app/main/__init__.py index ff64f5c69..7ce30ff8a 100644 --- a/app/main/__init__.py +++ b/app/main/__init__.py @@ -5,5 +5,5 @@ main = Blueprint('main', __name__) from app.main.views import ( index, sign_in, sign_out, register, two_factor, verify, sms, add_service, code_not_received, jobs, dashboard, templates, service_settings, forgot_password, - new_password, styleguide, user_profile, choose_service + new_password, styleguide, user_profile, choose_service, api_keys ) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py new file mode 100644 index 000000000..0241346a8 --- /dev/null +++ b/app/main/views/api_keys.py @@ -0,0 +1,9 @@ +from flask import render_template +from flask_login import login_required +from app.main import main + + +@main.route("/services//api-keys") +@login_required +def api_keys(service_id): + return render_template('views/api-keys.html', service_id=service_id) diff --git a/app/main/views/index.py b/app/main/views/index.py index 0dba1e396..81dad8693 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -36,9 +36,3 @@ def checkemail(service_id): @login_required def manageusers(service_id): return render_template('views/manage-users.html', service_id=service_id) - - -@main.route("/services//api-keys") -@login_required -def apikeys(service_id): - return render_template('views/api-keys.html', service_id=service_id) diff --git a/app/templates/main_nav.html b/app/templates/main_nav.html index 9594c8596..6cda2b50e 100644 --- a/app/templates/main_nav.html +++ b/app/templates/main_nav.html @@ -9,7 +9,7 @@
  • Templates
    • Manage users
    • diff --git a/tests/app/main/views/test_api_keys.py b/tests/app/main/views/test_api_keys.py new file mode 100644 index 000000000..b32feb64b --- /dev/null +++ b/tests/app/main/views/test_api_keys.py @@ -0,0 +1,14 @@ +from tests.app.main import create_test_user +from flask import url_for + + +def test_should_show_api_keys_and_documentation_page(notifications_admin, + notifications_admin_db, + notify_db_session): + with notifications_admin.test_request_context(): + with notifications_admin.test_client() as client: + user = create_test_user('active') + client.login(user) + response = client.get(url_for('.api_keys', service_id=123)) + + assert response.status_code == 200 From e2021612b4fdaa5b2fdb7667c5253a112b14e616 Mon Sep 17 00:00:00 2001 From: Chris Heathcote Date: Fri, 15 Jan 2016 11:41:31 +0000 Subject: [PATCH 2/5] initial sketch for api docs page --- app/templates/views/api-keys.html | 55 +++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/app/templates/views/api-keys.html b/app/templates/views/api-keys.html index c5615f741..8eaf3d2f0 100644 --- a/app/templates/views/api-keys.html +++ b/app/templates/views/api-keys.html @@ -7,13 +7,62 @@ GOV.UK Notify | API keys and documentation {% block maincolumn_content %} -

      API keys and documentation

      +

      API documentation and key

      -

      Here's where developers can access information about the API and access keys

      +

      How to integrate Notify into your service

      + +

      blah blah blah this is where we tell you how the API works

      + +

      Repositories

      + +

      https://github.com/alphagov/notify-api
      + Notify API

      + +

      A python api client for Notify

      + + +

      Python client

      + +

      blah blah blah this is what to do for Python

      + +
      +

      + here is; + some() { + code.stuff(); + } +

      +
      + +

      + +
      + +

      API key for [service name]

      + +

      API endpoint: https://www.notify.works/api/endpoint

      + + + + + + + + +
      {{ page_footer( back_link=url_for('.dashboard', service_id=service_id), back_link_text='Back to dashboard' ) }} -{% endblock %} +{% endblock %} \ No newline at end of file From c4544eb8332079d294189586d73a1df48c77f040 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Fri, 15 Jan 2016 10:50:10 +0000 Subject: [PATCH 3/5] Add API key component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a component for showing an API key. Usage: ```jinja {{ from 'components/api-key.html' import api_key }} {{ api_key('e1b0751388f3cd0fc9982c701acdb3c2') }} ``` Depending on the user’s browser, it works in three different ways. No Javascript --- The API key is shown on the page. Older browsers with Javascript --- The API key is hidden, and users can click a button to reveal it. Newer browsers that support copying to clipboard without Flash --- As above, but when the key is shown there is a button which copies it to the clipboard. This is acheived by using [this polyfill](https://www.npmjs.com/package/query-command-supported) to reliably detect browser support for the ‘copy’ command. The styling of the component is a bit different to the initial sketch. I think a grey button works better than green. Green feels like it’s going to take you somewhere else. --- app/assets/javascripts/apiKey.js | 58 +++++++++++++++++++ .../stylesheets/components/api-key.scss | 17 ++++++ app/assets/stylesheets/main.scss | 1 + app/templates/components/api-key.html | 5 ++ app/templates/views/styleguide.html | 5 ++ gulpfile.babel.js | 10 ++-- package.json | 3 +- 7 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 app/assets/javascripts/apiKey.js create mode 100644 app/assets/stylesheets/components/api-key.scss create mode 100644 app/templates/components/api-key.html diff --git a/app/assets/javascripts/apiKey.js b/app/assets/javascripts/apiKey.js new file mode 100644 index 000000000..30d87278d --- /dev/null +++ b/app/assets/javascripts/apiKey.js @@ -0,0 +1,58 @@ +(function(Modules) { + "use strict"; + + Modules.ApiKey = function() { + + const states = { + 'initial': ` + + `, + 'keyVisibleBasic': key => ` + ${key} + `, + 'keyVisible': key => ` + ${key} + + `, + 'keyCopied': ` + Copied to clipboard + + ` + }; + + this.copyKey = function(keyElement, callback) { + var selection = window.getSelection ? window.getSelection() : document.selection, + range = document.createRange(); + selection.removeAllRanges(); + range.selectNodeContents(keyElement); + selection.addRange(range); + document.execCommand('copy'); + selection.removeAllRanges(); + callback(); + }; + + this.start = function(component) { + + const $component = $(component).html(states.initial).attr('aria-live', 'polite'), + key = $component.data('key'); + + $component + .on( + 'click', '.api-key-button-show', () => + $component.html( + document.queryCommandSupported('copy') ? + states.keyVisible(key) : states.keyVisibleBasic(key) + ) + ) + .on( + 'click', '.api-key-button-copy', () => + this.copyKey( + $('.api-key-key', component)[0], () => + $component.html(states.keyCopied) + ) + ); + + }; + }; + +})(window.GOVUK.Modules); diff --git a/app/assets/stylesheets/components/api-key.scss b/app/assets/stylesheets/components/api-key.scss new file mode 100644 index 000000000..22c787355 --- /dev/null +++ b/app/assets/stylesheets/components/api-key.scss @@ -0,0 +1,17 @@ +.api-key { + + &-key { + font-family: monospace; + display: block; + margin-bottom: 10px; + } + + &-button-show { + @include button($grey-3); + } + + &-button-copy { + @include button($grey-3); + } + +} diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss index 2882baaa7..59b450ec7 100644 --- a/app/assets/stylesheets/main.scss +++ b/app/assets/stylesheets/main.scss @@ -45,6 +45,7 @@ @import 'components/management-navigation'; @import 'components/dropdown'; @import 'components/email-message'; +@import 'components/api-key'; @import 'views/job'; diff --git a/app/templates/components/api-key.html b/app/templates/components/api-key.html new file mode 100644 index 000000000..014136bc4 --- /dev/null +++ b/app/templates/components/api-key.html @@ -0,0 +1,5 @@ +{% macro api_key(key) %} +
      + {{ key }} +
      +{% endmacro %} diff --git a/app/templates/views/styleguide.html b/app/templates/views/styleguide.html index 0caefd563..2231b1173 100644 --- a/app/templates/views/styleguide.html +++ b/app/templates/views/styleguide.html @@ -7,6 +7,7 @@ {% from "components/sms-message.html" import sms_message %} {% from "components/table.html" import mapping_table, list_table, row, field %} {% from "components/textbox.html" import textbox %} +{% from "components/api-key.html" import api_key %} {% block page_title %} Styleguide – GOV.UK Notify @@ -152,4 +153,8 @@ {{ textbox(form.password) }} {{ textbox(form.message, highlight_tags=True) }} +

      API key

      + + {{ api_key('d30512af92e1386d63b90e5973b49a10') }} + {% endblock %} diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 6c336ce97..5207d6138 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -34,17 +34,19 @@ gulp.task('javascripts', () => gulp .src([ paths.npm + 'govuk_frontend_toolkit/javascripts/govuk/modules.js', paths.npm + 'govuk_frontend_toolkit/javascripts/govuk/selection-buttons.js', - paths.src + 'javascripts/highlightTags.js', + paths.src + 'javascripts/apiKey.js', paths.src + 'javascripts/dropdown.js', + paths.src + 'javascripts/highlightTags.js', paths.src + 'javascripts/main.js' ]) .pipe(plugins.babel({ presets: ['es2015'] })) .pipe(plugins.uglify()) - .pipe(plugins.addSrc.prepend( - './node_modules/jquery/dist/jquery.min.js' - )) + .pipe(plugins.addSrc.prepend([ + paths.npm + 'jquery/dist/jquery.min.js', + paths.npm + 'query-command-supported/dist/queryCommandSupported.min.js' + ])) .pipe(plugins.concat('all.js')) .pipe(gulp.dest(paths.dist + 'javascripts/')) ); diff --git a/package.json b/package.json index 582ad19c2..3f168c228 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "gulp-load-plugins": "1.1.0", "gulp-sass": "2.1.1", "gulp-uglify": "1.5.1", - "jquery": "1.11.2" + "jquery": "1.11.2", + "query-command-supported": "1.0.0" } } From e5585512c82f2554c19c562f48dd9c49732f4894 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Fri, 15 Jan 2016 20:03:00 +0000 Subject: [PATCH 4/5] Integrate API key pattern into existing page --- app/templates/views/api-keys.html | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/app/templates/views/api-keys.html b/app/templates/views/api-keys.html index 8eaf3d2f0..7243753c9 100644 --- a/app/templates/views/api-keys.html +++ b/app/templates/views/api-keys.html @@ -1,5 +1,6 @@ {% extends "withnav_template.html" %} {% from "components/page-footer.html" import page_footer %} +{% from "components/api-key.html" import api_key %} {% block page_title %} GOV.UK Notify | API keys and documentation @@ -9,16 +10,16 @@ GOV.UK Notify | API keys and documentation

      API documentation and key

      -

      How to integrate Notify into your service

      +

      How to integrate GOV.UK Notify into your service

      blah blah blah this is where we tell you how the API works

      Repositories

      -

      https://github.com/alphagov/notify-api
      - Notify API

      +

      https://github.com/alphagov/notifications-api
      + GOV.UK Notify API

      -

      A python api client for Notify

      +

      A python api client for GOV.UK Notify

      Python client

      @@ -42,27 +43,11 @@ GOV.UK Notify | API keys and documentation

      API endpoint: https://www.notify.works/api/endpoint

      - - - - - - - -
      + {{ api_key('d30512af92e1386d63b90e5973b49a10') }} {{ page_footer( back_link=url_for('.dashboard', service_id=service_id), back_link_text='Back to dashboard' ) }} -{% endblock %} \ No newline at end of file +{% endblock %} From 0df399f11c550bfea0bb6d1d175c4666e2f174e2 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Fri, 15 Jan 2016 20:14:05 +0000 Subject: [PATCH 5/5] =?UTF-8?q?Remove=20parts=20of=20the=20page=20that=20a?= =?UTF-8?q?ren=E2=80=99t=20in=20the=20story?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.pivotaltracker.com/story/show/111614524 Not clear if we are going to have code examples on this page, or if the documentation will be hosted somewhere else. It seems unecessary to put documentation behind a log in, so I’d lean towards this page just being links. --- app/templates/views/api-keys.html | 59 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/app/templates/views/api-keys.html b/app/templates/views/api-keys.html index 7243753c9..13122838b 100644 --- a/app/templates/views/api-keys.html +++ b/app/templates/views/api-keys.html @@ -3,48 +3,51 @@ {% from "components/api-key.html" import api_key %} {% block page_title %} -GOV.UK Notify | API keys and documentation + GOV.UK Notify | API keys and documentation {% endblock %} {% block maincolumn_content %} -

      API documentation and key

      +
      +
      -

      How to integrate GOV.UK Notify into your service

      +

      + API keys and documentation +

      -

      blah blah blah this is where we tell you how the API works

      +

      + How to integrate GOV.UK Notify into your service +

      -

      Repositories

      +

      + blah blah blah this is where we tell you how the API works +

      -

      https://github.com/alphagov/notifications-api
      - GOV.UK Notify API

      - -

      A python api client for GOV.UK Notify

      +

      Repositories

      -

      Python client

      -

      blah blah blah this is what to do for Python

      +

      + GOV.UK Notify API +

      -
      -

      - here is; - some() { - code.stuff(); - } -

      +

      + GOV.UK Notify Python client +

      + +

      API key for [service name]

      + + {{ api_key('d30512af92e1386d63b90e5973b49a10') }} + +

      API endpoint

      + +

      + https://www.notify.works/api/endpoint +

      + +
      -

      - -
      - -

      API key for [service name]

      - -

      API endpoint: https://www.notify.works/api/endpoint

      - - {{ api_key('d30512af92e1386d63b90e5973b49a10') }} - {{ page_footer( back_link=url_for('.dashboard', service_id=service_id), back_link_text='Back to dashboard'