Skip to content

Commit

Permalink
Create tests auth api
Browse files Browse the repository at this point in the history
Signed-off-by: Denis Karpelevich <[email protected]>
  • Loading branch information
dkarpele committed Jul 1, 2024
1 parent 69b14c8 commit e7b5ce8
Show file tree
Hide file tree
Showing 27 changed files with 217 additions and 48 deletions.
37 changes: 20 additions & 17 deletions .github/workflows/test-auth.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Test Auth FastAPI App

on:
Expand All @@ -14,26 +11,32 @@ permissions:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.12
uses: actions/setup-python@v3
with:
python-version: "3.10"
python-version: "3.12"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
pip install pytest
pip install -r ./tests/end_to_end/requirements.txt
# - name: Lint with flake8
# run: |
# # stop the build if there are Python syntax errors or undefined names
# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Set environment variables from secrets and create .env file
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
echo "${{ secrets.ENV_FILE }}" > ./test_apps/end_to_end/.env
echo "${{ secrets.PRIVATE_KEY }}" > ./keys/private_key.pem
echo "${{ secrets.PUBLIC_KEY }}" > ./keys/public_key.pem
ls -al
- name: Run docker-compose
uses: hoverkraft-tech/[email protected]
with:
compose-file: "./test_apps/end_to_end/docker-compose.yml"
4 changes: 2 additions & 2 deletions auth.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ ENV PYTHONPATH "${PYTHONPATH}:${WORKDIR}"
COPY ./auth_api/src/requirements.txt requirements.txt

RUN pip install --upgrade pip \
&& pip install -r /app/requirements.txt \
&& pip install -r ${WORKDIR}/requirements.txt \
&& mkdir -p ${WORKDIR}/logs

COPY ./auth_api/src ./auth_api/src
COPY ./auth_app ./auth_app
COPY ./db ./db
COPY ./settings ./settings
COPY ./project_settings ./project_settings
COPY ./helpers ./helpers
COPY ./keys ./keys

Expand Down
2 changes: 1 addition & 1 deletion auth_api/src/api/v1/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from auth_api.src.services.exceptions import exc_func, general_error_message
from auth_app.auth import auth_connector
from helpers.utils import redirect, handle_bad_user
from settings.logger import log_chat_id
from project_settings.logger import log_chat_id

router = APIRouter()
logger = logging.getLogger(__name__)
Expand Down
4 changes: 2 additions & 2 deletions auth_api/src/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from gunicorn import glogging
from pydantic import Field

from settings.config import MainConf
from settings.logger import LOGGING
from project_settings.config import MainConf
from project_settings.logger import LOGGING


class AuthSettings(MainConf):
Expand Down
4 changes: 2 additions & 2 deletions auth_api/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from auth_api.src.api.v1 import oauth
from auth_api.src.core.config import auth_settings
from db import db_redis
from settings.config import redis_settings
from settings.logger import LOGGING
from project_settings.config import redis_settings
from project_settings.logger import LOGGING

logger = logging.getLogger('auth_api')

Expand Down
2 changes: 1 addition & 1 deletion auth_app/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class AbstractAuth(ABC):
@staticmethod
@abstractmethod
async def get_authorization_url(chat_id: int):
async def get_authorization_url(chat_id: str):
pass

@staticmethod
Expand Down
19 changes: 9 additions & 10 deletions auth_app/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
from helpers.exceptions import (BadUserCredsException,
UserAlreadyLoggedInException)
from helpers.utils import generate_youtube_login_message
from settings.config import client_creds
from project_settings.config import client_creds

logger = logging.getLogger(__name__)
cache: AbstractCache = get_cache_service()


async def create_signature(chat_id: int):
async def create_signature(chat_id: str):
logger.info('Creating authorization signature.')
signature_content: bytes = \
str(chat_id).encode('utf-8') + \
Expand All @@ -33,7 +33,7 @@ async def create_signature(chat_id: int):

class GoogleAuth(AbstractAuth):
@staticmethod
async def get_authorization_url(chat_id: int) -> str | Response:
async def get_authorization_url(chat_id: str) -> str | Response:
logger.info('Creating authorization url')
signature_content = await create_signature(chat_id)

Expand Down Expand Up @@ -82,19 +82,18 @@ async def init_auth(self, code: str, state: str):
logger.info('User does initial authorization.')

async def inner(chat_id):
oauth2manager = Oauth2Manager()
logger.info('Creating user credentials.')
try:
user_creds: UserCreds = UserCreds(
**await oauth2manager.build_user_creds(
buc = await Oauth2Manager().build_user_creds(
grant=code,
client_creds=client_creds

))
)
user_creds: UserCreds = UserCreds(**buc)
except HTTPError:
logger.warning(f'Failed to build user creds',
exc_info=True)
raise BadUserCredsException

