Finish password expiration#224
Conversation
Add mgmt command for setting user-specific password expiry. Add documentation for password expiry.
Revise model migration. Add user_password_history command. Add management command tests. Improve password tests. Add Django admin functionality for new PasswordExpiry and PasswordHistory models.
Use middleware to detect password expiration and redirect to password change page if expired. Added to CHANGELOG.md. Removed outdated docs/changelog.rst. Added documentation for password middleware.
Add "Password is expired" message. Add `password_expired` signal. Update signals documentation.
Improve verbose plural model name.
If middleware detects expired password, add "?next=" to redirect URL with expected page.
Improve creation of redirect URL with "next" value.
3 similar comments
|
@brosner this is complete and ready for final thorough review, thanks! |
|
Hmm, seems like we need management command documentation. |
3 similar comments
|
@brosner besides code review you can test this for real by cloning the latest cloudspotting "dua-password-expiry" branch, pinax/cloudspotting#14, currently found at: Install and run cloudspotting as per docs (specifying latest hash of that branch), create a couple users, play around with management commands |
grahamu
left a comment
There was a problem hiding this comment.
These areas would appreciate thoughtful consideration, thanks.
| user.password_expiry.expiry = expire | ||
| user.password_expiry.save() | ||
|
|
||
| return "User \"{}\" password expiration set to {} seconds".format(username, expire) |
There was a problem hiding this comment.
This handle_label method works fine for one or a handful of users, but doesn't scale nicely for a large userbase or for all users in a system. Should we improve this mechanism or leave be until someone complains?
There was a problem hiding this comment.
I'm not sure of the particulars of the use case driving these changes, but I think it'd be useful to set an expiration for all users if
- adding the middleware to an existing project using DUA and wanting to set a "baseline" expiration for all existing users
- enforcing a reset for all users in response to some kind of security breach
I don't have a strong opinion on that functionality being required from the get-go, and perhaps a new issue to track that functionality is useful and it can be added later when required.
There was a problem hiding this comment.
@jwegner your first point is handled by the global setting ACCOUNT_PASSWORD_EXPIRY, which is used by default if password expiration is enabled and the user does not have their own PasswordExpiry instance. Good thought on the second case, but I'd prefer to track the idea separately.
| messages.WARNING, | ||
| _("Your password has expired. Please save a new password.") | ||
| ) | ||
| redirect_field_name = "next" # fragile! |
There was a problem hiding this comment.
This redirect field name reference ("next") is quite fragile because if the project uses a different string this will break. Note that the redirect field name in classes protected by LoginRequiredMixin and methods protected by login_required default to "next" but can be overridden by class attribute or by invocation parameter. However this code is middleware with no way to set/reset the redirect field name.
To resolve this fragility I suggest using an account global, something like ACCOUNT_REDIRECT_FIELD_NAME.
There was a problem hiding this comment.
I agree with removing fragility and standardizing that field name.
We might consider relying on / aliasing from django.contrib.auth.REDIRECT_FIELD_NAME, but still allowing the the overrides on the existing classes/methods above.
So REDIRECT_FIELD_NAME is the default unless overridden.
| ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| ('password', models.CharField(max_length=255)), | ||
| ('timestamp', models.DateTimeField(auto_now=True)), | ||
| ('timestamp', models.DateTimeField(default=django.utils.timezone.now)), |
There was a problem hiding this comment.
auto_now=True does not work for timestamp field because we need to set the timestamp explicitly when creating PasswordHistory via management command.
| --- | ||
|
|
||
| * initial release | ||
| * if migrating from Pinax; see :ref:`migration` |
There was a problem hiding this comment.
This file appeared to be an orphan, superseded by /CHANGELOG.md.
Allow customization, but use REDIRECT_FIELD_NAME as default.
|
@jacobwegner how does this look with regard to next page redirect? |
brosner
left a comment
There was a problem hiding this comment.
I am happy with the direction here. This will be an excellent addition to DUA 2.0.
This pull request completes password expiration functionality.