diff --git a/backend/app/db/__init__.py b/backend/app/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/db/crud.py b/backend/app/db/crud.py new file mode 100644 index 0000000..0141c16 --- /dev/null +++ b/backend/app/db/crud.py @@ -0,0 +1,28 @@ +from sqlalchemy.orm import Session + +from . import models, schemas + +# We declare functions that the endpoints in app/routers/*.py +# use to interact with the tables in the database + + +def create_user(db: Session, user: schemas.UserCreate): + db_user = models.User( + email=user.email, + first_name= "", + last_name="", + location="", + profile_picture="", + ) + db.add(db_user) + db.commit() + db.refresh(db_user) + return db_user + + +def get_user(db: Session, user_id: int): + return db.query(models.User).filter(models.User.user_id == user_id).first() + + +def get_user_by_email(db: Session, email: str): + return db.query(models.User).filter(models.User.email == email).first() diff --git a/backend/app/db/database.py b/backend/app/db/database.py new file mode 100644 index 0000000..cb5b2b7 --- /dev/null +++ b/backend/app/db/database.py @@ -0,0 +1,11 @@ +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +# TODO: Parameterize this +SQLALCHEMY_DATABASE_URL = "mysql+pymysql://user:password@localhost:3306/db" + +engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_pre_ping=True, echo=True) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() \ No newline at end of file diff --git a/backend/app/db/models.py b/backend/app/db/models.py new file mode 100644 index 0000000..9f26d57 --- /dev/null +++ b/backend/app/db/models.py @@ -0,0 +1,17 @@ +from sqlalchemy import Boolean, Column, Integer, VARCHAR, BLOB + +from .database import Base + +# Creating the User class as a subclass of Base +# will let us create the users table in +# app/routers/users.py +class User(Base): + __tablename__ = "users" + + user_id = Column(Integer, primary_key=True, index=True) + first_name = Column(VARCHAR(50)) + last_name = Column(VARCHAR(50)) + email = Column(VARCHAR(50), unique=True, index=True) + location = Column(VARCHAR(50)) + profile_picture = Column(BLOB) + recipe_driven = Column(Boolean, default=True) \ No newline at end of file diff --git a/backend/app/db/schemas.py b/backend/app/db/schemas.py new file mode 100644 index 0000000..1714092 --- /dev/null +++ b/backend/app/db/schemas.py @@ -0,0 +1,21 @@ +from pydantic import BaseModel +from typing import Union + +# This defines the type Schema for classes like User +# For the database schema/models, see ./models.py +class UserBase(BaseModel): + email: str + +class UserCreate(UserBase): + password: str + +class User(UserBase): + user_id: int + first_name: Union[str, None] + last_name: Union[str, None] + location: Union[str, None] + profile_picture: Union[str, None] + recipe_driven: bool + + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/app/deps.py b/backend/app/deps.py new file mode 100644 index 0000000..66adad6 --- /dev/null +++ b/backend/app/deps.py @@ -0,0 +1,8 @@ +from app.db.database import SessionLocal + +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() \ No newline at end of file diff --git a/backend/app/main.py b/backend/app/main.py index 0d17c9b..f17f15e 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,7 +1,8 @@ from fastapi import FastAPI +from .routers import users app = FastAPI() - +app.include_router(users.router) @app.get("/") async def root(): diff --git a/backend/app/routers/__init__.py b/backend/app/routers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/routers/users.py b/backend/app/routers/users.py new file mode 100644 index 0000000..3902f75 --- /dev/null +++ b/backend/app/routers/users.py @@ -0,0 +1,34 @@ +from fastapi import APIRouter, Depends, HTTPException + +from sqlalchemy.orm import Session + +from ..db import crud, models, schemas, database +from ..deps import get_db + +# This line creates the tables based on the subclasses of +# of Base we created in app/db/models.py +models.Base.metadata.create_all(bind=database.engine) + +# We can delegate all calls to the /users route +# to be handled by this router. We can give the +# APIRouter arguments for the prefix /users for +# brevity and the users tag for the local docs info +router = APIRouter( + prefix="/users", + tags=["users"] +) + + +@router.post("/", response_model=schemas.User) +def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): + db_user = crud.get_user_by_email(db, email=user.email) + if db_user: + raise HTTPException(status_code=400, detail="Email already registered") + return crud.create_user(db=db, user=user) + +@router.get("/{user_id}", response_model=schemas.User) +async def get_user(user_id: int, db: Session = Depends(get_db)): + db_user = crud.get_user(db, user_id=user_id) + if db_user is None: + raise HTTPException(status_code=404, detail="User not found") + return db_user \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt index f0615cf..e241501 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,2 +1,5 @@ fastapi -uvicorn \ No newline at end of file +uvicorn +sqlalchemy +pymysql +pymysql[rsa] \ No newline at end of file diff --git a/database/tables/users.sql b/database/tables/users.sql index 86b1898..686a94c 100644 --- a/database/tables/users.sql +++ b/database/tables/users.sql @@ -15,10 +15,10 @@ CREATE TABLE `users_table` ( `user_id` INT NOT NULL auto_increment, `first_name` VARCHAR(50), `last_name` VARCHAR(50), - `email` VARCHAR(50), + `email` VARCHAR(50) NOT NULL, `location` VARCHAR(50), `profile_picture` MEDIUMBLOB, - `recipe_driven` BOOLEAN, + `recipe_driven` BOOLEAN DEFAULT 1, PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;