diff --git a/backend/common/database.py b/backend/common/database.py index 361c996..54419ae 100644 --- a/backend/common/database.py +++ b/backend/common/database.py @@ -9,8 +9,6 @@ port = os.environ["POSTGRES_PORT"] database = os.environ["POSTGRES_DB"] -# TABLES = ["Users", "Questions", "Competitions", "Inputs", "Solves"] - def get_connection(): conn = psycopg2.connect( user=user, @@ -396,4 +394,3 @@ def add_user_with_uid(uid, email, username, password): """ cur.execute(query) conn.commit() - diff --git a/backend/routes/user.py b/backend/routes/user.py index 6622666..067b542 100644 --- a/backend/routes/user.py +++ b/backend/routes/user.py @@ -97,6 +97,8 @@ def reset_email_request(): verify_jwt_in_request() except: raise AuthError("Invalid token") +======= +>>>>>>> main diff --git a/backend/test/auth/login_test.py b/backend/test/auth/login_test.py index 104761c..392e678 100644 --- a/backend/test/auth/login_test.py +++ b/backend/test/auth/login_test.py @@ -1,10 +1,13 @@ +from datetime import datetime, timedelta + import pytest +from freezegun import freeze_time # Import for pytest from flask.testing import FlaskClient from test.helpers import clear_all, db_add_user, generate_csrf_header from test.fixtures import app, client - +from test.mock.mock_redis import fake_redis def test_no_users(client): clear_all() @@ -76,6 +79,53 @@ def test_lockout(client): assert response.status_code == 401 +def test_lockout_timing(client): + clear_all() + + db_add_user("asdfghjkl@gmail.com", "asdf", "foobar") + + # Incorrect login 3 times + for _ in range(3): + response = client.post("/auth/login", json={ + "email": "asdfghjkl@gmail.com", + "password": "foobaz" + }) + + assert response.status_code == 401 + + timeout_over = datetime.now() + timedelta(minutes=1, seconds=5) + + # Incorrect login again + with freeze_time(timeout_over): + response = client.post("/auth/login", json={ + "email": "asdfghjkl@gmail.com", + "password": "foobaz" + }) + + assert response.status_code == 401 + + still_timeout = timeout_over + timedelta(minutes=1) + + # Timeout is now 2 minutes + with freeze_time(still_timeout): + response = client.post("/auth/login", json={ + "email": "asdfghjkl@gmail.com", + "password": "foobar" + }) + + assert response.status_code == 401 + + second_timeout_over = still_timeout + timedelta(minutes=1, seconds=5) + + # Timeout is now 2 minutes + with freeze_time(second_timeout_over): + response = client.post("/auth/login", json={ + "email": "asdfghjkl@gmail.com", + "password": "foobar" + }) + + assert response.status_code == 200 + def test_protected_route(client: FlaskClient): clear_all() diff --git a/backend/test/auth/register_verify_test.py b/backend/test/auth/register_verify_test.py index ddc8707..ed4d846 100644 --- a/backend/test/auth/register_verify_test.py +++ b/backend/test/auth/register_verify_test.py @@ -1,16 +1,11 @@ -import email -import os -import poplib import re from datetime import datetime, timedelta -import fakeredis import pytest from freezegun import freeze_time from pytest_mock import mocker # Imports for pytest -import common from test.helpers import clear_all from test.fixtures import app, client from test.mock.mock_mail import mailbox @@ -37,12 +32,10 @@ def test_invalid_token(client): assert response.status_code == 401 # TODO: try working on this, if not feasible delete this test and test manually -@pytest.mark.skip() def test_token_expired(client, mocker): clear_all() - - fake = fakeredis.FakeStrictRedis() - mocker.patch.object(common.redis, "cache", return_value=fake) + + mocker.patch("routes.auth.mail", mailbox) register_response = client.post("/auth/register", json={ "email": "asdfghjkl@gmail.com", @@ -50,18 +43,10 @@ def test_token_expired(client, mocker): "password": "foobar" }) - print(fake.keys()) - assert register_response.status_code == 200 # Check inbox - mailbox = poplib.POP3("pop3.mailtrap.io", 1100) - mailbox.user(os.environ["MAILTRAP_USERNAME"]) - mailbox.pass_(os.environ["MAILTRAP_PASSWORD"]) - - # Check the contents of the email, and harvest the token from there - raw_email = b"\n".join(mailbox.retr(1)[1]) - parsed_email = email.message_from_bytes(raw_email) + parsed_email = mailbox.get_message(-1) # Assuming there's a HTML part for part in parsed_email.walk(): @@ -74,8 +59,6 @@ def test_token_expired(client, mocker): expired_time = datetime.now() + timedelta(hours=2) with freeze_time(expired_time): - print(fake.keys()) - response = client.post("/auth/register/verify", json={ "token": token }) diff --git a/backend/test/fixtures.py b/backend/test/fixtures.py index 033b899..abd4aeb 100644 --- a/backend/test/fixtures.py +++ b/backend/test/fixtures.py @@ -4,13 +4,17 @@ from pytest_mock import mocker from test.mock.mock_mail import mailbox +from test.mock.mock_redis import fake_redis @pytest.fixture() def app(mocker): - # Mock only where the data is being used + # Mock mailbox mocker.patch("app.mail", mailbox) mocker.patch("common.plugins.mail", mailbox) + # Mock redis + mocker.patch("common.redis.cache", fake_redis) + app = create_app({"TESTING": True}) yield app diff --git a/backend/test/helpers.py b/backend/test/helpers.py index 1b83689..44a50cc 100644 --- a/backend/test/helpers.py +++ b/backend/test/helpers.py @@ -47,8 +47,3 @@ def get_cookie_from_header(response, cookie_name): def generate_csrf_header(response): csrf_token = get_cookie_from_header(response, "csrf_access_token")["csrf_access_token"] return {"X-CSRF-TOKEN": csrf_token} - -## EMAIL MOCKING - -def get_emails(): - pass diff --git a/backend/test/mock/mock_redis.py b/backend/test/mock/mock_redis.py new file mode 100644 index 0000000..65257d1 --- /dev/null +++ b/backend/test/mock/mock_redis.py @@ -0,0 +1,3 @@ +import fakeredis + +fake_redis = fakeredis.FakeStrictRedis()