See c31264d4c for why ‘whitelist’ should be avoided. The use of
whitelist here was not referring to the user-maintained list, but to
mean ‘not a government’ email address. This commit renames these tests
to make that difference clear.
Stopped fixtures in conftest.py from calling the fixtures which return
user json as if they were functions. Deleted two fixtures that are now no
longer needed as a result of the changes to conftest.py.
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
we were seeing isort produce different outputs locally and in docker -
this was due to it having different opinions about whether the tests
module (ie all our unit tests) is a first party (local) or third party
(pip installed) import. It's a first party import, so by defining this
in the setup.cfg isort settings, we can force it to be consistent
between environments.
Note: I don't know why it was different in the first place though
Done using isort[1], with the following command:
```
isort -rc ./app ./tests
```
Adds linting to the `run_tests.sh` script to stop badly-sorted imports
getting re-introduced.
Chosen style is ‘Vertical Hanging Indent’ with trailing commas, because
I think it gives the cleanest diffs, eg:
```
from third_party import (
lib1,
lib2,
lib3,
lib4,
)
```
1. https://pypi.python.org/pypi/isort
We have a bunch of different styles of handling when function
definitions span multiple lines, which they almost always do with tests.
Here’s why an argument per line, single indent is best:
- cleaner diffs when you change the name of a method (one line change
instead of multiple lines)
- works better on narrow screens, eg Github’s diff view, or with two
terminals side by side on a laptop screen
- works with any editor’s indenting shortcuts, no need for an IDE
Also, trailing comma in the list of arguments is good because adding a
new argument to a method becomes a one line, not two line diff.
https://www.pivotaltracker.com/story/show/113840073
Previously the forgot password page would give an error if you entered an email
address which didn’t belong to an account.
This would allow a potential attacker to know which email addresses were
registered.
This commit changes the response to always be the same, whether or not the email
address exists.
Also, this is a good read about the dangers of asserting whether a mocked method
was called: http://engineeringblog.yelp.com/2015/02/assert_called_once-threat-or-menace.html
Which means the user will only be able to reset their password, and not sign-in.
Once the user resets the password the user state is set to active once more.
If the link is used a second time they will be redirected to the index page with a message
that the link in the email is not longer valid.
Refactored the forms so that fields like email_address can be used in multiple forms.
Refactored form validation so that a query function is passed into the form to be run, this
way the form is not exposed to the dao layer and the query is more efficient.
This PR still requires some frontend attention. Will work with Chris to update the templates.
Found a way to create the token that does not need to persist it to the database.
This requires proper error messages, written by people who speak menglis good.
Start implementation for new-password endpoints.
Created PasswordResetToken model
ToDo: create and save token, send valid url to user,
check validity of token, update user's password, redirect to /two-factor.