# Redis key='creds.{chat_id}' stores the user's access and refresh
# tokens and is created automatically when the authorization flow
# completes for the first time. It expires after 24 hours.
Expand Down Expand Up @@ -153,11 +152,11 @@ async def refresh_user_creds(
return user_creds

@staticmethod
async def get_user_creds(chat_id: int | str) -> str | None:
async def get_user_creds(chat_id: str) -> str | None:
logger.info('Getting user creds')
return await cache.get_from_cache_by_id(f'creds.{chat_id}')

async def auth_user(self, chat_id: int, context):
async def auth_user(self, chat_id: str, context):
if await cache.get_from_cache_by_id(f'creds.{chat_id}'):
raise UserAlreadyLoggedInException
else:
Expand Down
2 changes: 1 addition & 1 deletion auth_app/dependencies/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from db import db_redis
from db.abstract import AbstractCache
from settings.config import redis_settings
from project_settings.config import redis_settings


@lru_cache()
Expand Down
2 changes: 1 addition & 1 deletion bot.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ RUN pip install --upgrade pip \
COPY ./bot_app/src ./bot_app/src
COPY ./auth_app ./auth_app
COPY ./db ./db
COPY ./settings ./settings
COPY ./project_settings ./project_settings
COPY ./helpers ./helpers
COPY ./keys ./keys
COPY social_ai_profile_app ./social_ai_profile_app
Expand Down
2 changes: 1 addition & 1 deletion bot_app/src/handlers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from telegram import Update
from telegram.ext import ContextTypes

from settings.logger import log_chat_id
from project_settings.logger import log_chat_id
from bot_app.src.handlers.describe_handlers import (describe_user_handler,
describeme_consent_handler)
from bot_app.src.handlers.base_handlers import start_handler
Expand Down
4 changes: 2 additions & 2 deletions bot_app/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from telegram import Update

from bot_app.src.handlers.main import start, auth, logout, describeme, revoke, describeme_consent
from settings.config import bot_settings
from settings.logger import LOGGING
from project_settings.config import bot_settings
from project_settings.logger import LOGGING

config.dictConfig(LOGGING)

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion db/db_redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from redis.asyncio import Redis as AsyncRedis
from db.abstract import AbstractCache
from settings.config import redis_settings
from project_settings.config import redis_settings

logger = logging.getLogger(__name__)

Expand Down
5 changes: 2 additions & 3 deletions helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from helpers.exceptions import BadUserCredsException

from settings.config import bot_settings
from project_settings.config import bot_settings


def handle_bad_user(exc_func):
Expand Down Expand Up @@ -34,8 +34,7 @@ async def redirect_response(self, text_list: list, chat_id):
# return Response(status_code=307,
# content=content,
# headers={'location': self.url})
return RedirectResponse(url=self.url,
)
return RedirectResponse(url=self.url)


redirect = RedirectToBot()
Expand Down
2 changes: 1 addition & 1 deletion nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ http {
text/xml
text/javascript;

include conf.d/prod.conf;
include conf.d/test.conf;
}
Empty file added project_settings/__init__.py
Empty file.
File renamed without changes.
2 changes: 1 addition & 1 deletion settings/logger.py → project_settings/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from telegram import Update

from settings.config import smtp_settings
from project_settings.config import smtp_settings
from asgi_correlation_id import CorrelationIdFilter
from logging import Filter

Expand Down
2 changes: 1 addition & 1 deletion social_ai_profile_app/ai_portrait/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import google.generativeai as genai

from settings.config import google_creds
from project_settings.config import google_creds
from social_ai_profile_app.ai_portrait.abstract import AbstractPortrait

gemini_api_key = google_creds.gemini_api_key
Expand Down
2 changes: 1 addition & 1 deletion social_ai_profile_app/social_content/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from aiogoogle import Aiogoogle

from settings.config import client_creds
from project_settings.config import client_creds
from social_ai_profile_app.social_content.abstract import AbstractContent

logger = logging.getLogger(__name__)
Expand Down
12 changes: 12 additions & 0 deletions test_apps/end_to_end/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import asyncio

import pytest_asyncio

pytest_plugins = ("test_apps.end_to_end.fixtures.setup_redis",)


@pytest_asyncio.fixture(scope="session")
def event_loop():
loop = asyncio.get_event_loop()
yield loop
loop.close()
53 changes: 53 additions & 0 deletions test_apps/end_to_end/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
version: '3'

services:
fastapi-auth-api:
image: fastapi-auth-api
restart: unless-stopped
build:
context: ../../
dockerfile: auth.Dockerfile
env_file:
- .env
networks:
- test_apps
expose:
- "8000"
depends_on:
redis:
condition: service_healthy
volumes:
- ./../../test_apps:/${APP_HOME}/test_apps

tests:
image: fastapi-auth-api
privileged: true
env_file:
- .env
networks:
- test_apps
depends_on:
redis:
condition: service_healthy
fastapi-auth-api:
condition: service_started
entrypoint: ${APP_HOME}/test_apps/end_to_end/entrypoint.sh
volumes:
- ./../../test_apps:/${APP_HOME}/test_apps

redis:
image: redis:latest
restart: always
container_name: redis
privileged: true
networks:
- test_apps
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
interval: 30s
timeout: 10s
retries: 5


networks:
test_apps:
13 changes: 13 additions & 0 deletions test_apps/end_to_end/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
echo "Waiting for volume $APP_HOME/test_apps/ ..."

while [ ! -d "$APP_HOME"/test_apps/ ]
do
echo "volume $APP_HOME/test_apps/ is still creating ..."
sleep 1
done

echo "volume $APP_HOME/test_apps/ created"

pip install -r "$APP_HOME"/test_apps/end_to_end/requirements.txt &&
pytest -s -v --disable-warnings "$APP_HOME"/test_apps/end_to_end/src
26 changes: 26 additions & 0 deletions test_apps/end_to_end/fixtures/setup_redis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import pytest_asyncio
from test_apps.end_to_end.settings import settings
from redis.asyncio import Redis


redis_cli = Redis(host=settings.redis_host,
port=settings.redis_port)


@pytest_asyncio.fixture(scope='class')
async def redis_clear_data_before_after():
await redis_cli.flushall()
yield
await redis_cli.flushall()


@pytest_asyncio.fixture(scope='class')
async def redis_clear_data_after():
yield
await redis_cli.flushall()


@pytest_asyncio.fixture(scope='class')
async def redis_clear_data_before():
await redis_cli.flushall()
yield
2 changes: 2 additions & 0 deletions test_apps/end_to_end/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest==8.2.2
pytest-asyncio==0.23.7
Loading

0 comments on commit e7b5ce8

Please sign in to comment.