From 2e70664620881718a56ecad6b2bc30b1b653f97f Mon Sep 17 00:00:00 2001 From: Jacob Windsor Date: Wed, 19 Feb 2025 14:27:14 +0100 Subject: [PATCH] Add basic endpoints --- Makefile | 3 +++ backend/app/dtos/house_create_request.py | 9 +++++++ backend/app/dtos/house_create_response.py | 5 ++++ backend/app/main.py | 5 +++- backend/app/models/house.py | 13 +++++----- backend/app/models/owner.py | 5 +--- backend/app/providers/auth_provider.py | 4 +-- backend/app/repositories/house_repository.py | 2 +- backend/app/repositories/owner_repository.py | 2 +- backend/app/routers/houses.py | 27 +++++++++++++++++--- backend/app/routers/owners.py | 10 ++++++++ docker-compose.yml | 14 +++++++--- 12 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 backend/app/dtos/house_create_request.py create mode 100644 backend/app/dtos/house_create_response.py create mode 100644 backend/app/routers/owners.py diff --git a/Makefile b/Makefile index 74bd667..5482777 100644 --- a/Makefile +++ b/Makefile @@ -26,5 +26,8 @@ start-db: stop-db: docker-compose down +clean-db: + docker compose down -v db + clean: rm -rf $(VENV_DIR) \ No newline at end of file diff --git a/backend/app/dtos/house_create_request.py b/backend/app/dtos/house_create_request.py new file mode 100644 index 0000000..fff068b --- /dev/null +++ b/backend/app/dtos/house_create_request.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + +class HouseCreateRequest(BaseModel): + address: str + city: str + country: str + price: float + description: str + diff --git a/backend/app/dtos/house_create_response.py b/backend/app/dtos/house_create_response.py new file mode 100644 index 0000000..2c60514 --- /dev/null +++ b/backend/app/dtos/house_create_response.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + +class HouseCreateResponse(BaseModel): + id: str + diff --git a/backend/app/main.py b/backend/app/main.py index 36d1466..0374406 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -3,6 +3,7 @@ from fastapi.middleware.cors import CORSMiddleware from .providers.db_provider import create_db_and_tables from .routers.houses import router as houses_router +from .routers.owners import router as owners_router from contextlib import asynccontextmanager @@ -14,7 +15,8 @@ async def lifespan(_app: FastAPI): app = FastAPI( title="Fair Housing API", description="Provides access to core functionality for the fair housing platform.", - version="1.0.0" + version="1.0.0", + lifespan=lifespan ) app.add_middleware( @@ -26,3 +28,4 @@ app.add_middleware( ) app.include_router(houses_router, prefix="/houses", tags=["houses"]) +app.include_router(owners_router, prefix="/owners", tags=["owners"]) diff --git a/backend/app/models/house.py b/backend/app/models/house.py index 3dafd48..bf8f57b 100644 --- a/backend/app/models/house.py +++ b/backend/app/models/house.py @@ -2,9 +2,10 @@ from sqlmodel import SQLModel, Field from uuid import uuid4, UUID class House(SQLModel, table=True): - id: UUID = Field(primary_key=True, default_factory=uuid4), - address: str - city: str - country: str - price: float - description: str = None + id: UUID = Field(primary_key=True, default_factory=uuid4) + address: str = Field() + city: str = Field() + country: str = Field() + price: float = Field() + description: str = Field() + owner_id: UUID = Field(foreign_key="owner.id") diff --git a/backend/app/models/owner.py b/backend/app/models/owner.py index 0d3d857..4a192d3 100644 --- a/backend/app/models/owner.py +++ b/backend/app/models/owner.py @@ -3,7 +3,4 @@ from uuid import uuid4, UUID class Owner(SQLModel, table=True): id: UUID = Field(default_factory=uuid4, primary_key=True) - name: str - email: str - # TODO add user_id - # TODO add houses + user_id: UUID = Field(foreign_key="user.id") diff --git a/backend/app/providers/auth_provider.py b/backend/app/providers/auth_provider.py index 34ce622..dec1ad7 100644 --- a/backend/app/providers/auth_provider.py +++ b/backend/app/providers/auth_provider.py @@ -3,9 +3,9 @@ from ..models.user import User from ..settings import get_settings -class AuthProvider: +class AuthContext: """ - Provides authentication methods for the API. + Provides authentication context for the current request. """ def __init__( diff --git a/backend/app/repositories/house_repository.py b/backend/app/repositories/house_repository.py index c625d21..ce97af7 100644 --- a/backend/app/repositories/house_repository.py +++ b/backend/app/repositories/house_repository.py @@ -1,7 +1,7 @@ from sqlalchemy.ext.asyncio.session import AsyncSession from typing import Annotated from fastapi import Depends -from app.providers.db_provider import get_session +from ..providers.db_provider import get_session from ..models.house import House from sqlmodel import select diff --git a/backend/app/repositories/owner_repository.py b/backend/app/repositories/owner_repository.py index 72b44ee..2ec2627 100644 --- a/backend/app/repositories/owner_repository.py +++ b/backend/app/repositories/owner_repository.py @@ -1,7 +1,7 @@ from sqlalchemy.ext.asyncio.session import AsyncSession from typing import Annotated from fastapi import Depends -from app.providers.db_provider import get_session +from ..providers.db_provider import get_session from ..models.owner import Owner from sqlmodel import select diff --git a/backend/app/routers/houses.py b/backend/app/routers/houses.py index cd40957..d6b39d3 100644 --- a/backend/app/routers/houses.py +++ b/backend/app/routers/houses.py @@ -1,12 +1,33 @@ from fastapi import APIRouter, Depends from typing import Annotated -from ..providers.auth_provider import AuthProvider +from ..providers.auth_provider import AuthContext +from ..repositories.house_repository import HouseRepository +from ..models.house import House +from ..dtos.house_create_request import HouseCreateRequest +from ..dtos.house_create_response import HouseCreateResponse router = APIRouter() @router.post("") -async def create_house(auth_provider: Annotated[AuthProvider, Depends()]): - return auth_provider.user +async def create_house(body: HouseCreateRequest, auth: Annotated[AuthContext, Depends()], house_repository: Annotated[HouseRepository, Depends()]) -> HouseCreateResponse: + owner = auth.user + + house = House( + owner_id=owner.id, + address=body.address, + city=body.city, + country=body.country, + price=body.price, + description=body.description + ) + + await house_repository.save(house) + + return HouseCreateResponse( + id=house.id + ) + + @router.get("") async def get_all_houses(): diff --git a/backend/app/routers/owners.py b/backend/app/routers/owners.py new file mode 100644 index 0000000..2e17849 --- /dev/null +++ b/backend/app/routers/owners.py @@ -0,0 +1,10 @@ +from fastapi import APIRouter, Depends +from typing import Annotated +from ..repositories.owner_repository import OwnerRepository + +router = APIRouter() + + +@router.get("/{id}") +async def get_owner(id: str, owner_repository: Annotated[OwnerRepository, Depends()]): + return await owner_repository.get_by_id(id) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 50154d4..e9d5967 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,10 +10,16 @@ services: command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] db: - image: postgres:13 + image: postgres:15 + container_name: fair-housing-postgres environment: - POSTGRES_USER: user + POSTGRES_USER: developer POSTGRES_PASSWORD: password - POSTGRES_DB: mydatabase + POSTGRES_DB: dev ports: - - "5432:5432" \ No newline at end of file + - "5432:5432" + volumes: + - db-data:/var/lib/postgresql/data + +volumes: + db-data: \ No newline at end of file