Commit Graph

4187 Commits

Author SHA1 Message Date
Chris Hill-Scott
b998b6bb20 Remove methods for checking service/org name uniqueness
We don’t use these now – instead we try to update the name and see if
it works or not.
2022-01-13 10:16:07 +00:00
Chris Hill-Scott
a09af2acc8 Remove update_organisation_name model method
It’s weird to have a method just for updating one attribute. I think
the reason for doing this was to only invalidate the
`organisation-{}-name` cache when absolutely necessary, but:
- we don’t need a separate method to check whether it’s the name being
  updated
- it was easy to get around this by calling
  `OrganisationsClient.update_organisation` directly, leaving a stale
  value in the cache
2022-01-13 10:16:06 +00:00
Chris Hill-Scott
c630faf3b4 Remove re-enter password step from rename organisation
Note that this is copied from the same change made to the rename service
page:
1190e4541b

The original idea behind was to always ask users to re-enter their
password any time:
- we want them to be sure that they want to do what they’re about to do
- we want to be sure it’s really the user trying to do the thing (and
  not someone malicious)

In reality we:
- removed this from the initial place it was added (a descendent of the
  ‘suspend service’ feature)
- only ever added it to the ‘rename service’ and ‘rename organisation’
  features

So in reality it’s not a pattern we have persisted with. Arguably there
are several things you can now do in the admin app without re-entering
your password which are much more high consequence than changing the
service name.

Also, with browser autofill there’s a lot less chance that forcing
someone to re-enter a password really gives much defence against an
unattended laptop, for example.

So this commit removes the need to re-enter your password when renaming
an organisation.
2022-01-13 10:16:03 +00:00
Chris Hill-Scott
d4ec4bf9f4 Don’t error if organisation name is unchanged
If you submit the rename organisation form without making any changes
you will get an error saying that the name is currently in use. This is
true because it’s being used by the current organisation.

However your intention is probably not to actually change anything, so
we can just redirect back to the settings page.

This is the same thing we do when renaming services:
60f5b74904/app/main/views/service_settings.py (L99-L100)
2022-01-13 10:14:17 +00:00
Chris Hill-Scott
0ad106f572 Mark client fixture as ‘private’
No tests are now using the `client` fixture directly so we can rename
it.

Python convention is to use an `_underscore` for things which should be
considered semi private.

This should discourage people from writing new tests with these old
fixtures.

New tests should always use `client_request`.

Want to be logged in with a different user? Call
`client_request.login(user)` first.

Don’t want to be logged in? Call `client_request.logout()` first (most
of our tests need to be logged in).

Need an instance of `Response` object not an instance of
`BeautifulSoup`? Use `client_request.get_response` or
`client_request.post_response`.

Need to pass in a URL, not arguments to `url_for`? Use
`client_request.get_url(…)` or `client_request.post_url(…)`.

Need to pass in a URL and get a response back? Use
`client_request.get_response_from_url(…)` or
`client_request.post_response_from_url(…)`.
2022-01-10 14:39:46 +00:00
Chris Hill-Scott
6540701aa7 Replace uses of client to set request context
Some tests use the `client` fixture but don’t call any of its methods.
The reason for doing this is because the test depends on something in
the request context.

This commit replaces all those instances with `client_request`, which
also sets the request context.

These tests are the last ones that still use the `client` fixture. By
replacing it with `client_request` we will be able to say that no tests
should be using the `client` fixture directly.
2022-01-10 14:39:46 +00:00
Chris Hill-Scott
7e707db4b2 Replace uses of client.get and client.post
We have a `client_request` fixture which does a bunch of useful stuff
like:
- checking the status code of the response
- returning a `BeautifulSoup` object

Lots of our tests still use an older fixture called `client`. This is
not as good because it:
- returns a raw `Response` object
- doesn’t do the additional checks
- means our tests contain a lot of repetetive boilerplate like `page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')`

This commit converts all the tests which had a `client.get(…)` or
`client.post(…)` statement to use their equivalents on `client_request`
instead.

