diff --git a/.env_template b/.env_template index dde04ba..d75b365 100644 --- a/.env_template +++ b/.env_template @@ -6,14 +6,8 @@ DB_USER= DB_PASS= DB_NAME= -TEST_DB_HOST= -TEST_DB_PORT= -TEST_DB_USER= -TEST_DB_PASS= -TEST_DB_NAME= - -SECRET_KEY= -ALGORITHM= +JWT_SECRET_KEY= +JWT_ALGORITHM= REDIS_HOST= REDIS_PORT= diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index da11493..3ed2934 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -16,6 +16,35 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Generating .env + run: | + touch .env + echo MODE=${{ secrets.MODE }} >> .env + echo DB_HOST=${{ secrets.DB_HOST }} >> .env + echo DB_PORT=${{ secrets.DB_PORT }} >> .env + echo DB_USER=${{ secrets.DB_USER }} >> .env + echo DB_PASS=${{ secrets.DB_PASS }} >> .env + echo DB_NAME=${{ secrets.DB_NAME }} >> .env + echo SECRET_KEY=${{ secrets.SECRET_KEY }} >> .env + echo ALGORITHM=${{ secrets.ALGORITHM }} >> .env + echo REDIS_HOST=${{ secrets.REDIS_HOST }} >> .env + echo REDIS_PORT=${{ secrets.REDIS_PORT }} >> .env + echo REDIS_DB=${{ secrets.REDIS_DB }} >> .env + echo MONGO_HOST=${{ secrets.MONGO_HOST }} >> .env + echo MONGO_PORT=${{ secrets.MONGO_PORT }} >> .env + echo SMTP_HOST=${{ secrets.SMTP_HOST }} >> .env + echo SMTP_PORT=${{ secrets.SMTP_PORT }} >> .env + echo SMTP_USER=${{ secrets.SMTP_USER }} >> .env + echo SMTP_PASS=${{ secrets.SMTP_PASS }} >> .env + echo IMAGE_UPLOAD_SERVER=${{ secrets.IMAGE_UPLOAD_SERVER }} >> .env + echo INVITATION_LINK_HOST=${{ secrets.INVITATION_LINK_HOST }} >> .env + echo INVITATION_LINK_TOKEN_KEY=${{ secrets.INVITATION_LINK_TOKEN_KEY }} >> .env + echo SENTRY_DSN=${{ secrets.SENTRY_DSN }} >> .env + echo ADMIN_USER=${{ secrets.ADMIN_USER }} >> .env + echo ADMIN_USER_ID=${{ secrets.ADMIN_USER_ID }} >> .env + echo REGISTRATED_USER=${{ secrets.REGISTRATED_USER }} >> .env + echo VERIFICATED_USER=${{ secrets.VERIFICATED_USER }} >> .env + - name: Build and push backend uses: https://git.urec56.ru/urec/build-push-action@v6 with: diff --git a/app/config.py b/app/config.py index 4fea28f..4456e70 100644 --- a/app/config.py +++ b/app/config.py @@ -14,14 +14,8 @@ class Settings(BaseSettings): DB_PORT: str DB_NAME: str - TEST_DB_HOST: str - TEST_DB_PORT: str - TEST_DB_USER: str - TEST_DB_PASS: str - TEST_DB_NAME: str - - SECRET_KEY: str - ALGORITHM: str + JWT_SECRET_KEY: str + JWT_ALGORITHM: str REDIS_HOST: str REDIS_PORT: int diff --git a/app/database.py b/app/database.py index 36dff6e..9d6ee06 100644 --- a/app/database.py +++ b/app/database.py @@ -5,16 +5,10 @@ from sqlalchemy.orm import DeclarativeBase, sessionmaker from app.config import settings -if settings.MODE == "TEST": - DATABASE_URL = f"""postgresql+asyncpg://{settings.TEST_DB_USER}: - {settings.TEST_DB_PASS}@{settings.TEST_DB_HOST}: - {settings.TEST_DB_PORT}/{settings.TEST_DB_NAME}""" - DATABASE_PARAMS = {"poolclass": NullPool} -else: - DATABASE_URL = f"""postgresql+asyncpg://{settings.DB_USER}: - {settings.DB_PASS}@{settings.DB_HOST}: - {settings.DB_PORT}/{settings.DB_NAME}""" - DATABASE_PARAMS = {"pool_size": 50, "pool_pre_ping": True} +DATABASE_URL = f"""postgresql+asyncpg://{settings.DB_USER}: + {settings.DB_PASS}@{settings.DB_HOST}: + {settings.DB_PORT}/{settings.DB_NAME}""" +DATABASE_PARAMS = {"pool_size": 50, "pool_pre_ping": True} engine = create_async_engine(DATABASE_URL, **DATABASE_PARAMS) diff --git a/docker/Dockerfile_back b/docker/Dockerfile_back index 81d0955..409df7f 100644 --- a/docker/Dockerfile_back +++ b/docker/Dockerfile_back @@ -1,4 +1,4 @@ -FROM quay.io/urec56/python312 +FROM git.urec56.ru/urec/python:3.12-alpine RUN addgroup --system app && adduser --system --group app @@ -6,14 +6,14 @@ ENV APP_HOME=/home/app WORKDIR $APP_HOME -RUN apt-get update \ - && apt-get -y install curl gcc libpq-dev \ - && apt-get clean +# RUN apt-get update \ +# && apt-get -y install curl gcc libpq-dev \ +# && apt-get clean COPY requirements.txt . RUN pip config set global.trusted-host "pypi.python.org pypi.org files.pythonhosted.org" && \ - pip install -r requirements.txt + pip install --no-cache-dir -r requirements.txt COPY . . diff --git a/docker/Dockerfile_celery b/docker/Dockerfile_celery index 7eb0621..55f6f0f 100644 --- a/docker/Dockerfile_celery +++ b/docker/Dockerfile_celery @@ -1,4 +1,4 @@ -FROM quay.io/urec56/python312 +FROM git.urec56.ru/urec/python:3.12-alpine RUN addgroup --system app && adduser --system --group app @@ -6,14 +6,14 @@ ENV APP_HOME=/home/app WORKDIR $APP_HOME -RUN apt-get update \ - && apt-get -y install curl gcc libpq-dev \ - && apt-get clean +# RUN apt-get update \ +# && apt-get -y install curl gcc libpq-dev \ +# && apt-get clean COPY requirements.txt . RUN pip config set global.trusted-host "pypi.python.org pypi.org files.pythonhosted.org" && \ - pip install -r requirements.txt + pip install --no-cache-dir -r requirements.txt COPY . . diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 1e77fcc..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,3 +0,0 @@ -import os - -os.environ["MODE"] = "TEST" diff --git a/tests/integration_tests/chat_api_test.py b/tests/integration_tests/chat_api_test.py deleted file mode 100644 index 1f00ddd..0000000 --- a/tests/integration_tests/chat_api_test.py +++ /dev/null @@ -1,9 +0,0 @@ -from httpx import AsyncClient - - -async def test_get_chats(ac: AsyncClient): - await ac.post("/users/login", json={"email_or_username": "urec", "password": "12311231"}) - response = await ac.get("/chat") - assert response.status_code == 200 - print(response.json()) - assert len(response.json()) == 2 diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py deleted file mode 100644 index 50d882a..0000000 --- a/tests/integration_tests/conftest.py +++ /dev/null @@ -1,59 +0,0 @@ -import json -from datetime import datetime - -import pytest -from httpx import AsyncClient -from sqlalchemy import insert, update - -from app.config import settings -from app.database import Base, async_session_maker, engine -from app.main import app as fastapi_app -from app.models.chat import Chat -from app.models.message import Message -from app.models.user_chat import UserChat -from app.models.users import Users - - -@pytest.fixture(autouse=True, scope="module") -async def prepare_database(): - assert settings.MODE == "TEST" - - async with engine.begin() as conn: - await conn.run_sync(Base.metadata.drop_all) - raise - await conn.run_sync(Base.metadata.create_all) - - def open_mock_json(model: str): - with open(f"app/tests/mock_{model}.json", "r", encoding="utf8") as file: - return json.load(file) - - users = open_mock_json("users") - chats = open_mock_json("chats") - users_x_chats = open_mock_json("x_chats") - messages = open_mock_json("messages") - - new_users = [] - for i in users: - i["date_of_birth"] = datetime.strptime(i["date_of_birth"], "%Y-%m-%d") - new_users.append(i) - - async with async_session_maker() as session: - add_users = insert(Users).values(new_users) - add_chats = insert(Chat).values(chats) - add_users_x_chats = insert(UserChat).values(users_x_chats) - add_messages = insert(Message).values(messages) - set_verified_user = update(Users).values(role=1).where(Users.id == 3) - - await session.execute(add_users) - await session.execute(add_chats) - await session.execute(add_users_x_chats) - await session.execute(add_messages) - await session.execute(set_verified_user) - - await session.commit() - - -@pytest.fixture(scope="function") -async def ac(): - async with AsyncClient(app=fastapi_app, base_url="http://test") as ac: - yield ac diff --git a/tests/integration_tests/users_api_test.py b/tests/integration_tests/users_api_test.py deleted file mode 100644 index e19ce88..0000000 --- a/tests/integration_tests/users_api_test.py +++ /dev/null @@ -1,130 +0,0 @@ -import pytest -from httpx import AsyncClient - - -async def test_get_users(ac: AsyncClient): - response = await ac.get("/users") - assert response.status_code == 200 - assert isinstance(response.json(), list) - assert len(response.json()) == 3 - - -@pytest.mark.parametrize( - "email,username,password,date_of_birth,status_code", - [ - ("sosi@lox.com", "sobakasutulaya", "12311231", "1990-01-01", 200), - ("sosi@lox.com", "sobakasutulaya", "12311231", "1990-01-01", 409), - ("lox@sosi.com", "sobakasutulaya", "12311231", "1990-01-01", 409), - ("lox@sosi.com", "sobakastroinaya", "3228", "1990-01-01", 422), - ("lox@sosi.com", "sobakastroinaya", "asdwdawdasd", "2030-01-01", 422), - ("lox@sosi.com", "sobakastroinaya", "asdwdawdasd", "2000-01-01", 200), - ], -) -async def test_register_user(email, username, password, date_of_birth, status_code, ac: AsyncClient): - response = await ac.post( - "/users/register", json={"email": email, "username": username, "password": password, "date_of_birth": date_of_birth} - ) - - assert response.status_code == status_code - - -@pytest.mark.parametrize( - "email_or_username,password,status_code", - [ - ("sosi@lox.com", "12311231", 200), - ("sobakasutulaya", "12311231", 200), - ("sobakastroinaya", "12311231", 401), - ("sosi@lox.com", "123123", 401), - ("urec@urec.com", "12311231", 200), - ("sobakasutulaya", 12311231, 422), - (12311231, "sobakasutulaya", 422), - ], -) -async def test_login_user(email_or_username: str, password: str, status_code: int, ac: AsyncClient): - response = await ac.post("/users/login", json={"email_or_username": email_or_username, "password": password}) - assert response.status_code == status_code - if status_code == 200: - assert "access_token" in response.json() - assert "black_phoenix_access_token" in response.cookies - - -async def test_logout_user(ac: AsyncClient): - response = await ac.post("/users/logout") - assert response.status_code == 200 - assert "black_phoenix_access_token" not in response.cookies - - -async def test_get_user(ac: AsyncClient): - await ac.post("/users/login", json={"email_or_username": "urec@urec.com", "password": "12311231"}) - response = await ac.get("/users/me") - assert response.status_code == 200 - assert response.json()["email"] == "urec@urec.com" - assert response.json()["black_phoenix"] == False # noqa: E712 - - -@pytest.mark.parametrize( - "username,password,statuscode", - [ - ("urec", "12311231", 409), - ("neurec", "12311231", 200), - ("urec", "adw", 409), - ("urec", "12311231", 200), - ], -) -async def test_rename_user(username: str, password: str, statuscode: int, ac: AsyncClient): - await ac.post("/users/login", json={"email_or_username": "urec@urec.com", "password": "12311231"}) - response = await ac.patch("/users/rename", json={"username": username, "password": password}) - assert response.status_code == statuscode - if response.status_code == 200: - assert response.json()["username"] == username - - -@pytest.mark.parametrize( - "avatar_url,password,statuscode", - [ - ("https://images.black-phoenix.ru/static/images/avatars/v6BtxTxfCFi2dBAl_avatar.png", "12311231", 200), - ( - "https://images.black-phoenix.ru/static/images/%D1%82%D1%8B%20%D1%83%D0%B6%D0%B5%20%D0%BF%D0%B5%D1%88%D0%BA%D0%B0%20BP.png", # noqa: E501 - "adw", - 409, - ), - ( - "https://images.black-phoenix.ru/static/images/%D1%82%D1%8B%20%D1%83%D0%B6%D0%B5%20%D0%BF%D0%B5%D1%88%D0%BA%D0%B0%20BP.png", # noqa: E501 - "12311231", - 200, - ), - ], -) -async def test_change_avatar(avatar_url: str, password: str, statuscode: int, ac: AsyncClient): - await ac.post("/users/login", json={"email_or_username": "urec@urec.com", "password": "12311231"}) - response = await ac.patch("/users/change_avatar", json={"new_avatar_image": avatar_url, "password": password}) - assert response.status_code == statuscode - if response.status_code == 200: - assert response.json()["new_avatar_image"] == avatar_url - - -@pytest.mark.parametrize( - "login_password,current_password,new_password1,new_password2,statuscode", - [ - ("12311231", "12311231", "12311231", "12311231", 200), - ("12311231", "12311231", "1231121", "12311231", 422), - ("12311231", "12311231", "1231121", "1231231", 422), - ("12311231", "12311231", "1231121", "1231121", 422), - ("12311231", "12311231", "12311231", "1231121", 422), - ("12311231", "1231131", "12311231", "12311231", 422), - ("12311231", "12311231", "12311241", "12311241", 200), - ("12311241", "12311231", "12311241", "12311241", 409), - ("12311241", "12311241", "12311231", "12311231", 200), - ], -) -async def test_change_password( - login_password: str, current_password: str, new_password1: str, new_password2: str, statuscode: int, ac: AsyncClient -): - await ac.post("/users/login", json={"email_or_username": "urec@urec.com", "password": login_password}) - response = await ac.patch( - "/users/change_password", - json={"current_password": current_password, "new_password": new_password1, "new_password2": new_password2}, - ) - - assert response.status_code == statuscode - diff --git a/tests/mock_chats.json b/tests/mock_chats.json deleted file mode 100644 index 49e33db..0000000 --- a/tests/mock_chats.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "chat_name": "lox", - "chat_for": 2, - "visibility": true, - "created_by": 1 - }, - { - "chat_name": "lox", - "chat_for": 2, - "visibility": true, - "created_by": 1 - } -] \ No newline at end of file diff --git a/tests/mock_messages.json b/tests/mock_messages.json deleted file mode 100644 index 2633874..0000000 --- a/tests/mock_messages.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "message": "ВАЫФ", - "image_url": null, - "chat_id": 1, - "user_id": 1, - "visibility": true - } -] \ No newline at end of file diff --git a/tests/mock_users.json b/tests/mock_users.json deleted file mode 100644 index fddec5f..0000000 --- a/tests/mock_users.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "email": "user@example.com", - "username": "string", - "hashed_password": "$2b$12$OkYfLiufUGGpxcJIC1TxQeEZNllHpS/jWICF9iRC7E/WTv7uFePbK", - "date_of_birth": "2024-02-13" - }, - { - "email": "test@test.com", - "username": "test", - "hashed_password": "$2b$12$Q65fcP54s8gLeIjDo5EPLeyqD7oc8YFXl/mV1CDpnKvFKW8exGBOi", - "date_of_birth": "2024-02-14" - }, - { - "email": "urec@urec.com", - "username": "urec", - "hashed_password": "$2b$12$sWscnmmhugSNJECjiz.j4eQK0vVYYA.fsYZD7a00WuJIsj9bDzj3m", - "date_of_birth": "2024-02-14" - } -] \ No newline at end of file diff --git a/tests/mock_verification_codes.json b/tests/mock_verification_codes.json deleted file mode 100644 index fe6d6b2..0000000 --- a/tests/mock_verification_codes.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "user_id": 1, - "code": "2vwQ6k", - "description": "Код подтверждения почты" - }, - { - "user_id": 2, - "code": "W6VruA", - "description": "Код подтверждения почты" - }, - { - "user_id": 3, - "code": "bWe93v", - "description": "Код подтверждения почты" - } -] \ No newline at end of file diff --git a/tests/mock_x_chats.json b/tests/mock_x_chats.json deleted file mode 100644 index 1101771..0000000 --- a/tests/mock_x_chats.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "user_id": 1, - "chat_id": 2 - }, - { - "user_id": 3, - "chat_id": 2 - }, - { - "user_id": 1, - "chat_id": 1 - }, - { - "user_id": 3, - "chat_id": 1 - } -] \ No newline at end of file