Skip to content

Commit

Permalink
feat: add test to forgot password
Browse files Browse the repository at this point in the history
  • Loading branch information
Aydawka committed Jul 15, 2024
1 parent fb89848 commit 622865f
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 10 deletions.
36 changes: 26 additions & 10 deletions apis/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from flask import g, make_response, request, Response
from flask_restx import Namespace, Resource, fields
from jsonschema import FormatChecker, ValidationError, validate

import model
from invitation.invitation import reset_password, forgot_password

Expand Down Expand Up @@ -581,8 +582,8 @@ def validate_is_valid_email(instance):
if not user:
raise ValidationError("User associated with this email does not exist")

expired_in = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(
minutes=50
expired_in = get_now() + datetime.timedelta(
minutes=5
)
jti = str(uuid.uuid4())
reset_token = jwt.encode(
Expand All @@ -605,7 +606,11 @@ def validate_is_valid_email(instance):
forgot_password(email_address, first_name, last_name, reset_token)
user.update_password_reset(reset_token)
model.db.session.commit()
return "email is sent successfully", 200

response = make_response("email is sent successfully", 200)
if os.environ.get("FLASK_ENV") == "testing":
response.headers.add("X-Token", reset_token)
return response


@api.route("/auth/reset-password")
Expand Down Expand Up @@ -633,17 +638,14 @@ def post(self):
try:
decoded = jwt.decode(data["token"], config.FAIRHUB_SECRET, algorithms=["HS256"])
except (jwt.ExpiredSignatureError, jwt.DecodeError, jwt.InvalidSignatureError):
return Response(status=403)
return Response(status=401)
user = model.User.query.filter(model.User.email_address == decoded["email"]).first()
if not user:
raise ValidationError("Email doesnt exist")

# def validate_current_password(instance):
# new_password = data["new_password"]
#
# if not g.user.check_password(instance["new_password"]):
# raise ValidationError("choose different password")
# return True
validate_pass = user.check_password(data["new_password"])
if validate_pass:
return "old and new password can not be same. Please select a new one", 422

def confirm_new_password(instance):
new_password = data["new_password"]
Expand Down Expand Up @@ -696,3 +698,17 @@ def confirm_new_password(instance):
)

return "Password reset successfully", 200


frozen_date: Union[datetime.datetime, None] = None


def set_now(now: Union[datetime.datetime, None]) -> None:
global frozen_date
frozen_date = now


def get_now() -> datetime.datetime:
if frozen_date:
return frozen_date
return datetime.datetime.now(datetime.timezone.utc)
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
pytest.global_viewer_token = ""


pytest.global_reset_token = ""


# Create the flask app for testing
@pytest.fixture(scope="session")
def flask_app():
Expand Down Expand Up @@ -269,6 +272,7 @@ def clients(flask_app):
_admin_client = flask_app.test_client()
_editor_client = flask_app.test_client()
_viewer_client = flask_app.test_client()
# _test_client = flask_app.test_client()

with unittest.mock.patch("pytest_config.TestConfig", TestConfig):
response = _logged_in_client.post(
Expand Down
129 changes: 129 additions & 0 deletions tests/functional/test_user.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import datetime

from apis.authentication import set_now
from model.db import db


# ------------------- Password Change ------------------- #


Expand Down Expand Up @@ -118,6 +122,131 @@ def test_post_login_new_password(clients):
assert len(session_entries) == 1


def test_post_reset_password(flask_app):
"""
Given a Flask application configured for testing
WHEN the '/auth/password/reset-password' endpoint is requested (POST)
THEN check that the response is valid and the password is changed
"""
_test_client = flask_app.test_client()

forgot_response = _test_client.post(
"/auth/forgot-password",
json={
"email_address": "[email protected]",

},
)
assert forgot_response.status_code == 200

token = forgot_response.headers["X-Token"]
assert token is not None

reset_response = _test_client.post(
"/auth/reset-password",
json={
"token": token,
"confirm_password": "Updatedpassword4testing!1",
"new_password": "Updatedpassword4testing!1",
},
)
assert reset_response.status_code == 200

response = _test_client.post(
"/auth/login",
json={
"email_address": "[email protected]",
"password": "Updatedpassword4testing!1",
},
)

assert response.status_code == 200
logout_response = _test_client.post(
"/auth/logout"
)
assert logout_response.status_code == 204


def test_post_reset_password_is_not_same_old(flask_app):
"""
Given a Flask application configured for testing
WHEN the '/auth/password/reset-password' endpoint is requested (POST)
THEN check that the response is valid and the password is changed
"""
_test_client = flask_app.test_client()

forgot_response = _test_client.post(
"/auth/forgot-password",
json={
"email_address": "[email protected]",

},
)
assert forgot_response.status_code == 200

token = forgot_response.headers["X-Token"]
assert token is not None

reset_response = _test_client.post(
"/auth/reset-password",
json={
"token": token,
"confirm_password": "uniquepassword4testing!",
"new_password": "uniquepassword4testing!",
},
)

assert reset_response.status_code == 200

reset_response_old = _test_client.post(
"/auth/reset-password",
json={
"token": token,
"confirm_password": "uniquepassword4testing!",
"new_password": "uniquepassword4testing!",
},
)

assert reset_response_old.status_code == 422


def test_post_reset_password_expired(flask_app):
"""
Given a Flask application configured for testing
WHEN the '/auth/password/reset-password' endpoint is requested (POST)
THEN check that the response is valid and the password is changed
"""
_test_client = flask_app.test_client()

set_now(datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(
minutes=6
))
forgot_response = _test_client.post(
"/auth/forgot-password",
json={
"email_address": "[email protected]",

},
)
set_now(None)

assert forgot_response.status_code == 200

token = forgot_response.headers["X-Token"]

assert token is not None

reset_response = _test_client.post(
"/auth/reset-password",
json={
"token": token,
"confirm_password": "Updatedpassword4testing!",
"new_password": "Updatedpassword4testing!",
},
)
assert reset_response.status_code == 401


def test_post_logout(clients):
"""
Given a Flask application configured for testing
Expand Down

0 comments on commit 622865f

Please sign in to comment.