Add confirm loop

For pages where
- we want you to be sure that you want to do what you’re about to do
- we want to be sure it’s you trying to do the thing

This adds a page that asks the user to confirm their password.
This commit is contained in:
Chris Hill-Scott
2016-01-07 16:24:43 +00:00
parent 3989d1b576
commit 0b62d1e755
12 changed files with 227 additions and 82 deletions

View File

@@ -20,7 +20,7 @@
}
&-hint {
@include core-16;
@include core-19;
margin-top: 5px;
}

View File

@@ -12,7 +12,8 @@
.button {}
.button-destructive {
@include button($error-colour)
@include button($error-colour);
padding: 0.52632em 0.78947em 0.26316em 0.78947em;
}
}

View File

@@ -1,4 +1,4 @@
from flask import render_template, redirect, request, url_for
from flask import render_template, redirect, request, url_for, abort
from flask_login import login_required
from app.main import main
@@ -25,6 +25,18 @@ def name():
'views/service-settings/name.html',
service=service
)
elif request.method == 'POST':
return redirect(url_for('.confirm_name_change'))
@main.route("/service-settings/name/confirm", methods=['GET', 'POST'])
def confirm_name_change():
if request.method == 'GET':
return render_template(
'views/service-settings/confirm.html',
heading='Rename service',
submit_button_text='Confirm'
)
elif request.method == 'POST':
return redirect(url_for('.service_settings'))
@@ -47,6 +59,19 @@ def status():
'views/service-settings/status.html',
service=service
)
elif request.method == 'POST':
return redirect(url_for('.confirm_status_change'))
@main.route("/service-settings/status/confirm", methods=['GET', 'POST'])
def confirm_status_change():
if request.method == 'GET':
return render_template(
'views/service-settings/confirm.html',
heading='Turn off outgoing messages',
submit_button_text='Confirm',
destructive=True
)
elif request.method == 'POST':
return redirect(url_for('.service_settings'))
@@ -59,4 +84,17 @@ def delete():
service=service
)
elif request.method == 'POST':
return redirect(url_for('.index'))
return redirect(url_for('.confirm_delete'))
@main.route("/service-settings/delete/confirm", methods=['GET', 'POST'])
def confirm_delete():
if request.method == 'GET':
return render_template(
'views/service-settings/confirm.html',
heading='Delete service',
submit_button_text='Confirm',
destructive=True
)
elif request.method == 'POST':
return redirect(url_for('.dashboard'))

View File

@@ -1,11 +0,0 @@
{% macro list(items) %}
{% if items %}
<ul class="list list-bullet">
{% for item in items %}
<li>
{{ item }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}

View File

@@ -1,8 +1,8 @@
{% macro textbox(name, label, value='', small=True, highlight_tags=False) %}
{% macro textbox(name, label, value='', small=True, highlight_tags=False, password=False) %}
<div class="form-group">
<label class="form-label" for="{{ name }}">{{ label }}</label>
{% if small %}
<input class="form-control" id="{{ name }}" name="{{ name }}" type="text" value="{{ value }}">
<input class="form-control" id="{{ name }}" name="{{ name }}" type="{{ 'password' if password else 'text' }}" value="{{ value }}">
{% else %}
<textarea
class="form-control {% if highlight_tags %}textbox-highlight-textbox{% endif %}"

View File

