Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update database models for new requirements #28

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import logging

from api import constants
from api import settings

format_string = "[%(asctime)s] [%(process)d] [%(levelname)s] %(name)s - %(message)s"
date_format_string = "%Y-%m-%d %H:%M:%S %z"

logging.basicConfig(
format=format_string, datefmt=date_format_string, level=getattr(logging, constants.Config.LOG_LEVEL.upper())
format=format_string, datefmt=date_format_string, level=getattr(logging, settings.Server.LOG_LEVEL.upper())
)

logging.getLogger().info("Logging initialization complete")
12 changes: 0 additions & 12 deletions api/constants.py

This file was deleted.

99 changes: 0 additions & 99 deletions api/database.py

This file was deleted.

12 changes: 0 additions & 12 deletions api/dependencies.py

This file was deleted.

12 changes: 4 additions & 8 deletions api/main.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
from fastapi import FastAPI
from starlette.middleware.authentication import AuthenticationMiddleware

from api.constants import Config
from api.middleware import TokenAuthentication, on_auth_error
from api.routers import codejams, infractions, teams, users, winners
from api.routers.v1 import v1_routes_router
from api.settings import Server

app = FastAPI(redoc_url="/", docs_url="/swagger")

app.add_middleware(
AuthenticationMiddleware,
backend=TokenAuthentication(token=Config.TOKEN),
backend=TokenAuthentication(token=Server.API_TOKEN.get_secret_value()),
on_error=on_auth_error,
)

app.include_router(codejams.router)
app.include_router(infractions.router)
app.include_router(teams.router)
app.include_router(users.router)
app.include_router(winners.router)
app.include_router(v1_routes_router)
4 changes: 2 additions & 2 deletions api/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from starlette.requests import Request
from starlette.responses import JSONResponse

from api.constants import Config
from api.settings import Server

NO_AUTHORIZATION_HEADER = "no `Authorization` header in request."
INVALID_CREDENTIALS = "invalid credentials."
Expand All @@ -17,7 +17,7 @@ def __init__(self, token: str) -> None:

async def authenticate(self, request: Request) -> tuple[AuthCredentials, SimpleUser]:
"""Authenticate the request based on the Authorization header."""
if Config.DEBUG:
if Server.DEBUG:
credentials = AuthCredentials(scopes=["debug"])
user = SimpleUser(username="api_client")
return credentials, user
Expand Down
146 changes: 0 additions & 146 deletions api/models.py

This file was deleted.

6 changes: 6 additions & 0 deletions api/models/orm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Database models."""

from .infraction import Infraction # noqa: F401
from .jam import Jam # noqa: F401
from .team import Team # noqa: F401
from .user import JamSpecificDetail, User # noqa: F401
25 changes: 25 additions & 0 deletions api/models/orm/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""The base classes for ORM models."""

from pydantic import BaseModel
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.schema import MetaData

# See https://docs.sqlalchemy.org/en/14/core/constraints.html#constraint-naming-conventions
NAMING_CONVENTIONS = {
"ix": "%(column_0_label)s_ix",
"uq": "%(table_name)s_%(column_0_name)s_uq",
"ck": "%(table_name)s_%(constraint_name)s_ck",
"fk": "%(table_name)s_%(column_0_name)s_%(referred_table_name)s_fk",
"pk": "%(table_name)s_pk",
}


class Base(DeclarativeBase):
"""Classes that inherit this class will be automatically mapped using declarative mapping."""

metadata = MetaData(naming_convention=NAMING_CONVENTIONS)

def patch_from_pydantic(self, pydantic_model: BaseModel) -> None:
"""Patch this model using the given pydantic model, unspecified attributes remain the same."""
for key, value in pydantic_model.dict(exclude_unset=True).items():
setattr(self, key, value)
23 changes: 23 additions & 0 deletions api/models/orm/infraction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from typing import Literal

from sqlalchemy import Enum, ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column

from api.models.orm.base import Base

InfractionType = Literal["note", "ban", "warning"]


class Infraction(Base):
"""An infraction that was applied to a user."""

__tablename__ = "infractions"

infraction_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(ForeignKey("users.user_id"))
issued_in_jam_id: Mapped[int] = mapped_column(ForeignKey("jams.jam_id"))
infraction_type: Mapped[InfractionType] = mapped_column(
Enum(*InfractionType.__args__, name="infraction_type"),
nullable=False,
)
reason: Mapped[str] = mapped_column(String(), nullable=False)
Loading