From 7abb977dfe6edc6c18b1dbb05b3f53c6c57c78f5 Mon Sep 17 00:00:00 2001 From: ebreton Date: Fri, 12 Apr 2019 20:51:16 +0200 Subject: [PATCH 1/7] removed postgres_password from alembic.ini, read it from env var instead --- .../backend/app/alembic.ini | 3 --- .../backend/app/alembic/env.py | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/{{cookiecutter.project_slug}}/backend/app/alembic.ini b/{{cookiecutter.project_slug}}/backend/app/alembic.ini index 61bc2fdcbf..921aaf17b8 100755 --- a/{{cookiecutter.project_slug}}/backend/app/alembic.ini +++ b/{{cookiecutter.project_slug}}/backend/app/alembic.ini @@ -35,9 +35,6 @@ script_location = alembic # are written from script.py.mako # output_encoding = utf-8 -sqlalchemy.url = postgresql://postgres:{{cookiecutter.postgres_password}}@db/app - - # Logging configuration [loggers] keys = root,sqlalchemy,alembic diff --git a/{{cookiecutter.project_slug}}/backend/app/alembic/env.py b/{{cookiecutter.project_slug}}/backend/app/alembic/env.py index ae47ee586c..b7770629dd 100755 --- a/{{cookiecutter.project_slug}}/backend/app/alembic/env.py +++ b/{{cookiecutter.project_slug}}/backend/app/alembic/env.py @@ -1,4 +1,7 @@ from __future__ import with_statement + +import os + from alembic import context from sqlalchemy import engine_from_config, pool from logging.config import fileConfig @@ -27,6 +30,15 @@ # ... etc. +def get_url(): + return "postgresql://%s:%s@%s/%s" % ( + os.getenv("POSTGRES_USER", "postgres"), + os.getenv("POSTGRES_PASSWORD", ""), + os.getenv("POSTGRES_SERVER", "db"), + os.getenv("POSTGRES_DB", "app"), + ) + + def run_migrations_offline(): """Run migrations in 'offline' mode. @@ -39,7 +51,7 @@ def run_migrations_offline(): script output. """ - url = config.get_main_option("sqlalchemy.url") + url = get_url() context.configure( url=url, target_metadata=target_metadata, literal_binds=True, compare_type=True ) @@ -55,8 +67,10 @@ def run_migrations_online(): and associate a connection with the context. """ + configuration = config.get_section(config.config_ini_section) + configuration['sqlalchemy.url'] = get_url() connectable = engine_from_config( - config.get_section(config.config_ini_section), + configuration, prefix="sqlalchemy.", poolclass=pool.NullPool, ) From 14fe548bcab8834274896628a86107e8cdcfde10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Apr 2019 19:48:51 +0400 Subject: [PATCH 2/7] :recycle: use f-strings for PostgreSQL URL --- .../backend/app/alembic/env.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/{{cookiecutter.project_slug}}/backend/app/alembic/env.py b/{{cookiecutter.project_slug}}/backend/app/alembic/env.py index b7770629dd..df37198286 100755 --- a/{{cookiecutter.project_slug}}/backend/app/alembic/env.py +++ b/{{cookiecutter.project_slug}}/backend/app/alembic/env.py @@ -31,12 +31,11 @@ def get_url(): - return "postgresql://%s:%s@%s/%s" % ( - os.getenv("POSTGRES_USER", "postgres"), - os.getenv("POSTGRES_PASSWORD", ""), - os.getenv("POSTGRES_SERVER", "db"), - os.getenv("POSTGRES_DB", "app"), - ) + user = os.getenv("POSTGRES_USER", "postgres") + password = os.getenv("POSTGRES_PASSWORD", "") + server = os.getenv("POSTGRES_SERVER", "db") + db = os.getenv("POSTGRES_DB", "app") + return f"postgresql://{user}:{password}@{server}/{db}" def run_migrations_offline(): From b849bf2816d2cca378c2ac8861432dc08418d035 Mon Sep 17 00:00:00 2001 From: ebreton Date: Sat, 27 Apr 2019 20:35:56 +0200 Subject: [PATCH 3/7] Add byemail_authentication_token in test utils --- .../backend/app/app/core/config.py | 2 ++ .../backend/app/app/tests/utils/user.py | 21 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/{{cookiecutter.project_slug}}/backend/app/app/core/config.py b/{{cookiecutter.project_slug}}/backend/app/app/core/config.py index 07e42b084e..e413c5eaa0 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/core/config.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/core/config.py @@ -51,3 +51,5 @@ def getenv_boolean(var_name, default_value=False): FIRST_SUPERUSER_PASSWORD = os.getenv("FIRST_SUPERUSER_PASSWORD") USERS_OPEN_REGISTRATION = getenv_boolean("USERS_OPEN_REGISTRATION") + +EMAIL_TEST_USER = "test@example.com" diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py index 6a5b947e4a..f6a356e8b2 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py @@ -3,8 +3,8 @@ from app import crud from app.core import config from app.db.session import db_session -from app.models.user import UserCreate -from app.tests.utils.utils import random_lower_string +from app.models.user import UserCreate, UserUpdate +from app.tests.utils.utils import get_server_api, random_lower_string def user_authentication_headers(server_api, email, password): @@ -23,3 +23,20 @@ def create_random_user(): user_in = UserCreate(username=email, email=email, password=password) user = crud.user.create(db_session=db_session, user_in=user_in) return user + + +def byemail_authentication_token(email): + """ + Return a valid token for the user with given email, eventhough the user existed in the first place or not. + + The function generated the User if necessary, and update it with a fresh password otherwise. That allows to use again and again the same user during the test (instead of creating a new one every time), without storing any password in the code. + """ + password = random_lower_string() + user = crud.user.get_by_email(db_session, email=email) + if not user: + user = create_random_user() + else: + user_in = UserUpdate(password=password) + user = crud.user.update(db_session, user=user, user_in=user_in) + + return user_authentication_headers(get_server_api(), email, password) From ce2f673dea85d033bb265e9462a9b90ea9fbc29d Mon Sep 17 00:00:00 2001 From: ebreton Date: Sat, 27 Apr 2019 20:36:17 +0200 Subject: [PATCH 4/7] Add normaluser_token_headers fixture for tests --- .../backend/app/app/tests/conftest.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py index 0e3c044bc9..5b0474f432 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py @@ -1,6 +1,8 @@ import pytest +from app.core import config from app.tests.utils.utils import get_server_api, get_superuser_token_headers +from app.tests.utils.user import byemail_authentication_token @pytest.fixture(scope="module") @@ -11,3 +13,8 @@ def server_api(): @pytest.fixture(scope="module") def superuser_token_headers(): return get_superuser_token_headers() + + +@pytest.fixture(scope="module") +def normaluser_token_headers(): + return byemail_authentication_token(config.EMAIL_TEST_USER) From 13d9eafd3b92768c331ce9998ecd33b053c16978 Mon Sep 17 00:00:00 2001 From: ebreton Date: Sat, 27 Apr 2019 22:47:47 +0200 Subject: [PATCH 5/7] using normaluser_token_headers in test_users --- .../app/app/tests/api/api_v1/test_users.py | 19 ++++++++++++++----- .../backend/app/app/tests/utils/user.py | 6 +++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py index 119ed219fd..996a893232 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py @@ -20,6 +20,18 @@ def test_get_users_superuser_me(superuser_token_headers): assert current_user["email"] == config.FIRST_SUPERUSER +def test_get_users_normaluser_me(normaluser_token_headers): + server_api = get_server_api() + r = requests.get( + f"{server_api}{config.API_V1_STR}/users/me", headers=normaluser_token_headers + ) + current_user = r.json() + assert current_user + assert current_user["is_active"] is True + assert current_user["is_superuser"] is False + assert current_user["email"] == config.EMAIL_TEST_USER + + def test_create_user_new_email(superuser_token_headers): server_api = get_server_api() username = random_lower_string() @@ -71,16 +83,13 @@ def test_create_user_existing_username(superuser_token_headers): assert "_id" not in created_user -def test_create_user_by_normal_user(): +def test_create_user_by_normal_user(normaluser_token_headers): server_api = get_server_api() username = random_lower_string() password = random_lower_string() - user_in = UserCreate(email=username, password=password) - user = crud.user.create(db_session, user_in=user_in) - user_token_headers = user_authentication_headers(server_api, username, password) data = {"email": username, "password": password} r = requests.post( - f"{server_api}{config.API_V1_STR}/users/", headers=user_token_headers, json=data + f"{server_api}{config.API_V1_STR}/users/", headers=normaluser_token_headers, json=data ) assert r.status_code == 400 diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py index f6a356e8b2..af6b2f0ec4 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py @@ -17,8 +17,8 @@ def user_authentication_headers(server_api, email, password): return headers -def create_random_user(): - email = random_lower_string() +def create_random_user(email=None): + email = email or random_lower_string() password = random_lower_string() user_in = UserCreate(username=email, email=email, password=password) user = crud.user.create(db_session=db_session, user_in=user_in) @@ -34,7 +34,7 @@ def byemail_authentication_token(email): password = random_lower_string() user = crud.user.get_by_email(db_session, email=email) if not user: - user = create_random_user() + user = create_random_user(email=email) else: user_in = UserUpdate(password=password) user = crud.user.update(db_session, user=user, user_in=user_in) From 1900a9751e84966c0f6930968e0ef5ccca132f40 Mon Sep 17 00:00:00 2001 From: ebreton Date: Sun, 28 Apr 2019 08:58:34 +0200 Subject: [PATCH 6/7] do not use create_random_user for normal test user --- .../backend/app/app/tests/utils/user.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py index af6b2f0ec4..997120f6aa 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py @@ -17,8 +17,8 @@ def user_authentication_headers(server_api, email, password): return headers -def create_random_user(email=None): - email = email or random_lower_string() +def create_random_user(): + email = random_lower_string() password = random_lower_string() user_in = UserCreate(username=email, email=email, password=password) user = crud.user.create(db_session=db_session, user_in=user_in) @@ -34,7 +34,8 @@ def byemail_authentication_token(email): password = random_lower_string() user = crud.user.get_by_email(db_session, email=email) if not user: - user = create_random_user(email=email) + user_in = UserCreate(username=email, email=email, password=password) + user = crud.user.create(db_session=db_session, user_in=user_in) else: user_in = UserUpdate(password=password) user = crud.user.update(db_session, user=user, user_in=user_in) From 9b2b193bd97b4cb1f8eb3fe7f49f4c122497ebd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 19 Jan 2020 02:11:17 +0100 Subject: [PATCH 7/7] :art: Update format and names --- .../backend/app/app/tests/api/api_v1/test_users.py | 8 ++++---- .../backend/app/app/tests/conftest.py | 6 +++--- .../backend/app/app/tests/utils/user.py | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py index 996a893232..9204f87554 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/api/api_v1/test_users.py @@ -20,10 +20,10 @@ def test_get_users_superuser_me(superuser_token_headers): assert current_user["email"] == config.FIRST_SUPERUSER -def test_get_users_normaluser_me(normaluser_token_headers): +def test_get_users_normal_user_me(normal_user_token_headers): server_api = get_server_api() r = requests.get( - f"{server_api}{config.API_V1_STR}/users/me", headers=normaluser_token_headers + f"{server_api}{config.API_V1_STR}/users/me", headers=normal_user_token_headers ) current_user = r.json() assert current_user @@ -83,13 +83,13 @@ def test_create_user_existing_username(superuser_token_headers): assert "_id" not in created_user -def test_create_user_by_normal_user(normaluser_token_headers): +def test_create_user_by_normal_user(normal_user_token_headers): server_api = get_server_api() username = random_lower_string() password = random_lower_string() data = {"email": username, "password": password} r = requests.post( - f"{server_api}{config.API_V1_STR}/users/", headers=normaluser_token_headers, json=data + f"{server_api}{config.API_V1_STR}/users/", headers=normal_user_token_headers, json=data ) assert r.status_code == 400 diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py index 5b0474f432..e383ed183f 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/conftest.py @@ -2,7 +2,7 @@ from app.core import config from app.tests.utils.utils import get_server_api, get_superuser_token_headers -from app.tests.utils.user import byemail_authentication_token +from app.tests.utils.user import authentication_token_from_email @pytest.fixture(scope="module") @@ -16,5 +16,5 @@ def superuser_token_headers(): @pytest.fixture(scope="module") -def normaluser_token_headers(): - return byemail_authentication_token(config.EMAIL_TEST_USER) +def normal_user_token_headers(): + return authentication_token_from_email(config.EMAIL_TEST_USER) diff --git a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py index 997120f6aa..82931d6d23 100644 --- a/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py +++ b/{{cookiecutter.project_slug}}/backend/app/app/tests/utils/user.py @@ -25,11 +25,11 @@ def create_random_user(): return user -def byemail_authentication_token(email): - """ - Return a valid token for the user with given email, eventhough the user existed in the first place or not. +def authentication_token_from_email(email): + """ + Return a valid token for the user with given email. - The function generated the User if necessary, and update it with a fresh password otherwise. That allows to use again and again the same user during the test (instead of creating a new one every time), without storing any password in the code. + If the user doesn't exist it is created first. """ password = random_lower_string() user = crud.user.get_by_email(db_session, email=email)