@@ -2,38 +2,38 @@
{% from "components/browse-list.html" import browse_list %}
{% block page_title %}
GOV.UK Notify | Service settings
GOV.UK Notify | Service settings
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-xlarge">Service settings</h1>
<h1 class="heading-xlarge">Service settings</h1>
{{ browse_list([
{
'title': 'Rename service',
'link': url_for('.name'),
'hint': 'Your service is named {}'.format(service.name)
},
{
'title': 'Make service live',
'link': url_for('.request_to_go_live'),
'hint': 'A live service can send messages to anyone',
} if not service.live else {
},
{
'title': 'Stop sending messages',
'link': url_for('.status')
} if service.active else {
'title': 'Unsuspend service',
'link': url_for('.status')
},
{
'title': 'Delete everything',
'link': url_for('.delete'),
'hint': '',
'destructive': True
},
]) }}
{{ browse_list([
{
'title': 'Rename service',
'link': url_for('.name'),
'hint': 'Your service is called {}'.format(service.name)
},
{
'title': 'Request to make service live',
'link': url_for('.request_to_go_live'),
'hint': 'A live service can send messages to any phone number or email address',
} if not service.live else {
},
{
'title': 'Turn off outgoing messages',
'link': url_for('.status'),
'destructive': True
} if service.active else {
'title': 'Desuspend service',
'link': url_for('.status')
},
{
'title': 'Delete service',
'link': url_for('.delete'),
'destructive': True
},
]) }}
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "withnav_template.html" %}
{% from "components/textbox.html" import textbox %}
{% from "components/submit-form.html" import submit_form %}
{% block page_title %}
GOV.UK Notify | Service settings
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-xlarge">{{ heading }}</h1>
<div class="grid-row">
<div class="column-three-quarters">
<form method="post">
{{ textbox('new_name', 'Enter your password', password=True) }}
{{ submit_form(
submit_button_text,
destructive=destructive,
back_link=url_for('.service_settings')
) }}
</form>
</div>
</div>
{% endblock %}

View File

@@ -7,16 +7,37 @@
{% block maincolumn_content %}
<h1 class="heading-xlarge">Delete this service</h1>
<div class="grid-row">
<div class="column-three-quarters">
<h1 class="heading-xlarge">Delete service</h1>
<p>
All will be lost.
</p>
<p>
This cant be undone. You will lose:
</p>
<form method="post">
{{ submit_form('Delete', destructive=True) }}
</form>
<ul class="list list-bullet">
<li>
any data youve uploaded messages
</li>
<li>
any templates youve created
</li>
<li>
the history of
</li>
<li>
API keys
</li>
</ul>
<p><a href="{{ url_for('.service_settings') }}">Back to service settings</a></p>
<form method="post">
{{ submit_form(
'Yes, delete {}'.format(service.name),
destructive=True,
back_link=url_for('.service_settings')
) }}
</form>
</div>
</div>
{% endblock %}

View File

@@ -8,15 +8,23 @@ GOV.UK Notify | Service settings
{% block maincolumn_content %}
<h1 class="heading-xlarge">Rename your service</h1>
<div class="grid-row">
<div class="column-three-quarters">
<form method="post">
{{ textbox('new_name', 'New name', value=service.name) }}
{{ submit_form('Save') }}
</form>
<p><a href="{{ url_for('.service_settings') }}">Back to service settings</a></p>
<h1 class="heading-xlarge">Rename service</h1>
<p>
Users will see this name where?
</p>
<form method="post">
{{ textbox('new_name', 'New name', value=service.name) }}
{{ submit_form(
'Save',
back_link=url_for('.service_settings')
) }}
</form>
</div>
</div>
{% endblock %}

View File

@@ -1,6 +1,5 @@
{% extends "withnav_template.html" %}
{% from "components/submit-form.html" import submit_form %}
{% from "components/list.html" import list %}
{% block page_title %}
GOV.UK Notify | Service settings
@@ -8,26 +7,42 @@ GOV.UK Notify | Service settings
{% block maincolumn_content %}
<h1 class="heading-xlarge">Make your service live</h1>
<h1 class="heading-xlarge">Request to make service live</h1>
<div class="grid-row">
<div class="column-two-thirds">
<div class="column-three-quarters">
<p>
Before you can send messages to anyone, you need to:
A live service can send messages to any phone number or email address.
</p>
{{ list([
"Have spoken to someone",
"Have permission from someone else",
"etc."
]) }}
<p>
First you need to:
</p>
<ul class="list list-bullet">
<li>
have spoken to someone
</li>
<li>
have permission from someone else
</li>
<li>
etc.
</li>
</ul>
<p>
It takes a few working days for your request to be approved.
</p>
<form method="post">
{{ submit_form("Request to go live") }}
{{ submit_form(
'Request to make service live',
back_link=url_for('.service_settings')
) }}
</form>
<p><a href="{{ url_for('.service_settings') }}">Back to service settings</a></p>
</div>
</div>