Subsequent commits will remove uses of `client` in other tests, but
doing it this way means the work can be broken up into more manageable
chunks.
2022-01-10 14:39:45 +00:00
Chris Hill-Scott
07318b2d11 Replace instances of client.login with client_request
We have a `client_request` fixture which does a bunch of useful stuff
like:
- checking the status code of the response
- returning a `BeautifulSoup` object

Lots of our tests still use an older fixture called `client`. This is
not as good because it:
- returns a raw `Response` object
- doesn’t do the additional checks
- means our tests contain a lot of repetetive boilerplate like `page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')`

This commit converts all the tests which had a `client.login(…)`
statement to use `client_request` (which is already logged in by
default).

Subsequent commits will remove uses of `client` in other tests, but
doing it this way means the work can be broken up into more manageable
chunks.
2022-01-10 14:39:45 +00:00
Chris Hill-Scott
8b93a977a0 Remove temporary raw_response argument
We added a new argument to `client_request.get` and
`client_request.post` to specify that it should return a raw `Response`
object rather than an instance of `BeautifulSoup`.

This is useful because sometimes we need to look at stuff like the
response headers.

However it turns out we already have a separate method for this, so
rather than invent something new I think it’s better to stick with the
thing we already have.
2022-01-10 14:39:45 +00:00
Chris Hill-Scott
c37258fd0d Stop using logged_in_client_with_session fixture
We have a `client_request` fixture which does a bunch of useful stuff
like:
- checking the status code of the response
- returning a `BeautifulSoup` object

A few of our tests still use an older fixture called
`logged_in_client_with_session`. It’s not clear how this is different
from `logged_in_client`, which we have replaced with `client_request`.

So this commit goes ahead and converts all the tests using
`logged_in_client_with_session` to use `client_request` instead.
2022-01-10 14:39:45 +00:00
Chris Hill-Scott
0706664be4 Stop using logged_in_client fixture
We have a `client_request` fixture which does a bunch of useful stuff
like:
- checking the status code of the response
- returning a `BeautifulSoup` object

Lots of our tests still use an older fixture called `logged_in_client`.
This is not as good because:
- it returns a raw `Response` object
- doesn’t do the additional checks
- means our tests contain a lot of repetetive boilerplate like `page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')`

This commit converts all the tests using `logged_in_client` to:
use `client_request` instead.
2022-01-10 14:39:44 +00:00
Chris Hill-Scott
50eae6f935 Stop using platform_admin_client fixture
We have a `client_request` fixture which does a bunch of useful stuff
like:
- checking the status code of the response
- returning a `BeautifulSoup` object

For most tests of a platform admin view we used `platform_admin_client`
instead. This is not as good because it returns a raw `Response` object
and doesn’t do the additional checks.

This commit converts all the tests using `platform_admin_client` to:
use new `client_request` and log in as `platform_admin_user` before
making any requests.

This is also nice because it makes any test easy to parametrize with
additional users, for example to test differences in behaviour dependant
on being platform admin or not.
2022-01-10 14:39:40 +00:00
Chris Hill-Scott
0fd79bb500 Merge pull request #4122 from alphagov/no-text-in-svg
Don’t allow <text> elements in letter logos
2022-01-10 11:13:09 +00:00
Chris Hill-Scott
75f8c16071 Convert test to use client_request fixture
This is to avoid merge conflicts with
https://github.com/alphagov/notifications-admin/pull/4118/files
2022-01-06 17:39:01 +00:00
Chris Hill-Scott
291906e9fd Don’t allow <text> elements in letter logos
To render text in an SVG consistently the system rendering the SVG must
have the fonts specified by the SVG installed.

If the fonts are not installed then the renderer will fall back to a
system font and the text will look different. This is especially bad
news for branding where the right font is an integral part of any brand.

To fix this, the text should instead be converted to `<path>` elements.
This process is sometimes called ‘outlining’.

A few of our logos had this problem, and I’ve fixed most of them by
hand. Adding this validation will stop the problem, coming up again.
2022-01-06 17:39:01 +00:00
Chris Hill-Scott
5558af2527 Refactor for reuse 2022-01-06 17:39:01 +00:00
Chris Hill-Scott
474d7dfda8 Format phone numbers with spaces in download of received text messages
Some users have reported a problem with the received text message
report:

> I have tested the reply service but in the excel report the mobile
> number is showing as 4.47900E+23. How can I change the format so that
> it is show the mobile number that has replied?

This is happening because Excel is interpreting a phone number in the
format `447900900123` as a number in
[scientific notation](https://en.wikipedia.org/wiki/Scientific_notation),
in other words 4.479 &times; 10<sup>23</sup>.

`447900900123` is the format that our provider is giving us the number
in – there’s no guarantee it will always be in this format.

We can prevent this behaviour by putting spaces in the numbers. Excel
and Google Sheets won’t try to convert a string with spaces into a
number.

I think we used to do this for the sent text messages report but
probably stopped because we decided it was better to keep the phone
number in the same format as it had been supplied to us for
reconcilliation purposes.
2022-01-06 16:41:41 +00:00
Tom Byers
4f10272b00 Add styles and Jinja for component
Most of these are cut-and-paste'd from the GOVUK
metadata component:

https://components.publishing.service.gov.uk/component-guide/metadata

...but stripped back to only include what we need
and a optional suffix paragraph added.

Links to styles and ERB template
https://github.com/alphagov/govuk_publishing_components/blob/master/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss
https://github.com/alphagov/govuk_publishing_components/blob/master/app/views/govuk_publishing_components/components/_metadata.html.erb

Also adds it to the accessibility statement as an
example and updates the test that checks any
updates bump the date.
2022-01-05 15:21:37 +00:00
David McDonald
04fa99b3dc Update get_notifications_for_service to make POST requests
This updates the `get_notifications_for_service` of the
`NotificationApiClient` to make POST request to the api when the `to`
field is provided. This is done so that we avoid logging personal
details such as email addreses.

If the `to` field is not present, the method will make a GET reqeust and
there will be no change to how it works.
2022-01-04 11:14:16 +00:00
Chris Hill-Scott
2f0e3f39d3 Hide ‘Download this report’ link when no services
If an organisation doesn’t have any live services then there’s no data
to download. To make things less confusing we should hide the link in
this case.

This commit also modifies the existing test so that the assertions are
consistent.
2021-12-30 14:09:42 +00:00
Pea Tyczynska
e8876a0632 Make mocks more realistic
SMS remainder is never None, in practice it would be either 0 or
a natural number.
2021-12-22 17:31:01 +00:00
Pea Tyczynska
58fe9d5b56 Revert "Remove free text allowance remaining column from organisation report" 2021-12-21 16:05:29 +00:00
Katie Smith
2fe6c34730 Merge pull request #4098 from alphagov/form-bug-fixes
Fix two small bugs with forms
2021-12-13 11:19:11 +00:00
Katie Smith
30824b110c Fix billing page to show correct user who signed MOU
If the organisation table contains an entry for `agreement_signed_by_id`
and for `agreement_signed_on_behalf_of_name` then we should the person
who signed the MOU as being the `agreement_signed_on_behalf_of_name`.
This was wrongly showing the `agreement_signed_by_id` as the person who
signed the agreement.
2021-12-13 09:48:41 +00:00
Katie Smith
d8ebcdce22 Stop errors when changing an email address to an invalid one
We use the `ChangeEmailForm` if you want to change your own email
address or someone else's email address. This has various validators
which get run. We check if the email address is valid (by using a
function from utils) and if the email address is already in use
(by calling API).

If the email address is not valid, we should not call API to see if it's
already in use because this will cause an exception in API leading to a
`500` in admin. We now only call API if there were no other errors with
the email address.

(The `test_should_redirect_after_name_change` test didn't need the
`mock_email_is_not_already_in_use` fixture, so this has been removed.)
2021-12-10 17:11:46 +00:00
Katie Smith
e42853205c Update govuk_text_input_field_widget to only show one error
If there were multiple errors, this widget was joining the messages
together and displaying all error messages. If a text input field does
have more than one validation error, we only want to show one.
2021-12-10 14:59:18 +00:00
Katie Smith
58532ee4ca Merge pull request #4092 from alphagov/org-billing
Add new 'Billing' page for organisations
2021-12-10 12:48:37 +00:00
Katie Smith
aef83ad261 Add link to user page to go live tickets
This adds a link to the user profile of the person who requested to go
live for "Request to go live" Zendesk tickets. Viewing a user's profile
page helps us to check for duplicate organisations and services from
that user.
2021-12-10 11:51:04 +00:00
Katie Smith
66c50abc38 Add new 'Billing' page for organisations
We want organisation team members to be able to see the MOU details for
their organisation. This change creates a new page called billing, which
contains these details. It's only visible to platform admin users now -
the plan is to add more information to this page, then to make it visible
to all organisation users.

The page showing the MOU covers the case of when agreement_signed is
True, when an agreement_signed is False, and when agreement_signed is
None. The case when an agreement_signed is None is very rare - it
signifies that the agreement is not signed but that we have some
service-specific agreements in place. We only have a few organisations
in this state, so it's unlikely that the content for this scenario will
be seen.

When an organisation has signed the agreement we may know the full
details (signing date, version signed, the person who signed it or who it
was signed on behalf of), or we may only have the name of the person who
signed the agreement. We show the more detailed content if possible, and
a less detailed version of the content if not.

There's a new route for downloading the agreement which is almost
identical to the existing `.service_download_agreement` route (plus the
test is almost the same), except that it takes an organisation ID
instead of a service ID.
2021-12-10 08:46:24 +00:00
David McDonald
159e4c0bcb Merge pull request #4077 from alphagov/reduce-redis-cache-ttl
Reduce impact of bug with performance page caching stale data
2021-12-08 16:22:34 +00:00
David McDonald
e7d8918f7f Refactor test assertions
Doing this to reduce the use of overly verbose `call()` to match
assertions in test_status_api_client.
2021-12-08 16:01:26 +00:00
David McDonald
20cc1e230f Reduce TTL to 1 hour for get_count_of_live_services_and_organisations
This stat is shown on a few of our pages, such as our homepage,
the performance page and also a platform admin page
and is currently catched for the
default TTL of 1 week. I think there is no reason we can't make
this only cache once an hour and give slightly more up to date stats
which will update more regularly.

This mimics the approach and also the TTL choice of 1 hour that has
been added for the performance page (although there is no
particular bug here to fix, it is just nice to have slightly more up
up to date data).

Note, the API call only takes about 0.3 seconds at the moment
so it is not particularly intensive on the DB to run this more
regularly.
2021-12-08 15:39:10 +00:00
David McDonald
6acc7838e2 Add tests for existing status api client
Essentially copies the tests found in the performance_platform
api client.
2021-12-08 15:36:28 +00:00
Ben Thorner
1e63ee2d09 Merge pull request #4089 from alphagov/flash-upload-errors-177535141
Show flash instead of inline upload errors
2021-12-08 10:03:06 +00:00
Ben Thorner
b04bb51971 Merge pull request #4090 from alphagov/limit-csv-file-size-177535141
Reject CSV / Spreadsheet files larger than 10Mb
2021-12-07 17:00:05 +00:00
Ben Thorner
1a4204fed1 Merge pull request #4086 from alphagov/small-spreadsheet-refactor-177535141
Small refactoring to the Spreadsheet class
2021-12-07 16:59:46 +00:00
Ben Thorner
0ce7f72b07 Reject CSV / Spreadsheet files larger than 10Mb
This is a quick additional check to protect the user:

- From getting a CloudFront 502 error if the file takes too
long to upload. I was surprised to find it takes about 1 minute
to upload a 70Mb file to S3.*

- From getting a CloudFront 502 error when we follow the redirect
and run through the slow processing code in utils that builds a
RecipientCSV [1].

For context, a CSV with 100K rows and a few columns is around 5Mb,
so a 10Mb limit should be enough. Analysis over the past week shows
that the vast majority of CSV uploads are actually < 2.5Mb.

I haven't added any tests for this because:

- The check isn't critical, as the worst case scenario is the user
gets a worse error than this in-app one.

- There's no easy way to mock the validation, and I didn't want to
have a test that depends on a 10Mb+ file.

*We're using "key.put" to upload the file, when we could be doing
a multipart upload [2]. However, I tried this myself with a chunk
size of 1000 bytes and found it only led to a marginal improvement.

[1]: https://github.com/alphagov/notifications-utils/pull/930
[2]: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html
2021-12-07 15:33:34 +00:00
David McDonald
925f86aa70 Merge pull request #4088 from alphagov/security-policy
Add security policy page
2021-12-07 15:29:33 +00:00
Chris Hill-Scott
b34a9f2c91 Merge pull request #4091 from alphagov/fix-combining-polygons-from-multiple-areas
Don’t combine polygons with different projections
2021-12-07 15:13:45 +00:00
Chris Hill-Scott
fb441e1f09 Merge pull request #4084 from alphagov/dont-confirm-password-service-name-change
Don’t force users to re-enter their password when renaming a service
2021-12-07 15:02:21 +00:00
David McDonald
fea5596234 Add security policy page
This follows the guidance in
https://gds-way.cloudapps.digital/standards/vulnerability-disclosure.html#vulnerability-disclosure-and-security-txt
2021-12-07 14:53:42 +00:00
Chris Hill-Scott
bf15488095 Rename test to remove ‘confirmation’ 2021-12-07 14:30:56 +00:00
Chris Hill-Scott
99a8a4fd48 Don’t combine polygons with different projections
When we combine simplified polygons from different areas we try to use
the polygons that are defined in metres as a speed optimisation.

This doesn’t work when those polygons are in several different
projections because the distance in metres is relative to the edge of
the projection. Just naively choosing one projection means that some
of the polygons will shift position on the earth by 100s of kilometers
once they are converted back to degrees.

To avoid this we need to:
- check for situations where we have polygons in multiple different
  projections
- transforms these polygons back into degrees and let `Polygons` pick a
  common projection for all of them before doing any
  merging/smoothing/etc.
2021-12-07 14:16:54 +00:00
David McDonald
2767328e79 Reduce impact of stale cache for performance page
I came across a bug where the performance page might be visited
on say the 22nd and we expect it to show data for yesterday and
the past 7 days (so the 21st and back 7 days) but instead it
only shows it for the 20th and then back 6 days.

The cause is that we have nightly tasks that run to
calculate the number of notifications sent per service (the
ft_notification_status table)
calculate the number of notifications sent within 10 seconds
(the ft_processing_time table)
Both of these tables get filled between the hours of midnight and
2:30am. The first seems to be filled by about 12:30 every night
whereas the processing stats seems to be filled about 2am every
night.

The admin app currently caches the results of the call to the API
(https://github.com/alphagov/notifications-api/blob/master/app/performance_dashboard/rest.py#L24)
to get this data with the key
performance-stats-{start_date}-to-{end_date}.

Now the issue here is that if the performance page is visited at
00:01 on the 23rd, it will call the API for data on the 22nd and
backwards 7 days. The data it gets at 00:01 will not yet have the
data for the 22nd, it will only go as far as the 21st, because
the overnight jobs to put data in the tables have not run yet. The
admin app then caches this data, meaning that for the rest of the
day the page will be missing data for the 22nd, even though it
becomes available after approx 2am. We have seen it a few times
in production where the performance page has indeed been visited
before say 2 am, leaving the page with missing data.

In terms of solutions, there are several potential options.

1. Remove the caching that we do in redis. The downside of this is
that we will hit the API more (currently once a day for the first
visitor to the performance page). We have had 255 requests
to the performance page in the last week and when there is no value
in redis, the call to the API takes approximately 1-2 seconds.
Removing the caching would against why the caching was originally
added which was to act as a basic protection against malicious
DOS attempts.

2. Make the admin app only set the cache value if it is after
2:30am. This one feels a bit gross and snowflakey.

3. The API flushes the redis cache after it has finished its nightly
tasks. We don't have that much precedent of the API interacting
with redis, it is mostly the admin app that does but this is still
a valid option.

4. Cache in redis the data for 2 days ago to 7 days ago and then
get the data for yesterday freshly every time. This would mean
some things are still cached but the smallest bit that we can't rely
on can be gathered fresh.

5. Remove the caching we do in redis but then try and optimise the
API endpoint to return results even faster and with less
interaction with the DB. My hypothesis is that the slowest part
is where the API has to calculate how many notifications Notify
has ever sent
(https://github.com/alphagov/notifications-api/blob/master/app/performance_dashboard/rest.py#L36)
and so we could potentially try and store these totals in the DB
every night and update them nightly rather than having to query all
the data in the table to figure them out every time.

6. Reduce the expiry time of the cache key so although the bug will
still exist, it will only exist for a much shorter time.

In the end, we've gone for option 6. The user impact of
this bug sticking around for an hour is minimal, in particular
because that would be in the early hours of the morning. The solution
is also quick to implement and keeps the protection against a DOS attack.

The value of 1 hour for expiry was a fairly abitrary choice, it could
have been as little as 1 minute or as much as 6 hours.
2021-12-07 12:44:36 +00:00
Chris Hill-Scott
787cb3ef1f Merge pull request #3994 from alphagov/update-utils-coordinate-transformation
Update utils to bring in coordinate transformation
2021-12-07 11:07:07 +00:00
Ben Thorner
92549fd2d6 Show flash instead of inline upload errors
This has several advantages:

- It gives us more room to explain the error and actions. This will
be useful for upcoming work we want to do, which will add yet more
validations for CSV uploads.

- We already use a flash to show certain kinds of errors on these
pages (just above). This is more consistent.

- It's potentially more accessible. Previously the error and the
button text used to be read out as a single sentence. Now the page
reloads and reads the flash error alone.

In theory we should show an error in both places, but this can be
confusing on pages where there's only a single form control, and
especially if the error is long.
2021-12-06 17:12:27 +00:00
Ben Thorner
4a5345f011 Move Spreadsheet models tests into own file
Previously this class was in app/utils.py, so it made sense for the
tests to be in "utils/test_csv.py". Since the class is now a proper
model [1], we can also move the tests into their own file.

[1]: 2c46d023da (diff-ac7b8d56e509c921efaadb5a776e1c9037531c4d2af78787f06f67a1f3533ae4)
2021-12-03 17:17:15 +00:00
Ben Thorner
c0da7a27ed Fix not showing errors for invalid contact uploads
This code should behave the same way as other CSV uploads [1],
but we had to write it in a hurry [2] and the way we show an
error with the upload field was based off that for PDF uploads,
where we show custom button text instead of an error [3].

This fixes the inconsistency, so that we see the same errors
for CSV uploads here as in other parts of the app.

[1]: 6b52735dac/app/templates/views/send.html (L25)
[2]: 1c02476ee7 (diff-aedd12af78c9737f1c3344d2afbb9c00878eccbcc754b2b3d9e6864c2ad2f7c3R32)
[3]: 3b3f74bbf0
2021-12-01 16:59:30 +00:00
Chris Hill-Scott
1190e4541b Remove re-enter password step from rename service
The original idea behind was to always ask users to re-enter their
password any time:
- we want them to be sure that they want to do what they’re about to do
- we want to be sure it’s really the user trying to do the thing (and
  not someone malicious)

In reality we:
- removed this from the initial place it was added (a descendent of the
  ‘suspend service’ feature)
- only ever added it to the ‘rename service’ feature

So in reality it’s not a pattern we have persisted with. Arguably there
are several things you can now do in the admin app without re-entering
your password which are much more high consequence than changing the
service name.

Also, with browser autofill there’s a lot less chance that forcing
someone to re-enter a password really gives much defence against an
unatteneded laptop, for example.

I also wonder whether we might get people to give better service names
if we make the process of renaming the service less intimidating.

So this commit removes the need to re-enter your password when renaming
a service.

Note that re-naming an organisation still has the same check, but I
haven’t removed that too for the sake of keeping scope of the PR small.
2021-12-01 15:25:53 +00:00
Chris Hill-Scott
0cf443e9a6 Use already-transformed polygons wherever possible
Transforming full resolution polygons to linear coordinates is somewhat
expensive. We can make things run faster by:
- looking at `simple_polygons` which have fewer points and are therefore
  faster to transform.
- reusing polygons that have already been transformed where possible
2021-12-01 14:10:55 +00:00