mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-07 16:33:10 -05:00
Feature/misc tasks (#864)
* feat(backend): 🌐 make foods/ingredients translatable * feat(backend): ✨ add remember me support for login - 14 days * feat(frontend): 💄 add persistent darkmode for user sessions * capture #859 * feat(frontend): 💄 add basic open-graph data for site links
This commit is contained in:
@@ -3,6 +3,7 @@ from pathlib import Path
|
||||
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.db.data_access_layer.access_model_factory import Database
|
||||
from mealie.schema.recipe import CreateIngredientFood, CreateIngredientUnit
|
||||
|
||||
CWD = Path(__file__).parent
|
||||
logger = get_logger(__name__)
|
||||
@@ -14,21 +15,26 @@ def get_default_foods():
|
||||
return foods
|
||||
|
||||
|
||||
def get_default_units():
|
||||
def get_default_units() -> dict[str, str]:
|
||||
with open(CWD.joinpath("resources", "units", "en-us.json"), "r") as f:
|
||||
units = json.loads(f.read())
|
||||
return units
|
||||
|
||||
|
||||
def default_recipe_unit_init(db: Database) -> None:
|
||||
for unit in get_default_units():
|
||||
for unit in get_default_units().values():
|
||||
try:
|
||||
db.ingredient_units.create(unit)
|
||||
db.ingredient_units.create(
|
||||
CreateIngredientUnit(
|
||||
name=unit["name"], description=unit["description"], abbreviation=unit["abbreviation"]
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
for food in get_default_foods():
|
||||
try:
|
||||
db.ingredient_foods.create(food)
|
||||
|
||||
db.ingredient_foods.create(CreateIngredientFood(name=food, description=""))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,122 +1,102 @@
|
||||
[
|
||||
{
|
||||
{
|
||||
"teaspoon": {
|
||||
"name": "teaspoon",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "tsp"
|
||||
},
|
||||
{
|
||||
"tablespoon": {
|
||||
"name": "tablespoon",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "tbsp"
|
||||
},
|
||||
{
|
||||
"cup": {
|
||||
"name": "cup",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "cup"
|
||||
},
|
||||
{
|
||||
"fluid-ounce": {
|
||||
"name": "fluid ounce",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "fl oz"
|
||||
},
|
||||
{
|
||||
"pint": {
|
||||
"name": "pint",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "pt"
|
||||
},
|
||||
{
|
||||
"quart": {
|
||||
"name": "quart",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "qt"
|
||||
},
|
||||
{
|
||||
"gallon": {
|
||||
"name": "gallon",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "gal"
|
||||
},
|
||||
{
|
||||
"milliliter": {
|
||||
"name": "milliliter",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "ml"
|
||||
},
|
||||
{
|
||||
"liter": {
|
||||
"name": "liter",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "l"
|
||||
},
|
||||
{
|
||||
"pound": {
|
||||
"name": "pound",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "lb"
|
||||
},
|
||||
{
|
||||
"ounce": {
|
||||
"name": "ounce",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "oz"
|
||||
},
|
||||
{
|
||||
"gram": {
|
||||
"name": "gram",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "g"
|
||||
},
|
||||
{
|
||||
"kilogram": {
|
||||
"name": "kilogram",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "kg"
|
||||
},
|
||||
{
|
||||
"milligram": {
|
||||
"name": "milligram",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": "mg"
|
||||
},
|
||||
{
|
||||
"splash": {
|
||||
"name": "splash",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": ""
|
||||
},
|
||||
{
|
||||
"dash": {
|
||||
"name": "dash",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": ""
|
||||
},
|
||||
{
|
||||
"serving": {
|
||||
"name": "serving",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": ""
|
||||
},
|
||||
{
|
||||
"head": {
|
||||
"name": "head",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": ""
|
||||
},
|
||||
{
|
||||
"clove": {
|
||||
"name": "clove",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": ""
|
||||
},
|
||||
{
|
||||
"can": {
|
||||
"name": "can",
|
||||
"description": "",
|
||||
"fraction": true,
|
||||
"abbreviation": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, Request, status
|
||||
from datetime import timedelta
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, Form, Request, status
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from sqlalchemy.orm.session import Session
|
||||
@@ -15,12 +18,31 @@ public_router = APIRouter(tags=["Users: Authentication"])
|
||||
user_router = UserAPIRouter(tags=["Users: Authentication"])
|
||||
|
||||
|
||||
@public_router.post("/token/long")
|
||||
class CustomOAuth2Form(OAuth2PasswordRequestForm):
|
||||
def __init__(
|
||||
self,
|
||||
grant_type: str = Form(None, regex="password"),
|
||||
username: str = Form(...),
|
||||
password: str = Form(...),
|
||||
remember_me: bool = Form(False),
|
||||
scope: str = Form(""),
|
||||
client_id: Optional[str] = Form(None),
|
||||
client_secret: Optional[str] = Form(None),
|
||||
):
|
||||
self.grant_type = grant_type
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.remember_me = remember_me
|
||||
self.scopes = scope.split()
|
||||
self.client_id = client_id
|
||||
self.client_secret = client_secret
|
||||
|
||||
|
||||
@public_router.post("/token")
|
||||
def get_token(
|
||||
background_tasks: BackgroundTasks,
|
||||
request: Request,
|
||||
data: OAuth2PasswordRequestForm = Depends(),
|
||||
data: CustomOAuth2Form = Depends(),
|
||||
session: Session = Depends(generate_session),
|
||||
):
|
||||
email = data.username
|
||||
@@ -37,7 +59,8 @@ def get_token(
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
access_token = security.create_access_token(dict(sub=user.email))
|
||||
duration = timedelta(days=14) if data.remember_me else None
|
||||
access_token = security.create_access_token(dict(sub=user.email), duration)
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ def scrape_image(image_url: str, slug: str) -> Path:
|
||||
|
||||
all_image_requests = []
|
||||
for url in image_url:
|
||||
if isinstance(url, dict):
|
||||
url = url.get("url", "")
|
||||
try:
|
||||
r = requests.get(url, stream=True, headers={"User-Agent": _FIREFOX_UA})
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user