Added identity

This commit is contained in:
jableader 2024-04-25 12:03:30 +10:00
parent 6ba6406427
commit edbe082387
6 changed files with 71 additions and 51 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.venv/
__pycache__
data/
.vscode/*

22
main.py
View file

@ -4,8 +4,9 @@ import datetime
from pydantic import BaseModel
from typing import List, Annotated
from fastapi import FastAPI, Depends, Query
from fastapi import FastAPI, Depends, Query, Cookie
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
@ -27,6 +28,9 @@ async def get_db():
finally:
await sql_db.close()
async def cookie_person(user_id: Annotated[int, Cookie(alias='user_id')], conn: sqlite3.Connection = Depends(get_db)) -> persons.Person:
return await persons.find_person_by_id(conn, user_id)
@app.get("/recipes/parse")
async def parse_recipe_handler(url: str, conn: sqlite3.Connection = Depends(get_db)) -> recipes.Recipe:
parsed = await recipes.parse_recipe(conn, url)
@ -89,7 +93,7 @@ async def get_recipe(recipe_id: int, conn: sqlite3.Connection = Depends(get_db))
return r
@app.post('/recipes/')
async def create_recipe(item: recipes.Recipe, conn: sqlite3.Connection = Depends(get_db)) -> recipes.Recipe:
async def create_recipe(item: recipes.Recipe, conn: sqlite3.Connection = Depends(get_db), user: persons.Person = Depends(cookie_person)) -> recipes.Recipe:
if not item.ingredients:
return JSONResponse(status_code=400, content={'message': 'Recipe must have at least one ingredient'})
@ -97,6 +101,7 @@ async def create_recipe(item: recipes.Recipe, conn: sqlite3.Connection = Depends
if not ingredient.product:
return JSONResponse(status_code=400, content={'message': 'Ingredient must have a product'})
item.created_by_id = user.id
await recipes.insert_recipe(conn, item)
for ingredient in item.ingredients:
ingredient.recipe_id = item.id
@ -169,3 +174,16 @@ async def create_person(person: persons.Person, conn: sqlite3.Connection = Depen
await persons.insert(conn, person)
await conn.commit()
return person
class LoginBody(BaseModel):
username: str
@app.post('/auth/login')
async def login(data: LoginBody, conn: sqlite3.Connection = Depends(get_db)) -> persons.Person:
person = await persons.get_by_name(conn, data.username)
if not person:
return JSONResponse(status_code=404, content={'message': 'Person not found'})
response = JSONResponse(content=jsonable_encoder(person))
response.set_cookie(key='user_id', value=str(person.id))
return response

View file

@ -1,31 +0,0 @@
from typing import List, ClassVar
from pydantic import BaseModel
"""
class Person:
def __init__(self, id: int, name: str) -> None:
self.id = id
self.name = name
class Meal:
def __init__(self, id: int, date: datetime, chef: List[Person], cleanup: List[Person],
consumers: List[Person], recipes: List[Recipe]) -> None:
self.id = id
self.date = date
self.chef = chef
self.cleanup = cleanup
self.consumers = consumers
self.recipes = recipes
class ShoppingListItem:
def __init__(self, id: int, food_item: Product, measure: Measurement, source: Union[Meal, None]) -> None:
self.id = id
self.food_item = food_item
self.measure = measure
self.source = source
class ShoppingList:
def __init__(self, date: datetime, items: List[ShoppingListItem]) -> None:
self.date = date
self.items = items
"""

View file

@ -1,5 +1,5 @@
from pydantic import BaseModel
from typing import List, ClassVar
from typing import List
class Person(BaseModel):
id: int
@ -12,6 +12,22 @@ async def create(conn):
name TEXT UNIQUE
);''')
await insert(conn, Person(id=0, name='Jacob'))
await insert(conn, Person(id=0, name='Ellie'))
await insert(conn, Person(id=0, name='Ryan'))
await insert(conn, Person(id=0, name='Chris'))
async def get_by_name(conn, name: str) -> Person:
cursor = await conn.execute('''
SELECT id, name
FROM Person
WHERE name = ?
''', (name,))
row = await cursor.fetchone()
if not row:
return None
return Person(id=row[0], name=row[1])
async def get_by_id(conn, id: int) -> Person:
cursor = await conn.execute('''
SELECT id, name

View file

@ -2,8 +2,6 @@ from recipes.db import Recipe, insert_recipe, find_recipe_by_id, get_all, find_r
from recipes.scraping import scrape_recipe_ldata as _scrape_recipe_ldata
from ingredients import parse_ingredient_from_nlp as _parse_ingredient_from_nlp, match_existing_products as _match_existing_products
import json
async def parse_recipe(conn, url: str) -> Recipe:
ldata = await _scrape_recipe_ldata(url)
if ldata:
@ -30,6 +28,5 @@ async def _get_recipe_from_ldata(conn, url: str, ldata: dict) -> dict:
name=name,
link=url,
image_urls=images,
raw_data=json.dumps(ldata),
ingredients=ingredients
)

View file

@ -1,34 +1,53 @@
import json
import json, datetime
from persons import Person
from ingredients import Ingredient, find_ingredients_by_recipe_id
from pydantic import BaseModel, Field
from typing import List, ClassVar, Tuple
from pydantic import BaseModel
from typing import List, ClassVar, Tuple, Optional
class Recipe(BaseModel):
KEYS: ClassVar[List[str]] = ['id', 'name', 'link', 'image_urls', 'raw_data']
KEYS: ClassVar[List[str]] = ['id', 'name', 'link', 'image_urls', 'based_on_recipe', 'created_by_id', 'date_created', 'hidden_by_id', 'date_hidden']
id: int
name: str
link: str
raw_data: str
image_urls: List[str] = []
ingredients: List[Ingredient] = []
based_on_recipe: Optional[int] = None
date_created: Optional[datetime.datetime] = None
created_by_id: Optional[int] = None
created_by: Optional[Person] = None
date_hidden: Optional[datetime.datetime] = None
hidden_by_id: Optional[int] = None
hidden_by: Optional[Person] = None
async def create(conn):
await conn.execute('''
CREATE TABLE IF NOT EXISTS Recipe (
id INTEGER PRIMARY KEY,
name TEXT,
link TEXT,
image_urls TEXT,
raw_data TEXT
name TEXT NOT NULL,
link TEXT NOT NULL,
image_urls TEXT NOT NULL,
based_on_recipe INTEGER NULL,
date_created DATETIME DEFAULT CURRENT_TIMESTAMP,
created_by_id INTEGER NOT NULL,
date_hidden DATETIME DEFAULT NULL,
hidden_by_id INTEGER DEFAULT NULL,
FOREIGN KEY (based_on_recipe) REFERENCES Recipe(id)
FOREIGN KEY (created_by_id) REFERENCES Person(id)
FOREIGN KEY (hidden_by_id) REFERENCES Person(id)
);''')
async def insert_recipe(conn, recipe: Recipe):
async with conn.execute('''
INSERT INTO Recipe (name, link, raw_data, image_urls)
VALUES (?, ?, ?, ?)
''', (recipe.name, recipe.link, recipe.raw_data, json.dumps(recipe.image_urls))) as cursor:
INSERT INTO Recipe (name, link, image_urls, based_on_recipe, created_by_id)
VALUES (?, ?, ?, ?, ?)
''', (recipe.name, recipe.link, json.dumps(recipe.image_urls), recipe.based_on_recipe, recipe.created_by_id)) as cursor:
recipe.id = cursor.lastrowid
def row_to_recipe(col_tuples: List[Tuple[str, ...]]) -> Recipe: