On the ‘find user’ page it says ‘sms_auth’ instead of ‘Text message
code’.
This commit fixes that, and adds a handy formatter so it’s easier to do
the right thing in the future.
Having this as a function which does string parsing and manipulation
surprised me a bit when I was trying to figure out why something wasn’t
working.
It’s more in line with the way we do other config like this (for example
`ASSET_PATH`) to make it a simple config variable, rather than trying to
be clever and guess things based on other config variables.
It’s also less code, and is explicit enough that it doesn’t need tests.
Brings in https://github.com/alphagov/notifications-utils/pull/889/files
At the moment, we are not doing any transformation of features before
applying geometric algorithms to them. This is, in effect, assuming that
the earth is flat.
This new version of utils implements the transformation of our polygons
to a Cartesian plane. In other words, it converts them from being
defined in spherical degrees to metres.
For the admin app this means we need to convert places where the code
expects things to be measured in degrees to work in metres instead.
We give estimates of the area for those who can’t see the map. These
estimates were needlessly precise, gave a false sense of accuracy and
were causing intermittent test failures between different environments.
This commit rounds them in the same way that we round the count of
phones.
This adds Yubico's FIDO2 library and two APIs for working with the
"navigator.credentials.create()" function in JavaScript. The GET
API uses the library to generate options for the "create()" function,
and the POST API decodes and verifies the resulting credential. While
the options and response are dict-like, CBOR is necessary to encode
some of the byte-level values, which can't be represented in JSON.
Much of the code here is based on the Yubico library example [1][2].
Implementation notes:
- There are definitely better ways to alert the user about failure, but
window.alert() will do for the time being. Using location.reload() is
also a bit jarring if the page scrolls, but not a major issue.
- Ideally we would use window.fetch() to do AJAX calls, but we don't
have a polyfill for this, and we use $.ajax() elsewhere [3]. We need
to do a few weird tricks [6] to stop jQuery trashing the data.
- The FIDO2 server doesn't serve web requests; it's just a "server" in
the sense of WebAuthn terminology. It lives in its own module, since it
needs to be initialised with the app / config.
- $.ajax returns a promise-like object. Although we've used ".fail()"
elsewhere [3], I couldn't find a stub object that supports it, so I've
gone for ".catch()", and used a Promise stub object in tests.
- WebAuthn only works over HTTPS, but there's an exception for "localhost"
[4]. However, the library is a bit too strict [5], so we have to disable
origin verification to avoid needing HTTPS for dev work.
[1]: c42d9628a4/examples/server/server.py
[2]: c42d9628a4/examples/server/static/register.html
[3]: 91453d3639/app/assets/javascripts/updateContent.js (L33)
[4]: https://stackoverflow.com/questions/55971593/navigator-credentials-is-null-on-local-server
[5]: c42d9628a4/fido2/rpid.py (L69)
[6]: https://stackoverflow.com/questions/12394622/does-jquery-ajax-or-load-allow-for-responsetype-arraybuffer
This matches the existing performance platform page, and I think is a
bit easier to read for high-level numbers where you don’t need to see
that they’re changing second-by-second.
Note, no option at the moment to set the service broadcast account type
as None, or back to without the broadcast permission. This has been done
for speed of development given the chance of us needing this is very
low. We can add it later if we need to.
As formatters we can use them in Jinja or Python code.
It also means we don’t need to import them every time we want to use
them – they’re always available in the template context.
For now this doesn’t remove the macros, it just aliases them to the
formatters. This gives us confidence that the formatters are working the
same way the old macros did, and reduces the diff size of each commit.
We have lots of functions for converting various types of data into
strings to be displayed to the user somewhere.
This commit collects all these functions into their own module, rather
than having them cluttering up `app/__init__.py` or buried amongst
various other things that have ended up in `app/utils.py`.
We added this code in
https://github.com/alphagov/notifications-admin/pull/3371/files to
account for Flask Login renaming its cookies. We wanted our apps to be
compatible with the old and new names, so people didn’t get logged out
when we rolled out the change.
Now that all the cookies with the old names will have expired (some
weekends have passed since March) we can remove this loop.
When looking at Google’s PageSpeed Insights tool as part of the
compression work I noticed a suggestion that we preload our font files.
The tool suggests this should save about 300ms on first page load time.
***
Our font files are referenced from our CSS. This means that the browser
has to download and parse the CSS before it knows where to find the font
files. This means the requests happen in sequence.
We can make the requests happen in parallel by using a `<link>` tag with
`rel=preload`. This tells the browser to start downloading the fonts
before it’s even started downloading the CSS (the CSS will be the next
thing to start downloading, since it’s the next `<link>` element in the
head of the HTML).
Downloading fonts before things like images is important because once
the font is downloaded it causes the layout to repaint, and shift
everything around. So the page doesn’t feel stable until after the fonts
have loaded.
Google call this [cumulative layout shift](https://web.dev/cls/) which
is a score for how much the page moves around. A lower score means a
better experience (and, less importantly for us, means the page might
rank higher in search results)
We’re only preloading the WOFF2 fonts because only modern browsers
support preload, and these browsers also all support WOFF2.
We set an empty `crossorigin` attribute (which means anonymous-mode)
because the preload request needs to match the origin’s CORS mode. See
https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content#CORS-enabled_fetches
for more details.
We set `as=font` because this helps the browser use the correct content
security policy, and prioritise which requests to make first.