Skip to content

Commit

Permalink
Dev Container
Browse files Browse the repository at this point in the history
  • Loading branch information
LimeDrive committed Sep 21, 2024
1 parent 367d962 commit 21b30a4
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 77 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,7 @@ cython_debug/

# apple
.DS_Store

#devcontainer
.devcontainer/
docker-compose-dev.yml
33 changes: 32 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,38 @@ COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt --only main --without-hashes \
&& pip install --no-cache-dir -r requirements.txt

FROM python:3.12-alpine
FROM python:3.12-alpine AS development

ENV PYTHONUNBUFFERED=1 \
POETRY_VERSION=1.8.3

RUN apk add --no-cache \
gcc \
musl-dev \
libffi-dev \
openssl \
postgresql-client \
git \
&& pip install --no-cache-dir "poetry==$POETRY_VERSION"

WORKDIR /app

COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .

RUN poetry config virtualenvs.create false \
&& poetry install --no-root

ARG GUNICORN_PORT=8080
ENV EXPOSE_PORT=${GUNICORN_PORT}
EXPOSE ${EXPOSE_PORT}

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

CMD ["/bin/sh"]

FROM python:3.12-alpine AS production

ENV PYTHONUNBUFFERED=1

Expand Down
70 changes: 70 additions & 0 deletions deploy/dev-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
version: '3.8'

services:
app:
build:
context: .
dockerfile: Dockerfile
target: development
stdin_open: true
tty: true
volumes:
- .:/app
ports:
- "8080:8080"
environment:
RELOAD: True
SECRET_API_KEY: 'superkey_that_can_be_changed'
TMDB_API_KEY: <REDACTED>
ZILEAN_SCHEMA: 'https'
ZILEAN_PORT: 443
ZILEAN_HOST: <REDACTED>
PG_HOST: postgresql-dev
REDIS_HOST: redis-dev
LOG_LEVEL: DEBUG
LOG_REDACTED: False
depends_on:
- postgresql-dev
- redis-dev

postgresql-dev:
image: postgres:16.3-alpine3.20
container_name: postgresql-dev
restart: unless-stopped
environment:
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_USER: streamfusion
POSTGRES_PASSWORD: streamfusion
POSTGRES_DB: streamfusion
expose:
- 5432
volumes:
- postgres_dev:/var/lib/postgresql/data/pgdata

redis-dev:
image: redis:latest
container_name: redis-dev
expose:
- 6379
volumes:
- redis_dev:/data
command: redis-server --appendonly yes
restart: unless-stopped

pgadmin:
image: dpage/pgadmin4:latest
container_name: pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: adminpassword
ports:
- "5050:80"
volumes:
- pgadmin_data:/var/lib/pgadmin
depends_on:
- postgresql-dev

volumes:
postgres_dev:
redis_dev:
pgadmin_data:
3 changes: 1 addition & 2 deletions poetry.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[virtualenvs]
in-project = true
create = true
in-project = false
19 changes: 19 additions & 0 deletions stream_fusion/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ def main() -> None:
host=settings.host,
port=settings.port,
reload=settings.reload,
reload_excludes=[
"*.pyc",
"*.log",
".git/*",
".vscode/*",
"tests/*",
"docs/*",
".venv/*",
".devcontainer/*",
".github/*",
"Dockerfile",
"config/*",
],
reload_includes=[
"*.py",
"*.html",
"*.css",
"*.js",
],
log_level=settings.log_level.value.lower(),
factory=True,
)
Expand Down
147 changes: 73 additions & 74 deletions stream_fusion/services/postgresql/dao/apikey_dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,65 +24,65 @@ def __init__(self, session: AsyncSession = Depends(get_db_session)) -> None:
self.expiration_limit = 15 # Default expiration limit in days

async def create_key(self, api_key_create: APIKeyCreate) -> APIKeyInDB:
try:
api_key = str(uuid.uuid4())
expiration_timestamp = (
None
if api_key_create.never_expire
else datetime_to_timestamp(datetime.now(timezone.utc) + timedelta(days=self.expiration_limit))
)

new_key = APIKeyModel(
api_key=api_key,
is_active=True,
never_expire=api_key_create.never_expire,
expiration_date=expiration_timestamp,
name=api_key_create.name,
)
async with self.session.begin():
try:
api_key = str(uuid.uuid4())
expiration_timestamp = (
None
if api_key_create.never_expire
else datetime_to_timestamp(datetime.now(timezone.utc) + timedelta(days=self.expiration_limit))
)

self.session.add(new_key)
await self.session.commit()
await self.session.refresh(new_key)
new_key = APIKeyModel(
api_key=api_key,
is_active=True,
never_expire=api_key_create.never_expire,
expiration_date=expiration_timestamp,
name=api_key_create.name,
)

