-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add password change confirmation email (#971)
## Fixes issue #947 ## Description of Changes Added an email action that lets the user know that their password has changed and added validation that emails were being sent in the tests. ## Notes for Deployment - The `OO_ADMIN_EMAIL` environment variable needs to be added to the production `.env` file. ## Screenshots (if appropriate) <img width="1074" alt="Screenshot 2023-07-13 at 1 44 06 PM" src="https://github.com/lucyparsons/OpenOversight/assets/5885605/1d0195db-b8fb-4e96-8f20-945a8b0633e7"> ## Tests and linting - [x] This branch is up-to-date with the `develop` branch. - [x] `pytest` passes on my local development environment. - [x] `pre-commit` passes on my local development environment.
- Loading branch information
1 parent
b462294
commit 3606e67
Showing
12 changed files
with
82 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,14 @@ Example `.env` variable: | |
OO_SERVICE_EMAIL="[email protected]" | ||
``` | ||
|
||
In addition to needing a service account email, you also need an admin email address so that users have someone to reach out to if an action is taken on their account that needs to be reversed or addressed. | ||
For production, save the email address associated with your admin account to a variable named `OO_HELP_EMAIL` in a `.env` file in the base directory of this repository. For development and testing, update the `OO_HELP_EMAIL` variable in the `docker-compose.yml` file. | ||
|
||
Example `.env` variable: | ||
```bash | ||
OO_HELP_EMAIL="[email protected]" | ||
``` | ||
|
||
## Testing S3 Functionality | ||
We use an S3 bucket for image uploads. If you are working on functionality involving image uploads, | ||
then you should follow the "S3 Image Hosting" section in [DEPLOY.md](/DEPLOY.md) to make a test S3 bucket | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
OpenOversight/app/templates/auth/email/change_password.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<p>Dear {{ user.username }},</p> | ||
<p>Your password has just been changed.</p> | ||
<p>If you initiated this change to your password, you can ignore this email.</p> | ||
<p> | ||
If you did not reset your password, please contact <a href="mailto:{{ help_email }}">the OpenOversight help account</a>; they will help you address this issue. | ||
</p> | ||
<p>Sincerely,</p> | ||
<p>The OpenOversight Team</p> | ||
<p> | ||
<small>Please note that we may not monitor replies to this email address.</small> | ||
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# Routing and view tests | ||
from http import HTTPStatus | ||
from unittest import TestCase | ||
from urllib.parse import urlparse | ||
|
||
import pytest | ||
|
@@ -141,8 +142,10 @@ def test_user_cannot_register_if_passwords_dont_match(mockdata, client, session) | |
|
||
|
||
def test_user_can_register_with_legit_credentials(mockdata, client, session): | ||
with current_app.test_request_context(): | ||
diceware_password = "operative hamster perservere verbalize curling" | ||
with current_app.test_request_context(), TestCase.assertLogs( | ||
current_app.logger | ||
) as log: | ||
diceware_password = "operative hamster persevere verbalize curling" | ||
form = RegistrationForm( | ||
email="[email protected]", | ||
username="redshiftzero", | ||
|
@@ -154,6 +157,10 @@ def test_user_can_register_with_legit_credentials(mockdata, client, session): | |
) | ||
|
||
assert b"A confirmation email has been sent to you." in rv.data | ||
assert ( | ||
f"{current_app.config['OO_MAIL_SUBJECT_PREFIX']} Confirm Your Account" | ||
in str(log.output) | ||
) | ||
|
||
|
||
def test_user_cannot_register_with_weak_password(mockdata, client, session): | ||
|
@@ -172,16 +179,24 @@ def test_user_cannot_register_with_weak_password(mockdata, client, session): | |
|
||
|
||
def test_user_can_get_a_confirmation_token_resent(mockdata, client, session): | ||
with current_app.test_request_context(): | ||
with current_app.test_request_context(), TestCase.assertLogs( | ||
current_app.logger | ||
) as log: | ||
login_user(client) | ||
|
||
rv = client.get(url_for("auth.resend_confirmation"), follow_redirects=True) | ||
|
||
assert b"A new confirmation email has been sent to you." in rv.data | ||
assert ( | ||
f"{current_app.config['OO_MAIL_SUBJECT_PREFIX']} Confirm Your Account" | ||
in str(log.output) | ||
) | ||
|
||
|
||
def test_user_can_get_password_reset_token_sent(mockdata, client, session): | ||
with current_app.test_request_context(): | ||
with current_app.test_request_context(), TestCase.assertLogs( | ||
current_app.logger | ||
) as log: | ||
form = PasswordResetRequestForm(email="[email protected]") | ||
|
||
rv = client.post( | ||
|
@@ -191,12 +206,18 @@ def test_user_can_get_password_reset_token_sent(mockdata, client, session): | |
) | ||
|
||
assert b"An email with instructions to reset your password" in rv.data | ||
assert ( | ||
f"{current_app.config['OO_MAIL_SUBJECT_PREFIX']} Reset Your Password" | ||
in str(log.output) | ||
) | ||
|
||
|
||
def test_user_can_get_password_reset_token_sent_with_differently_cased_email( | ||
mockdata, client, session | ||
): | ||
with current_app.test_request_context(): | ||
with current_app.test_request_context(), TestCase.assertLogs( | ||
current_app.logger | ||
) as log: | ||
form = PasswordResetRequestForm(email="[email protected]") | ||
|
||
rv = client.post( | ||
|
@@ -206,6 +227,10 @@ def test_user_can_get_password_reset_token_sent_with_differently_cased_email( | |
) | ||
|
||
assert b"An email with instructions to reset your password" in rv.data | ||
assert ( | ||
f"{current_app.config['OO_MAIL_SUBJECT_PREFIX']} Reset Your Password" | ||
in str(log.output) | ||
) | ||
|
||
|
||
def test_user_can_get_reset_password_with_valid_token(mockdata, client, session): | ||
|
@@ -361,7 +386,9 @@ def test_user_can_not_confirm_account_with_invalid_token(mockdata, client, sessi | |
|
||
|
||
def test_user_can_change_password_if_they_match(mockdata, client, session): | ||
with current_app.test_request_context(): | ||
with current_app.test_request_context(), TestCase.assertLogs( | ||
current_app.logger | ||
) as log: | ||
login_user(client) | ||
form = ChangePasswordForm( | ||
old_password="dog", password="validpasswd", password2="validpasswd" | ||
|
@@ -372,6 +399,10 @@ def test_user_can_change_password_if_they_match(mockdata, client, session): | |
) | ||
|
||
assert b"Your password has been updated." in rv.data | ||
assert ( | ||
f"{current_app.config['OO_MAIL_SUBJECT_PREFIX']} Your Password Has Changed" | ||
in str(log.output) | ||
) | ||
|
||
|
||
def test_unconfirmed_user_redirected_to_confirm_account(mockdata, client, session): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ services: | |
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}" | ||
ENV: "${ENV:-development}" | ||
FLASK_APP: OpenOversight.app | ||
OO_HELP_EMAIL: "[email protected]" | ||
OO_SERVICE_EMAIL: "[email protected]" | ||
S3_BUCKET_NAME: "${S3_BUCKET_NAME}" | ||
volumes: | ||
|