Skip to content

Commit

Permalink
Update config
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbreves committed Aug 21, 2023
1 parent 52be4d7 commit 4d277d3
Show file tree
Hide file tree
Showing 16 changed files with 770 additions and 269 deletions.
33 changes: 29 additions & 4 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ on:
pull_request:
branches: ["terraform"]

concurrency:
group: ${{ github.ref }}
cancel-in-progress: true

# These permissions are needed to interact with GitHub's OIDC Token endpoint.
jobs:
build:
Expand Down Expand Up @@ -33,7 +37,28 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3

# Build inside Docker containers
- run: sam build --use-container
# Prevent prompts and failure when the stack is unchanged
- run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --image-repository ${{ vars.AWS_ECR_REPO }} --stack-name fastapi-backend-lambda
- uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: Install Poetry
run: curl -sSL https://install.python-poetry.org | python3 -

- name: Poetry install
run: poetry install

- name: Poetry export
run: poetry export -f requirements.txt --without-hashes > requirements.txt

- run: >
sam build --use-container
- name: sam deploy
# Prevent prompts and failure when the stack is unchanged
run: >
sam deploy
--no-confirm-changeset
--no-fail-on-empty-changeset
--stack-name fastapi-backend-lambda
--parameter-overrides "SecretKeyArn=${{ vars.SECRET_ARN }} DBSecretArn=${{ vars.DB_SECRET_ARN }} DBEndpoint=${{ vars.DB_ENDPOINT }}"
--on-failure DELETE
5 changes: 4 additions & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,7 @@ cython_debug/
# website: https://docs.aws.amazon.com/serverless-application-model

# Ignore build folder
.aws-sam/
.aws-sam/

# dependencies are managed by Poetry and exported on build
requirements.txt
29 changes: 22 additions & 7 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import os
from dotenv import load_dotenv
from sqlalchemy import URL
import json
import botocore
import botocore.session
from aws_secretsmanager_caching import SecretCache, SecretCacheConfig

load_dotenv()

PROJECT_NAME = "fastapi-react-project"

DATABASE_URL: URL = os.getenv("DATABASE_URL")
SECRET_KEY: str = os.getenv("SECRET_KEY")
TEST_USERNAME: str = os.getenv("TEST_USERNAME")
TEST_PASSWORD: str = os.getenv("TEST_PASSWORD")
CORS_ORIGINS: str = os.getenv("CORS_ORIGINS")

AWS_REGION: str = os.environ.get("AWS_REGION")
TEST_USERNAME: str = os.environ.get("TEST_USERNAME")
TEST_PASSWORD: str = os.environ.get("TEST_PASSWORD")
CORS_ORIGINS: str = os.environ.get("CORS_ORIGINS")

API_V1_STR = "/api/v1"

_client = botocore.session.get_session().create_client(
'secretsmanager', region_name=AWS_REGION)
_cache_config = SecretCacheConfig()
_cache = SecretCache(config=_cache_config, client=_client)


def load_secret(secret_name):
try:
secret = _cache.get_secret_string(secret_name)
return json.loads(secret)
except Exception as e:
print(e)
raise e
15 changes: 12 additions & 3 deletions backend/app/core/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@
from fastapi.security import OAuth2PasswordBearer
from passlib.hash import sha512_crypt
from datetime import datetime, timedelta
from app.core import config
from app.core.config import load_secret

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/token")

SECRET_KEY = config.SECRET_KEY
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

_secret_key = None

def get_secret_key():
global _secret_key
if _secret_key is not None:
return _secret_key

_secret_key = load_secret("SECRET_KEY")
return _secret_key


def get_password_hash(password: str) -> str:
return sha512_crypt.hash(password)
Expand All @@ -26,5 +35,5 @@ def create_access_token(*, data: dict, expires_delta: timedelta | None = None):
else:
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
encoded_jwt = jwt.encode(to_encode, get_secret_key(), algorithm=ALGORITHM)
return encoded_jwt
33 changes: 25 additions & 8 deletions backend/app/db/session.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy.orm import sessionmaker, declarative_base, Session
from app.core.config import load_secret

from app.core import config
Base = declarative_base()

engine = create_engine(
config.DATABASE_URL,
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
_session_local: None | Session = None

Base = declarative_base()

def get_session_local():
global _session_local

if _session_local is not None:
return _session_local()

db_secret_name = os.environ.get("DB_SECRET_ARN")
db_secret = load_secret(db_secret_name)
db_endpoint = os.environ.get("DB_ENDPOINT")
db_name = os.environ.get("DB_NAME")
db_url = f"postgresql://{db_secret['username']}:{db_secret['password']}@{db_endpoint}/{db_name}"

engine = create_engine(db_url)

_session_local = sessionmaker(
autocommit=False, autoflush=False, bind=engine)

return _session_local()


# Dependency
def get_db():
db = SessionLocal()
db = get_session_local()
try:
yield db
finally:
Expand Down
6 changes: 5 additions & 1 deletion backend/app/domains/auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ async def get_current_user(
)
try:
payload = jwt.decode(
token, security.SECRET_KEY, algorithms=[security.ALGORITHM]
token, security.get_secret_key(), algorithms=[security.ALGORITHM]
)
email: str = payload.get("sub")
if email is None:
Expand All @@ -28,6 +28,10 @@ async def get_current_user(
email=email, permissions=permissions)
except PyJWTError:
raise credentials_exception

if token_data is None or token_data.email is None:
raise credentials_exception

user = get_user_by_email(db, token_data.email)
if user is None:
raise credentials_exception
Expand Down
4 changes: 2 additions & 2 deletions backend/app/fastapi_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from app import celery_tasks
from app.core.celery_app import celery_app
from app.domains.auth.auth import get_current_active_user
from app.db.session import SessionLocal
from app.db.session import get_session_local
from app.core import config
from app.domains.tasks.api.api_v1.routers.tasks import tasks_router
from app.domains.tasks.api.api_v1.routers.projects import projects_router
Expand All @@ -29,7 +29,7 @@

@app.middleware("http")
async def db_session_middleware(request: Request, call_next):
request.state.db = SessionLocal()
request.state.db = get_session_local()
response = await call_next(request)
request.state.db.close()
return response
Expand Down
4 changes: 2 additions & 2 deletions backend/app/initial_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3

from random import choice
from app.db.session import SessionLocal
from app.db.session import get_session_local
from datetime import date
from app.core import config
from app.domains.users.db.user_repository import create_user, get_user_by_email
Expand Down Expand Up @@ -76,7 +76,7 @@


def init() -> None:
db = SessionLocal()
db = get_session_local()

admin_email = config.TEST_USERNAME
admin_password = config.TEST_PASSWORD
Expand Down
3 changes: 2 additions & 1 deletion backend/app/mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
python_version = 3.8
plugins = pydantic.mypy, sqlmypy
ignore_missing_imports = True
disallow_untyped_defs = True
disallow_untyped_defs = True
check_untyped_defs = True
Loading

0 comments on commit 4d277d3

Please sign in to comment.