mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-05 10:53:28 -05:00
Merge pull request #187 from alphagov/invite-users
Add pages to invite, edit, and delete users
This commit is contained in:
@@ -155,7 +155,7 @@ def useful_headers_after_request(response):
|
||||
response.headers.add('X-Content-Type-Options', 'nosniff')
|
||||
response.headers.add('X-XSS-Protection', '1; mode=block')
|
||||
response.headers.add('Content-Security-Policy',
|
||||
"default-src 'self' 'unsafe-inline'; font-src 'self' data:;") # noqa
|
||||
"default-src 'self' 'unsafe-inline'; font-src 'self' data:; img-src 'self' data:;") # noqa
|
||||
if 'Cache-Control' in response.headers:
|
||||
del response.headers['Cache-Control']
|
||||
response.headers.add(
|
||||
|
||||
BIN
app/assets/images/tick-white.png
Normal file
BIN
app/assets/images/tick-white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 622 B |
BIN
app/assets/images/tick.png
Normal file
BIN
app/assets/images/tick.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 834 B |
BIN
app/assets/images/tick.psd
Normal file
BIN
app/assets/images/tick.psd
Normal file
Binary file not shown.
@@ -3,22 +3,20 @@
|
||||
|
||||
Modules.FileUpload = function() {
|
||||
|
||||
let $field, $button, $filename;
|
||||
let $field;
|
||||
|
||||
this.update = function() {
|
||||
this.submit = function() {
|
||||
|
||||
$filename.text($field.val().split('\\').pop());
|
||||
$field.parents('form').trigger('submit');
|
||||
|
||||
};
|
||||
|
||||
this.start = function(component) {
|
||||
|
||||
$field = $('.file-upload-field', component);
|
||||
$button = $('.file-upload-button', component);
|
||||
$filename = $('.file-upload-filename', component);
|
||||
|
||||
// Need to put the event on the container, not the input for it to work properly
|
||||
$(component).on('change', '.file-upload-field', this.update);
|
||||
$(component).on('change', '.file-upload-field', this.submit);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -66,3 +66,16 @@ a {
|
||||
font-family: monospace;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.inline {
|
||||
|
||||
.block-label {
|
||||
|
||||
@include media(tablet) {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,19 +16,13 @@
|
||||
|
||||
.banner-with-tick,
|
||||
.banner-default-with-tick {
|
||||
|
||||
@extend %banner;
|
||||
padding: $gutter-half ($gutter + $gutter-half);
|
||||
|
||||
&:before {
|
||||
@include core-24;
|
||||
content: '✔';
|
||||
position: absolute;
|
||||
top: $gutter-half;
|
||||
left: $gutter-half;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
background-image: file-url('tick-white.png');
|
||||
background-size: 19px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: $gutter-half $gutter-half;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.banner-dangerous {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
}
|
||||
|
||||
&-button {
|
||||
@include button($panel-colour);
|
||||
@include button($button-colour);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
&-delete-link {
|
||||
|
||||
line-height: 40px;
|
||||
padding: 0 0 0 5px;
|
||||
padding: 1px 0 0 15px;
|
||||
|
||||
a {
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
margin: 40px 0 5px 0;
|
||||
}
|
||||
|
||||
.table-field-headings {
|
||||
th {
|
||||
padding: 0 0 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
%table-field,
|
||||
.table-field {
|
||||
|
||||
@@ -36,6 +42,19 @@
|
||||
|
||||
}
|
||||
|
||||
&-yes,
|
||||
&-no {
|
||||
display: block;
|
||||
text-indent: -999em;
|
||||
background-size: 19px 19px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
}
|
||||
|
||||
&-yes {
|
||||
background-image: file-url('tick.png');
|
||||
}
|
||||
|
||||
&-missing {
|
||||
color: $error-colour;
|
||||
font-weight: bold;
|
||||
@@ -77,4 +96,5 @@
|
||||
margin-top: -20px;
|
||||
border-bottom: 1px solid $border-colour;
|
||||
padding-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
36
app/assets/stylesheets/components/yes-no.scss
Normal file
36
app/assets/stylesheets/components/yes-no.scss
Normal file
@@ -0,0 +1,36 @@
|
||||
.yes-no-wrapper {
|
||||
border-bottom: 1px solid $border-colour;
|
||||
margin: 0 0 $gutter 0;
|
||||
}
|
||||
|
||||
.yes-no {
|
||||
|
||||
border-top: 1px solid $border-colour;
|
||||
padding: 10px 0;
|
||||
|
||||
&-label {
|
||||
padding-top: 19px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
&-fields {
|
||||
|
||||
text-align: right;
|
||||
|
||||
.block-label {
|
||||
|
||||
@include media(tablet) {
|
||||
|
||||
margin-bottom: 0;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,6 +47,7 @@ $path: '/static/images/';
|
||||
@import 'components/browse-list';
|
||||
@import 'components/email-message';
|
||||
@import 'components/api-key';
|
||||
@import 'components/yes-no';
|
||||
|
||||
@import 'views/job';
|
||||
@import 'views/edit-template';
|
||||
|
||||
@@ -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, api_keys
|
||||
new_password, styleguide, user_profile, choose_service, api_keys, manage_users
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import url_for
|
||||
from flask import url_for, abort
|
||||
from app import notifications_api_client
|
||||
from notifications_python_client.errors import HTTPError
|
||||
from app.utils import BrowsableItem
|
||||
from notifications_python_client.errors import HTTPError
|
||||
|
||||
|
||||
def insert_new_service(service_name, user_id):
|
||||
@@ -29,7 +29,9 @@ def get_service_by_id(id_):
|
||||
|
||||
def get_service_by_id_or_404(id_):
|
||||
try:
|
||||
return get_service_by_id(id_)
|
||||
return notifications_api_client.get_service(id_)['data']
|
||||
except KeyError:
|
||||
abort(404)
|
||||
except HTTPError as e:
|
||||
if e.status_code == 404:
|
||||
abort(404)
|
||||
|
||||
@@ -21,10 +21,10 @@ from app.utils import (
|
||||
)
|
||||
|
||||
|
||||
def email_address():
|
||||
def email_address(label='Email address'):
|
||||
gov_uk_email \
|
||||
= "(^[^@^\\s]+@[^@^\\.^\\s]+(\\.[^@^\\.^\\s]*)*.gov.uk)"
|
||||
return EmailField('Email address', validators=[
|
||||
return EmailField(label, validators=[
|
||||
Length(min=5, max=255),
|
||||
DataRequired(message='Email cannot be empty'),
|
||||
Email(message='Enter a valid email address'),
|
||||
@@ -96,6 +96,10 @@ class RegisterUserForm(Form):
|
||||
password = password()
|
||||
|
||||
|
||||
class InviteUserForm(Form):
|
||||
email_address = email_address('Their email address')
|
||||
|
||||
|
||||
class TwoFactorForm(Form):
|
||||
def __init__(self, validate_code_func, *args, **kwargs):
|
||||
'''
|
||||
|
||||
@@ -34,63 +34,3 @@ def send_email(service_id):
|
||||
@login_required
|
||||
def check_email(service_id):
|
||||
return render_template('views/check-email.html')
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/manage-users")
|
||||
@login_required
|
||||
def manage_users(service_id):
|
||||
users = [
|
||||
{
|
||||
'name': 'Henry Hadlow',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': False,
|
||||
'permission_manage_api_keys': False
|
||||
},
|
||||
|
||||
{
|
||||
'name': 'Pete Herlihy',
|
||||
'permission_send_messages': False,
|
||||
'permission_manage_service': False,
|
||||
'permission_manage_api_keys': False,
|
||||
},
|
||||
{
|
||||
'name': 'Chris Hill-Scott',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': True,
|
||||
'permission_manage_api_keys': True
|
||||
},
|
||||
{
|
||||
'name': 'Martyn Inglis',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': True,
|
||||
'permission_manage_api_keys': True
|
||||
}
|
||||
]
|
||||
invited_users = [
|
||||
{
|
||||
'email_localpart': 'caley.smolska',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': False,
|
||||
'permission_manage_api_keys': False
|
||||
},
|
||||
|
||||
{
|
||||
'email_localpart': 'ash.stephens',
|
||||
'permission_send_messages': False,
|
||||
'permission_manage_service': False,
|
||||
'permission_manage_api_keys': False
|
||||
},
|
||||
{
|
||||
'email_localpart': 'nicholas.staples',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': True,
|
||||
'permission_manage_api_keys': True
|
||||
},
|
||||
{
|
||||
'email_localpart': 'adam.shimali',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': True,
|
||||
'permission_manage_api_keys': True
|
||||
}
|
||||
]
|
||||
return render_template('views/manage-users.html', service_id=service_id, users=users, invited_users=invited_users)
|
||||
|
||||
96
app/main/views/manage_users.py
Normal file
96
app/main/views/manage_users.py
Normal file
@@ -0,0 +1,96 @@
|
||||
from flask import (
|
||||
request,
|
||||
render_template,
|
||||
redirect,
|
||||
abort,
|
||||
url_for,
|
||||
flash
|
||||
)
|
||||
|
||||
from flask_login import login_required, current_user
|
||||
|
||||
from app.main import main
|
||||
from app.main.dao import users_dao
|
||||
from app.main.forms import InviteUserForm
|
||||
from app.main.dao.services_dao import get_service_by_id_or_404
|
||||
from app import user_api_client
|
||||
|
||||
fake_users = [
|
||||
{
|
||||
'name': '',
|
||||
'permission_send_messages': True,
|
||||
'permission_manage_service': True,
|
||||
'permission_manage_api_keys': True,
|
||||
'active': True
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/users")
|
||||
@login_required
|
||||
def manage_users(service_id):
|
||||
return render_template(
|
||||
'views/manage-users.html',
|
||||
service_id=service_id,
|
||||
users=fake_users,
|
||||
current_user=current_user,
|
||||
invited_users=[]
|
||||
)
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/users/invite", methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def invite_user(service_id):
|
||||
|
||||
form = InviteUserForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
flash('Invite sent to {}'.format(form.email_address.data), 'default_with_tick')
|
||||
return redirect(url_for('.manage_users', service_id=service_id))
|
||||
|
||||
return render_template(
|
||||
'views/invite-user.html',
|
||||
user={},
|
||||
service=get_service_by_id_or_404(service_id),
|
||||
service_id=service_id,
|
||||
form=form
|
||||
)
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/users/<user_id>", methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_user(service_id, user_id):
|
||||
|
||||
if request.method == 'POST':
|
||||
return redirect(url_for('.manage_users', service_id=service_id))
|
||||
|
||||
return render_template(
|
||||
'views/invite-user.html',
|
||||
user=fake_users[int(user_id)],
|
||||
user_id=user_id,
|
||||
service=get_service_by_id_or_404(service_id),
|
||||
service_id=service_id
|
||||
)
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/users/<user_id>/delete", methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def delete_user(service_id, user_id):
|
||||
|
||||
if request.method == 'POST':
|
||||
return redirect(url_for('.manage_users', service_id=service_id))
|
||||
|
||||
user = fake_users[int(user_id)]
|
||||
|
||||
flash(
|
||||
'Are you sure you want to delete {}’s account?'.format(user.get('name') or user['email_localpart']),
|
||||
'delete'
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'views/invite-user.html',
|
||||
user=user,
|
||||
user_id=user_id,
|
||||
service=get_service_by_id_or_404(service_id),
|
||||
service_id=service_id
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
from flask import render_template, current_app, abort
|
||||
from flask_wtf import Form
|
||||
from wtforms import StringField, PasswordField, TextAreaField, FileField, validators
|
||||
from utils.template import Template
|
||||
from app.main import main
|
||||
|
||||
|
||||
@@ -17,13 +18,16 @@ def styleguide():
|
||||
message = TextAreaField(u'Message')
|
||||
file_upload = FileField('Upload a CSV file to add your recipients’ details')
|
||||
|
||||
sms = "Your vehicle tax for ((registration number)) is due on ((date)). Renew online at www.gov.uk/vehicle-tax"
|
||||
|
||||
form = FormExamples()
|
||||
|
||||
form.message.data = "Your vehicle tax for ((registration number)) is due on ((date)). Renew online at www.gov.uk/vehicle-tax" # noqa
|
||||
|
||||
form.message.data = sms
|
||||
form.validate()
|
||||
|
||||
template = Template({'content': sms})
|
||||
|
||||
return render_template(
|
||||
'views/styleguide.html',
|
||||
form=form
|
||||
form=form,
|
||||
template=template
|
||||
)
|
||||
|
||||
@@ -15,22 +15,10 @@ from app.main.dao import services_dao as sdao
|
||||
@main.route("/services/<service_id>/templates")
|
||||
@login_required
|
||||
def manage_service_templates(service_id):
|
||||
try:
|
||||
jobs = job_api_client.get_job(service_id)['data']
|
||||
except HTTPError as e:
|
||||
if e.status_code == 404:
|
||||
abort(404)
|
||||
else:
|
||||
raise e
|
||||
return render_template(
|
||||
'views/manage-templates.html',
|
||||
service_id=service_id,
|
||||
has_jobs=bool(jobs),
|
||||
templates=[
|
||||
Template(template)
|
||||
for template in tdao.get_service_templates(service_id)['data']
|
||||
]
|
||||
)
|
||||
return redirect(url_for(
|
||||
'.choose_sms_template',
|
||||
service_id=service_id
|
||||
))
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/templates/add", methods=['GET', 'POST'])
|
||||
@@ -50,10 +38,10 @@ def add_service_template(service_id):
|
||||
tdao.insert_service_template(
|
||||
form.name.data, form.template_content.data, service_id)
|
||||
return redirect(url_for(
|
||||
'.manage_service_templates', service_id=service_id))
|
||||
'.choose_sms_template', service_id=service_id))
|
||||
return render_template(
|
||||
'views/edit-template.html',
|
||||
h1='Add template',
|
||||
h1='Add a text message template',
|
||||
form=form,
|
||||
service_id=service_id)
|
||||
|
||||
@@ -69,7 +57,7 @@ def edit_service_template(service_id, template_id):
|
||||
tdao.update_service_template(
|
||||
template_id, form.name.data,
|
||||
form.template_content.data, service_id)
|
||||
return redirect(url_for('.manage_service_templates', service_id=service_id))
|
||||
return redirect(url_for('.choose_sms_template', service_id=service_id))
|
||||
|
||||
return render_template(
|
||||
'views/edit-template.html',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% macro file_upload(field, button_text="Choose file") %}
|
||||
<div class="form-group{% if field.errors %} error{% endif %}" data-module="file-upload">
|
||||
<label class="file-upload-label" for="{{ field.name }}">
|
||||
{{ field.label }}
|
||||
<span class="visually-hidden">{{ field.label }}</span>
|
||||
{% if hint %}
|
||||
<span class="form-hint">
|
||||
{{ hint }}
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<input type="submit" class="button{% if destructive %}-destructive{% endif %}" value="{{ button_text }}" />
|
||||
{% endif %}
|
||||
{% if delete_link %}
|
||||
<span class="page-footer-delete-link">
|
||||
or <a href="{{ delete_link }}">{{ delete_link_text }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if back_link %}
|
||||
<a class="page-footer-back-link" href="{{ back_link }}">{{ back_link_text }}</a>
|
||||
{% endif %}
|
||||
{% if delete_link %}
|
||||
<span class="page-footer-delete-link">
|
||||
<a href="{{ delete_link }}">{{ delete_link_text }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if secondary_link and secondary_link_text %}
|
||||
<a class="page-footer-secondary-link" href="{{ secondary_link }}">{{ secondary_link_text }}</a>
|
||||
{% endif %}
|
||||
|
||||
@@ -55,6 +55,18 @@
|
||||
</td>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro text_field(text) -%}
|
||||
{% call field() %}
|
||||
{{ text }}
|
||||
{% endcall %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro boolean_field(yes) -%}
|
||||
{% call field(status='yes' if yes else 'no') %}
|
||||
{{ "Yes" if yes else "No" }}
|
||||
{% endcall %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro right_aligned_field_heading(text) %}
|
||||
<span class="table-field-heading-right-aligned">{{ text }}</span>
|
||||
{%- endmacro %}
|
||||
|
||||
17
app/templates/components/yes-no.html
Normal file
17
app/templates/components/yes-no.html
Normal file
@@ -0,0 +1,17 @@
|
||||
{% macro yes_no(name, label, current_value=None) %}
|
||||
<fieldset class='yes-no'>
|
||||
<legend class='yes-no-label'>
|
||||
{{ label }}
|
||||
</legend>
|
||||
<div class='yes-no-fields inline'>
|
||||
<label class='block-label'>
|
||||
<input type='radio' name='{{ name }}' {% if current_value == True %}checked{% endif %} />
|
||||
Yes
|
||||
</label>
|
||||
<label class='block-label'>
|
||||
<input type='radio' name='{{ name }}' {% if current_value == False %}checked{% endif %} />
|
||||
No
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endmacro %}
|
||||
@@ -5,7 +5,7 @@
|
||||
{{ banner(
|
||||
message,
|
||||
'default' if ((category == 'default') or (category == 'default_with_tick')) else 'dangerous',
|
||||
delete_button="Yes, delete this template" if 'delete' == category else None,
|
||||
delete_button="Yes, delete" if 'delete' == category else None,
|
||||
with_tick=True if category == 'default_with_tick' else False
|
||||
)}}
|
||||
{% endfor %}
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
<li><a href="{{ url_for('.send_email', service_id=service_id) }}">Send emails</a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="{{ url_for('.manage_service_templates', service_id=service_id) }}">Manage templates</a></li>
|
||||
<li><a href="{{ url_for('.manage_users', service_id=service_id) }}">Manage users</a></li>
|
||||
<li><a href="{{ url_for('.service_settings', service_id=service_id) }}">Manage service settings</a></li>
|
||||
<li><a href="{{ url_for('.manage_users', service_id=service_id) }}">Manage team</a></li>
|
||||
<li><a href="{{ url_for('.service_settings', service_id=service_id) }}">Manage settings</a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="{{ url_for('.documentation', service_id=service_id) }}">Developer documentation</a></li>
|
||||
<li><a href="{{ url_for('.api_keys', service_id=service_id) }}">API keys</a></li>
|
||||
<li><a href="{{ url_for('.documentation', service_id=service_id) }}">Developer documentation</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
|
||||
<p>
|
||||
<p class='table-show-more-link'>
|
||||
<a href="{{ url_for('.create_api_key', service_id=service_id) }}">Create a new API key</a>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -23,18 +23,16 @@
|
||||
<div class="sms-message-use-links">
|
||||
<a href="{{ url_for(".send_sms", service_id=service_id, template_id=template.id) }}">Add recipients</a>
|
||||
<a href="{{ url_for(".send_sms_to_self", service_id=service_id, template_id=template.id) }}">Send yourself a test</a>
|
||||
<a href="{{ url_for(".edit_service_template", service_id=service_id, template_id=template.id) }}">Edit template</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ banner(
|
||||
'<a href="{}">Add a text message template</a> to start sending messages'.format(
|
||||
url_for(".add_service_template", service_id=service_id)
|
||||
)|safe,
|
||||
type="tip"
|
||||
)}}
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
<a href="{{ url_for('.add_service_template', service_id=service_id) }}" class="button">Add a new template</a>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
{{ page_footer(
|
||||
'Save',
|
||||
delete_link=url_for('.delete_service_template', service_id=service_id, template_id=template_id) if template_id or None,
|
||||
delete_link_text='delete this template',
|
||||
secondary_link=url_for('.manage_service_templates', service_id=service_id),
|
||||
secondary_link_text='Back to templates'
|
||||
delete_link_text='Delete this template',
|
||||
back_link=url_for('.choose_sms_template', service_id=service_id),
|
||||
back_link_text='Cancel'
|
||||
) }}
|
||||
</form>
|
||||
|
||||
|
||||
50
app/templates/views/invite-user.html
Normal file
50
app/templates/views/invite-user.html
Normal file
@@ -0,0 +1,50 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/yes-no.html" import yes_no %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
|
||||
{% block page_title %}
|
||||
Manage users – GOV.UK Notify
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<h1 class="heading-large">
|
||||
{{ user.name or user.email_localpart or "Add a new team member" }}
|
||||
</h1>
|
||||
|
||||
<div class="grid-row">
|
||||
<form method="post" class="column-three-quarters">
|
||||
|
||||
{% if user %}
|
||||
<p class='bottom-gutter'>
|
||||
{{ current_user.email_address }}
|
||||
</p>
|
||||
{% else %}
|
||||
{{ textbox(form.email_address, hint='Email address must end in .gov.uk', width='1-1') }}
|
||||
{% endif %}
|
||||
|
||||
<fieldset class='yes-no-wrapper'>
|
||||
<legend class='heading-small'>
|
||||
Permissions
|
||||
</legend>
|
||||
{{ yes_no('send_messages', 'Send messages', user.permission_send_messages) }}
|
||||
{{ yes_no('manage_service', 'Manage service', user.permission_manage_service) }}
|
||||
{{ yes_no('manage_api_keys', 'Manage API keys', user.permission_manage_api_keys) }}
|
||||
</fieldset>
|
||||
|
||||
{% if user %}
|
||||
{{ page_footer(
|
||||
'Save',
|
||||
delete_link=url_for('.delete_user', service_id=service_id, user_id=user_id),
|
||||
delete_link_text='Delete this account',
|
||||
back_link=url_for('.manage_users', service_id=service_id),
|
||||
back_link_text='Cancel'
|
||||
) }}
|
||||
{% else %}
|
||||
{{ page_footer('Send invitation email') }}
|
||||
{% endif %}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,53 +0,0 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/browse-list.html" import browse_list %}
|
||||
|
||||
{% block page_title %}
|
||||
Manage templates – GOV.UK Notify
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<h1 class="heading-large">Manage templates</h1>
|
||||
|
||||
|
||||
{% if not has_jobs %}
|
||||
{{ banner(
|
||||
'<a href="{}">Send yourself a text message</a>'.format(
|
||||
url_for(".choose_sms_template", service_id=service_id)
|
||||
)|safe,
|
||||
subhead='Next step',
|
||||
type="tip"
|
||||
)}}
|
||||
{% endif %}
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
|
||||
{% for template in templates %}
|
||||
{% if template.template_type == 'email' %}
|
||||
{{ email_message(
|
||||
template.get_field('subject'),
|
||||
template.get_field('content'),
|
||||
name=template.get_field('name'),
|
||||
edit_link=url_for('.edit_service_template', service_id=service_id, template_id=template.id)
|
||||
) }}
|
||||
{% else %}
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup,
|
||||
name=template.name,
|
||||
id=template.id,
|
||||
edit_link=url_for('.edit_service_template', service_id=service_id, template_id=template.id)
|
||||
) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<p>
|
||||
<a href="{{ url_for('.add_service_template', service_id=service_id) }}" class="button">Add new template</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,65 +1,55 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/table.html" import list_table, row, field %}
|
||||
{% from "components/table.html" import list_table, row, field, boolean_field, hidden_field_heading %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
|
||||
{% set table_options = {
|
||||
'field_headings': [
|
||||
'Name', 'Send messages', 'Manage service', 'Manage API keys', hidden_field_heading('Link to change')
|
||||
],
|
||||
'field_headings_visible': True,
|
||||
'caption_visible': True
|
||||
} %}
|
||||
|
||||
{% block page_title %}
|
||||
Manage users – GOV.UK Notify
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<h1 class="heading-large">Manage users</h1>
|
||||
<h1 class="heading-large">
|
||||
Manage team
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<a href="#" class="button">Invite users</a>
|
||||
</p>
|
||||
<a href="{{ url_for('.invite_user', service_id=service_id) }}" class="button">Invite a team member</a>
|
||||
|
||||
{% call(item) list_table(
|
||||
users,
|
||||
caption='Active users',
|
||||
field_headings=['Name', 'Send messages', 'Manage Service', 'Manage API keys', 'Link to change'],
|
||||
field_headings_visible=True,
|
||||
caption_visible=True
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.name }}
|
||||
{% call(item) list_table(
|
||||
users, caption='Active', **table_options
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ current_user.name }}
|
||||
{% endcall %}
|
||||
{{ boolean_field(item.permission_send_messages) }}
|
||||
{{ boolean_field(item.permission_manage_service) }}
|
||||
{{ boolean_field(item.permission_manage_api_keys) }}
|
||||
{% call field(align='right') %}
|
||||
<a href="{{ url_for('.edit_user', service_id=service_id, user_id=0)}}">Change</a>
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ "✔" if item.permission_send_messages else "❌" }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ "✔" if item.permission_manage_service else "❌" }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ "✔" if item.permission_manage_api_keys else "❌" }}
|
||||
{% endcall %}
|
||||
{% call field(align='right') %}
|
||||
<a href="#">Change</a>
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
|
||||
{% call(item) list_table(
|
||||
invited_users,
|
||||
caption='Invited users',
|
||||
field_headings=['Name', 'Send messages', 'Manage Service', 'Manage API keys', 'Link to change'],
|
||||
field_headings_visible=True,
|
||||
caption_visible=True
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.email_localpart }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ "✔" if item.permission_send_messages else "❌" }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ "✔" if item.permission_manage_service else "❌" }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ "✔" if item.permission_manage_api_keys else "❌" }}
|
||||
{% endcall %}
|
||||
{% call field(align='right') %}
|
||||
<a href="#">Change</a>
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% if invited_users %}
|
||||
{% call(item) list_table(
|
||||
invited_users, caption='Invited', **table_options
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.email_localpart }}
|
||||
{% endcall %}
|
||||
{{ boolean_field(item.permission_send_messages) }}
|
||||
{{ boolean_field(item.permission_manage_service) }}
|
||||
{{ boolean_field(item.permission_manage_api_keys) }}
|
||||
{% call field(align='right') %}
|
||||
<a href="{{ url_for('.edit_user', service_id=service_id, user_id=item.id)}}">Change</a>
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -20,16 +20,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{file_upload(form.file, button_text='Choose a CSV file')}}
|
||||
|
||||
<p>
|
||||
<a href="{{ url_for('.get_example_csv', service_id=service_id, template_id=template.id) }}">Download an example CSV file</a>
|
||||
</p>
|
||||
|
||||
{{ page_footer(
|
||||
"Continue to preview"
|
||||
) }}
|
||||
|
||||
{{file_upload(form.file, button_text='Upload a CSV file')}}
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
@@ -25,21 +25,9 @@
|
||||
|
||||
{% if not jobs %}
|
||||
{{ banner(
|
||||
"""
|
||||
<ol>
|
||||
<li>
|
||||
<a href='{}'>Add a template</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href='{}'>Send yourself a text message</a>
|
||||
</li>
|
||||
</ol>
|
||||
""".format(
|
||||
url_for(".add_service_template", service_id=service_id),
|
||||
url_for(".choose_sms_template", service_id=service_id)
|
||||
)|safe,
|
||||
'Send yourself a text message',
|
||||
subhead='Get started',
|
||||
type="tip"
|
||||
type='tip'
|
||||
)}}
|
||||
{% else %}
|
||||
{% call(item) list_table(
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
{% from "components/browse-list.html" import browse_list %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/table.html" import mapping_table, list_table, row, field, right_aligned_field_heading %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/table.html" import mapping_table, list_table, row, field, text_field, boolean_field, right_aligned_field_heading %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
{% from "components/file-upload.html" import file_upload %}
|
||||
{% from "components/yes-no.html" import yes_no %}
|
||||
{% from "components/api-key.html" import api_key %}
|
||||
|
||||
{% block page_title %}
|
||||
@@ -25,21 +27,26 @@
|
||||
</p>
|
||||
|
||||
<h2 class="heading-large">Banner</h2>
|
||||
<p>Used to show the status of a thing or action.</p>
|
||||
<div class="grid-row">
|
||||
<div class="column-three-quarters">
|
||||
<p>Used to show the status of a thing or action.</p>
|
||||
|
||||
{{ banner("You sent 1,234 text messages", with_tick=True) }}
|
||||
{{ banner("You sent 1,234 text messages", with_tick=True) }}
|
||||
|
||||
{{ banner('You’re not allowed to do this', 'dangerous')}}
|
||||
{{ banner('You’re not allowed to do this', 'dangerous')}}
|
||||
|
||||
{{ banner('Are you sure you want to delete?', 'dangerous', delete_button="Yes, delete this thing")}}
|
||||
{{ banner('Are you sure you want to delete?', 'dangerous', delete_button="Yes, delete this thing")}}
|
||||
|
||||
{{ banner(
|
||||
'<a href="#">Send your first message</a>'|safe,
|
||||
subhead='Get started',
|
||||
type='tip'
|
||||
)}}
|
||||
{{ banner(
|
||||
'<a href="#">Send your first message</a>'|safe,
|
||||
subhead='Get started',
|
||||
type='tip'
|
||||
)}}
|
||||
|
||||
{{ banner('You could go to jail', 'important')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ banner('You could go to jail', 'important')}}
|
||||
|
||||
<h2 class="heading-large">Big number</h2>
|
||||
|
||||
@@ -118,7 +125,7 @@
|
||||
|
||||
<h2 class="heading-large">SMS message</h2>
|
||||
|
||||
<p>Used to show, preview or choose an SMS message.</p>
|
||||
<p>Used to show, preview or choose an SMS template.</p>
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="column-half">
|
||||
@@ -127,82 +134,105 @@
|
||||
name='Two week reminder',
|
||||
) }}
|
||||
{{ sms_message(
|
||||
'Your vehicle tax for ((registration number)) is due on ((date)). Renew online at www.gov.uk/vehicle-tax'
|
||||
template.formatted_as_markup
|
||||
) }}
|
||||
{{ sms_message(
|
||||
'Your vehicle tax for registration number is due on date. Renew online at www.gov.uk/vehicle-tax',
|
||||
'Your vehicle tax for LC12 BFL is due on 1 March 2016. Renew online at www.gov.uk/vehicle-tax',
|
||||
'+44 7700 900 306'
|
||||
) }}
|
||||
{{ sms_message(
|
||||
'Your vehicle tax for ((registration number)) is due on ((date)). Renew online at www.gov.uk/vehicle-tax',
|
||||
template.formatted_as_markup,
|
||||
name='Two week reminder',
|
||||
edit_link='#'
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="heading-large">Email message</h2>
|
||||
|
||||
<p>Used to show, preview or choose an email template.</p>
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ email_message(
|
||||
subject="Vehicle tax reminder",
|
||||
body="Dear Alice Smith,\n\nYour vehicle tax for LC12 BFL is due on 1 March 2016.\n\nRenew online at www.gov.uk/vehicle-tax",
|
||||
from_name="Vehicle tax",
|
||||
from_address="vehicle.tax@notifications.service.gov.uk",
|
||||
name="Two week reminder",
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="heading-large">Tables</h2>
|
||||
{% call mapping_table(
|
||||
caption='Account settings',
|
||||
field_headings=['Label', 'Value', 'Action'],
|
||||
field_headings_visible=False,
|
||||
caption_visible=True
|
||||
) %}
|
||||
{% call row() %}
|
||||
{% call field() %}
|
||||
Username
|
||||
<div class="grid-row">
|
||||
<div class="column-three-quarters">
|
||||
<p>
|
||||
Used for comparing rows of data.
|
||||
</p>
|
||||
{% call mapping_table(
|
||||
caption='Account settings',
|
||||
field_headings=['Label', 'True', 'False', 'Action'],
|
||||
field_headings_visible=False,
|
||||
caption_visible=True
|
||||
) %}
|
||||
{% call row() %}
|
||||
{{ text_field('Username' )}}
|
||||
{{ boolean_field(True) }}
|
||||
{{ boolean_field(False) }}
|
||||
{% call field(align='right') %}
|
||||
<a href="#">Change</a>
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
admin
|
||||
{% endcall %}
|
||||
{% call field(align='right') %}
|
||||
<a href="#">Change</a>
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
|
||||
{% call(item) list_table(
|
||||
[
|
||||
{
|
||||
'file': 'dispatch_20151114.csv', 'status': 'Queued'
|
||||
},
|
||||
{
|
||||
'file': 'dispatch_20151117.csv', 'status': 'Delivered'
|
||||
},
|
||||
{
|
||||
'file': 'remdinder_monday.csv', 'status': 'Failed'
|
||||
}
|
||||
],
|
||||
caption='Messages',
|
||||
field_headings=['File', right_aligned_field_heading('Status')],
|
||||
field_headings_visible=True,
|
||||
caption_visible=False
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.file }}
|
||||
{% endcall %}
|
||||
{% call field(
|
||||
align='right',
|
||||
status='error' if item.status == 'Failed' else 'default'
|
||||
) %}
|
||||
{{ item.status }}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% call(item) list_table(
|
||||
[
|
||||
{
|
||||
'file': 'dispatch_20151114.csv', 'status': 'Queued'
|
||||
},
|
||||
{
|
||||
'file': 'dispatch_20151117.csv', 'status': 'Delivered'
|
||||
},
|
||||
{
|
||||
'file': 'remdinder_monday.csv', 'status': 'Failed'
|
||||
}
|
||||
],
|
||||
caption='Messages',
|
||||
field_headings=['File', right_aligned_field_heading('Status')],
|
||||
field_headings_visible=True,
|
||||
caption_visible=False
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.file }}
|
||||
{% endcall %}
|
||||
{% call field(
|
||||
align='right',
|
||||
status='error' if item.status == 'Failed' else 'default'
|
||||
) %}
|
||||
{{ item.status }}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
|
||||
{% call(item) list_table(
|
||||
[],
|
||||
caption='Jobs',
|
||||
field_headings=['Job', 'Time'],
|
||||
caption_visible=True,
|
||||
empty_message='You haven’t scheduled any jobs yet'
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.job }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ item.time }}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
{% call(item) list_table(
|
||||
[],
|
||||
caption='Jobs',
|
||||
field_headings=['Job', 'Time'],
|
||||
caption_visible=True,
|
||||
empty_message='You haven’t scheduled any jobs yet'
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.job }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ item.time }}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
<p class="table-show-more-link">
|
||||
<a href="#">Add a job now</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="heading-large">Textbox</h2>
|
||||
{{ textbox(form.username) }}
|
||||
@@ -213,6 +243,17 @@
|
||||
<h2 class="heading-large">File upload</h2>
|
||||
{{ file_upload(form.file_upload) }}
|
||||
|
||||
<h2 class="heading-large">Yes/no</h2>
|
||||
<div class="grid-row">
|
||||
<div class='column-half'>
|
||||
<fieldset class='yes-no-wrapper'>
|
||||
{{ yes_no('manage_service', 'Manage service', True) }}
|
||||
{{ yes_no('templates', 'Create templates', True) }}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2 class="heading-large">API key</h2>
|
||||
|
||||
{{ api_key('d30512af92e1386d63b90e5973b49a10') }}
|
||||
|
||||
@@ -15,7 +15,9 @@ var gulp = require('gulp'),
|
||||
src: 'app/assets/',
|
||||
dist: 'app/static/',
|
||||
templates: 'app/templates/',
|
||||
npm: 'node_modules/'
|
||||
npm: 'node_modules/',
|
||||
template: 'node_modules/govuk_template_jinja/',
|
||||
toolkit: 'node_modules/govuk_frontend_toolkit/'
|
||||
};
|
||||
|
||||
// 3. TASKS
|
||||
@@ -23,18 +25,24 @@ var gulp = require('gulp'),
|
||||
|
||||
// Move GOV.UK template resources
|
||||
|
||||
gulp.task('copy:govuk_template:template', () => gulp.src(paths.npm + '/govuk_template_jinja/views/layouts/govuk_template.html')
|
||||
gulp.task('copy:govuk_template:template', () => gulp.src(paths.template + 'views/layouts/govuk_template.html')
|
||||
.pipe(gulp.dest(paths.templates))
|
||||
);
|
||||
|
||||
gulp.task('copy:govuk_template:assets', () => gulp.src(paths.npm + '/govuk_template_jinja/assets/**/*')
|
||||
.pipe(gulp.dest(paths.dist))
|
||||
gulp.task('copy:govuk_template:css', () => gulp.src(paths.template + 'assets/stylesheets/**/*.css')
|
||||
.pipe(plugins.sass({outputStyle: 'compressed'}))
|
||||
.pipe(gulp.dest(paths.dist + 'stylesheets/'))
|
||||
);
|
||||
|
||||
gulp.task('copy:govuk_template:js', () => gulp.src(paths.template + 'assets/javascripts/**/*.js')
|
||||
.pipe(plugins.uglify())
|
||||
.pipe(gulp.dest(paths.dist + 'javascripts/'))
|
||||
);
|
||||
|
||||
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.toolkit + 'javascripts/govuk/modules.js',
|
||||
paths.toolkit + 'javascripts/govuk/selection-buttons.js',
|
||||
paths.src + 'javascripts/apiKey.js',
|
||||
paths.src + 'javascripts/autofocus.js',
|
||||
paths.src + 'javascripts/highlightTags.js',
|
||||
@@ -59,10 +67,11 @@ gulp.task('sass', () => gulp
|
||||
outputStyle: 'compressed',
|
||||
includePaths: [
|
||||
paths.npm + 'govuk-elements-sass/public/sass/',
|
||||
paths.npm + 'govuk_frontend_toolkit/stylesheets/'
|
||||
paths.toolkit + 'stylesheets/'
|
||||
]
|
||||
}))
|
||||
.pipe(gulp.dest(paths.dist + '/stylesheets'))
|
||||
.pipe(plugins.base64({baseDir: 'app'}))
|
||||
.pipe(gulp.dest(paths.dist + 'stylesheets/'))
|
||||
);
|
||||
|
||||
|
||||
@@ -71,9 +80,10 @@ gulp.task('sass', () => gulp
|
||||
gulp.task('images', () => gulp
|
||||
.src([
|
||||
paths.src + 'images/**/*',
|
||||
paths.npm + 'govuk_frontend_toolkit/images/**/*'
|
||||
paths.toolkit + 'images/**/*',
|
||||
paths.template + 'assets/images/**/*'
|
||||
])
|
||||
.pipe(gulp.dest(paths.dist + '/images'))
|
||||
.pipe(gulp.dest(paths.dist + 'images/'))
|
||||
);
|
||||
|
||||
|
||||
@@ -82,10 +92,11 @@ gulp.task('watchForChanges', function() {
|
||||
gulp.watch(paths.src + 'javascripts/**/*', ['javascripts']);
|
||||
gulp.watch(paths.src + 'stylesheets/**/*', ['sass']);
|
||||
gulp.watch(paths.src + 'images/**/*', ['images']);
|
||||
gulp.watch('gulpfile.babel.js', ['default']);
|
||||
});
|
||||
|
||||
gulp.task('lint:sass', () => gulp
|
||||
.src(paths.src + '/stylesheets/**/*.scss')
|
||||
.src(paths.src + 'stylesheets/**/*.scss')
|
||||
.pipe(plugins.sassLint())
|
||||
.pipe(plugins.sassLint.format(stylish))
|
||||
.pipe(plugins.sassLint.failOnError())
|
||||
@@ -104,7 +115,14 @@ gulp.task('lint',
|
||||
|
||||
// Default: compile everything
|
||||
gulp.task('default',
|
||||
['copy:govuk_template:template', 'copy:govuk_template:assets', 'javascripts', 'sass', 'images']
|
||||
[
|
||||
'copy:govuk_template:template',
|
||||
'copy:govuk_template:css',
|
||||
'copy:govuk_template:js',
|
||||
'javascripts',
|
||||
'sass',
|
||||
'images'
|
||||
]
|
||||
);
|
||||
|
||||
// Optional: recompile on changes
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"gulp": "3.9.0",
|
||||
"gulp-add-src": "0.2.0",
|
||||
"gulp-babel": "6.1.1",
|
||||
"gulp-base64": "0.1.3",
|
||||
"gulp-concat": "2.6.0",
|
||||
"gulp-include": "2.1.0",
|
||||
"gulp-jquery": "1.1.1",
|
||||
|
||||
@@ -6,4 +6,4 @@ def test_owasp_useful_headers_set(app_):
|
||||
assert response.headers['X-Frame-Options'] == 'deny'
|
||||
assert response.headers['X-Content-Type-Options'] == 'nosniff'
|
||||
assert response.headers['X-XSS-Protection'] == '1; mode=block'
|
||||
assert response.headers['Content-Security-Policy'] == "default-src 'self' 'unsafe-inline'; font-src 'self' data:;" # noqa
|
||||
assert response.headers['Content-Security-Policy'] == "default-src 'self' 'unsafe-inline'; font-src 'self' data:; img-src 'self' data:;" # noqa
|
||||
|
||||
84
tests/app/main/views/test_manage_users.py
Normal file
84
tests/app/main/views/test_manage_users.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import json
|
||||
from flask import url_for
|
||||
|
||||
|
||||
def test_should_show_overview_page(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_service
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
response = client.get(url_for('main.manage_users', service_id=55555))
|
||||
|
||||
assert 'Manage team' in response.get_data(as_text=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_should_show_page_for_one_user(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_service
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
response = client.get(url_for('main.edit_user', service_id=55555, user_id=0))
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_redirect_after_saving_user(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_service
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
response = client.post(url_for(
|
||||
'main.edit_user', service_id=55555, user_id=0
|
||||
))
|
||||
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for(
|
||||
'main.manage_users', service_id=55555, _external=True
|
||||
)
|
||||
|
||||
|
||||
def test_should_show_page_for_inviting_user(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_service
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
response = client.get(url_for('main.invite_user', service_id=55555))
|
||||
|
||||
assert 'Add a new team member' in response.get_data(as_text=True)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_invite_user(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_service
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
response = client.post(
|
||||
url_for('main.invite_user', service_id=55555),
|
||||
data={'email_address': 'test@example.gov.uk'},
|
||||
follow_redirects=True
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert 'Invite sent to test@example.gov.uk' in response.get_data(as_text=True)
|
||||
@@ -16,7 +16,7 @@ def test_should_return_list_of_all_templates(app_,
|
||||
client.login(api_user_active)
|
||||
service_id = str(uuid.uuid4())
|
||||
response = client.get(url_for(
|
||||
'.manage_service_templates', service_id=service_id))
|
||||
'.manage_service_templates', service_id=service_id), follow_redirects=True)
|
||||
|
||||
assert response.status_code == 200
|
||||
mock_get_service_templates.assert_called_with(service_id)
|
||||
@@ -72,7 +72,7 @@ def test_should_redirect_when_saving_a_template(app_,
|
||||
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for(
|
||||
'.manage_service_templates', service_id=service_id, _external=True)
|
||||
'.choose_sms_template', service_id=service_id, _external=True)
|
||||
mock_update_service_template.assert_called_with(
|
||||
template_id, name, 'sms', content, service_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user