View File

@@ -7,24 +7,28 @@ GOV.UK Notify | Service settings
{% block maincolumn_content %}
<h1 class="heading-xlarge">Turn off outgoing messages</h1>
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Suspend your service</h1>
<div class="column-three-quarters">
<p>
Suspending a service means it wont send messages. Any messages that are
already queued will still be sent.
Youll still be able to send messages to yourself by uploading a CSV
file.
</p>
<p>
You can undo this at any time.
You can start sending messages again when youre ready.
</p>
<form method="post">
{{ submit_form('Suspend') }}
{{ submit_form(
'Turn off outgoing messages',
destructive=True,
back_link=url_for('.service_settings')
) }}
</form>
<p><a href="{{ url_for('.service_settings') }}">Back to service settings</a></p>
</div>
</div>

View File

@@ -9,7 +9,7 @@ def test_should_show_service_name(notifications_admin):
response = notifications_admin.test_client().get('/service-settings/name')
assert response.status_code == 200
assert 'Service name' in response.get_data(as_text=True)
assert 'Rename service' in response.get_data(as_text=True)
def test_should_redirect_after_change_service_name(notifications_admin):
@@ -19,11 +19,25 @@ def test_should_redirect_after_change_service_name(notifications_admin):
assert 'http://localhost/service-settings' == response.location
def test_should_show_service_name_confirmation(notifications_admin):
response = notifications_admin.test_client().get('/service-settings/name/confirm')
assert response.status_code == 200
assert 'Rename service' in response.get_data(as_text=True)
def test_should_redirect_after_service_name_confirmation(notifications_admin):
response = notifications_admin.test_client().post('/service-settings/name/confirm')
assert response.status_code == 302
assert 'http://localhost/service-settings' == response.location
def test_should_show_request_to_go_live(notifications_admin):
response = notifications_admin.test_client().get('/service-settings/request-to-go-live')
assert response.status_code == 200
assert 'Request to go live' in response.get_data(as_text=True)
assert 'Request to make service live' in response.get_data(as_text=True)
def test_should_redirect_after_request_to_go_live(notifications_admin):
@@ -37,12 +51,26 @@ def test_should_show_status_page(notifications_admin):
response = notifications_admin.test_client().get('/service-settings/status')
assert response.status_code == 200
assert 'Suspend your service' in response.get_data(as_text=True)
assert 'Turn off outgoing messages' in response.get_data(as_text=True)
def test_should_show_redirect_after_status_change(notifications_admin):
response = notifications_admin.test_client().post('/service-settings/status')
assert response.status_code == 302
assert 'http://localhost/service-settings/status/confirm' == response.location
def test_should_show_status_confirmation(notifications_admin):
response = notifications_admin.test_client().get('/service-settings/status/confirm')
assert response.status_code == 200
assert 'Turn off outgoing messages' in response.get_data(as_text=True)
def test_should_redirect_after_status_confirmation(notifications_admin):
response = notifications_admin.test_client().post('/service-settings/status/confirm')
assert response.status_code == 302
assert 'http://localhost/service-settings' == response.location
@@ -58,4 +86,18 @@ def test_should_show_redirect_after_deleting_service(notifications_admin):
response = notifications_admin.test_client().post('/service-settings/delete')
assert response.status_code == 302
assert 'http://localhost/' == response.location
assert 'http://localhost/service-settings/delete/confirm' == response.location
def test_should_show_delete_confirmation(notifications_admin):
response = notifications_admin.test_client().get('/service-settings/delete/confirm')
assert response.status_code == 200
assert 'Delete service' in response.get_data(as_text=True)
def test_should_redirect_delete_confirmation(notifications_admin):
response = notifications_admin.test_client().post('/service-settings/delete/confirm')
assert response.status_code == 302
assert 'http://localhost/dashboard' == response.location