logger.success(f"Created new API key: {api_key}")
return APIKeyInDB(
id=new_key.id,
api_key=new_key.api_key,
is_active=new_key.is_active,
never_expire=new_key.never_expire,
expiration_date=timestamp_to_datetime(new_key.expiration_date),
latest_query_date=timestamp_to_datetime(new_key.latest_query_date),
total_queries=new_key.total_queries,
name=new_key.name
)
except Exception as e:
await self.session.rollback()
logger.error(f"Error creating API key: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
self.session.add(new_key)
await self.session.flush()

async def get_all_keys(self, limit: int, offset: int) -> List[APIKeyInDB]:
try:
query = select(APIKeyModel).limit(limit).offset(offset)
result = await self.session.execute(query)
keys = [
APIKeyInDB(
id=key.id,
api_key=key.api_key,
is_active=key.is_active,
never_expire=key.never_expire,
expiration_date=timestamp_to_datetime(key.expiration_date),
latest_query_date=timestamp_to_datetime(key.latest_query_date),
total_queries=key.total_queries,
name=key.name
logger.success(f"Created new API key: {api_key}")
return APIKeyInDB(
id=new_key.id,
api_key=new_key.api_key,
is_active=new_key.is_active,
never_expire=new_key.never_expire,
expiration_date=timestamp_to_datetime(new_key.expiration_date),
latest_query_date=timestamp_to_datetime(new_key.latest_query_date),
total_queries=new_key.total_queries,
name=new_key.name
)
for key in result.scalars().all()
]
logger.info(f"Retrieved {len(keys)} API keys")
return keys
except Exception as e:
logger.error(f"Error retrieving API keys: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
except Exception as e:
logger.error(f"Error creating API key: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")

async def get_all_keys(self, limit: int, offset: int) -> List[APIKeyInDB]:
async with self.session.begin():
try:
query = select(APIKeyModel).limit(limit).offset(offset)
result = await self.session.execute(query)
keys = [
APIKeyInDB(
id=key.id,
api_key=key.api_key,
is_active=key.is_active,
never_expire=key.never_expire,
expiration_date=timestamp_to_datetime(key.expiration_date),
latest_query_date=timestamp_to_datetime(key.latest_query_date),
total_queries=key.total_queries,
name=key.name
)
for key in result.scalars().all()
]
logger.info(f"Retrieved {len(keys)} API keys")
return keys
except Exception as e:
logger.error(f"Error retrieving API keys: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")

async def get_key_by_uuid(self, api_key: uuid.UUID) -> Optional[APIKeyInDB]:
try:
query = select(APIKeyModel).where(APIKeyModel.api_key == str(api_key))
Expand Down Expand Up @@ -189,30 +189,29 @@ async def delete_key(self, api_key: uuid.UUID) -> bool:
raise HTTPException(status_code=500, detail="Internal server error")

async def check_key(self, api_key: uuid.UUID) -> bool:
try:
query = select(APIKeyModel).where(APIKeyModel.api_key == str(api_key))
result = await self.session.execute(query)
db_key = result.scalar_one_or_none()
async with self.session.begin():
try:
query = select(APIKeyModel).where(APIKeyModel.api_key == str(api_key))
result = await self.session.execute(query)
db_key = result.scalar_one_or_none()

if not db_key or not db_key.is_active:
logger.warning(f"Invalid or inactive API key: {api_key}")
return False
if not db_key or not db_key.is_active:
logger.warning(f"Invalid or inactive API key: {api_key}")
return False

current_time = datetime_to_timestamp(datetime.now(timezone.utc))
if not db_key.never_expire and db_key.expiration_date < current_time:
logger.warning(f"Expired API key: {api_key}")
return False
current_time = datetime_to_timestamp(datetime.now(timezone.utc))
if not db_key.never_expire and db_key.expiration_date < current_time:
logger.warning(f"Expired API key: {api_key}")
return False

db_key.total_queries += 1
db_key.latest_query_date = current_time
await self.session.commit()
db_key.total_queries += 1
db_key.latest_query_date = current_time

logger.debug(f"Valid API key used: {api_key}")
return True
except Exception as e:
await self.session.rollback()
logger.error(f"Error checking API key {api_key}: {str(e)}")
return False
logger.debug(f"Valid API key used: {api_key}")
return True
except Exception as e:
logger.error(f"Error checking API key {api_key}: {str(e)}")
return False

async def renew_key(self, api_key: uuid.UUID) -> APIKeyInDB:
try:
Expand Down

0 comments on commit 21b30a4

Please sign in to comment.