feature/secure-routes (#226)

* secure routes

* add token to test routes

* fix duplicate data

Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
Hayden 2021-03-28 12:42:21 -08:00 committed by GitHub
commit 09765979e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 142 additions and 114 deletions

View file

@ -4,6 +4,7 @@ import shutil
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from mealie.core.config import BACKUP_DIR, TEMPLATE_DIR
from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user
from mealie.schema.backup import BackupJob, ImportJob, Imports, LocalBackup
from mealie.schema.snackbar import SnackResponse
from mealie.services.backups import imports
@ -11,7 +12,7 @@ from mealie.services.backups.exports import backup_all
from sqlalchemy.orm.session import Session
from starlette.responses import FileResponse
router = APIRouter(prefix="/api/backups", tags=["Backups"])
router = APIRouter(prefix="/api/backups", tags=["Backups"], dependencies=[Depends(get_current_user)])
@router.get("/available", response_model=Imports)
@ -52,7 +53,7 @@ def export_database(data: BackupJob, session: Session = Depends(generate_session
@router.post("/upload")
def upload_backup_zipfile(archive: UploadFile = File(...)):
def upload_backup_file(archive: UploadFile = File(...)):
""" Upload a .zip File to later be imported into Mealie """
dest = BACKUP_DIR.joinpath(archive.filename)
@ -66,7 +67,7 @@ def upload_backup_zipfile(archive: UploadFile = File(...)):
@router.get("/{file_name}/download")
async def upload_nextcloud_zipfile(file_name: str):
async def download_backup_file(file_name: str):
""" Upload a .zip File to later be imported into Mealie """
file = BACKUP_DIR.joinpath(file_name)

View file

@ -1,9 +1,10 @@
import json
from fastapi import APIRouter, Depends
from mealie.core.config import APP_VERSION, DEBUG_DIR, LOGGER_FILE
from fastapi import APIRouter
from mealie.routes.deps import get_current_user
router = APIRouter(prefix="/api/debug", tags=["Debug"])
router = APIRouter(prefix="/api/debug", tags=["Debug"], dependencies=[Depends(get_current_user)])
@router.get("/version")
@ -25,9 +26,7 @@ async def get_log(num: int):
""" Doc Str """
with open(LOGGER_FILE, "rb") as f:
log_text = tail(f, num)
HTML_RESPONSE = log_text
return HTML_RESPONSE
return log_text
def tail(f, lines=20):

View file

@ -25,9 +25,7 @@ def get_all_meals(
@router.post("/create")
def create_meal_plan(
data: MealPlanIn,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
data: MealPlanIn, session: Session = Depends(generate_session), current_user=Depends(get_current_user)
):
""" Creates a meal plan database entry """
processed_plan = process_meals(session, data)
@ -37,7 +35,12 @@ def create_meal_plan(
@router.put("/{plan_id}")
def update_meal_plan(plan_id: str, meal_plan: MealPlanIn, session: Session = Depends(generate_session)):
def update_meal_plan(
plan_id: str,
meal_plan: MealPlanIn,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Updates a meal plan based off ID """
processed_plan = process_meals(session, meal_plan)
processed_plan = MealPlanInDB(uid=plan_id, **processed_plan.dict())
@ -47,7 +50,7 @@ def update_meal_plan(plan_id: str, meal_plan: MealPlanIn, session: Session = Dep
@router.delete("/{plan_id}")
def delete_meal_plan(plan_id, session: Session = Depends(generate_session)):
def delete_meal_plan(plan_id, session: Session = Depends(generate_session), current_user=Depends(get_current_user)):
""" Removes a meal plan from the database """
db.meals.delete(session, plan_id)
@ -56,20 +59,14 @@ def delete_meal_plan(plan_id, session: Session = Depends(generate_session)):
@router.get("/this-week", response_model=MealPlanInDB)
def get_this_week(
session: Session = Depends(generate_session),
current_user: UserInDB = Depends(get_current_user),
):
def get_this_week(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)):
""" Returns the meal plan data for this week """
return db.groups.get_meals(session, current_user.group)[0]
@router.get("/today", tags=["Meal Plan"])
def get_today(
session: Session = Depends(generate_session),
current_user: UserInDB = Depends(get_current_user),
):
def get_today(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)):
"""
Returns the recipe slug for the meal scheduled for today.
If no meal is scheduled nothing is returned

View file

@ -1,6 +1,7 @@
from fastapi import APIRouter, Depends
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends
from mealie.routes.deps import get_current_user
from mealie.schema.meal import MealPlanInDB
from mealie.schema.recipe import Recipe
from sqlalchemy.orm.session import Session
@ -9,13 +10,15 @@ router = APIRouter(prefix="/api/meal-plans", tags=["Meal Plan"])
@router.get("/{id}/shopping-list")
def get_shopping_list(id: str, session: Session = Depends(generate_session)):
def get_shopping_list(
id: str,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
#! Refactor into Single Database Call
mealplan = db.meals.get(session, id)
mealplan: MealPlanInDB
slugs = [x.slug for x in mealplan.meals]
recipes: list[Recipe] = [db.recipes.get(session, x) for x in slugs]
ingredients = [{"name": x.name, "recipeIngredient": x.recipeIngredient} for x in recipes if x]
return ingredients
return [{"name": x.name, "recipeIngredient": x.recipeIngredient} for x in recipes if x]

View file

@ -2,16 +2,17 @@ import operator
import shutil
from typing import List
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from mealie.core.config import MIGRATION_DIR
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from mealie.routes.deps import get_current_user
from mealie.schema.migration import MigrationFile, Migrations
from mealie.schema.snackbar import SnackResponse
from mealie.services.migrations.chowdown import chowdown_migrate as chowdow_migrate
from mealie.services.migrations.nextcloud import migrate as nextcloud_migrate
from sqlalchemy.orm.session import Session
from mealie.schema.snackbar import SnackResponse
router = APIRouter(prefix="/api/migrations", tags=["Migration"])
router = APIRouter(prefix="/api/migrations", tags=["Migration"], dependencies=[Depends(get_current_user)])
@router.get("", response_model=List[Migrations])

View file

@ -1,3 +1,4 @@
from mealie.routes.deps import get_current_user
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends
@ -26,7 +27,7 @@ def get_all_recipes_by_category(category: str, session: Session = Depends(genera
@router.delete("/{category}")
async def delete_recipe_category(category: str, session: Session = Depends(generate_session)):
async def delete_recipe_category(category: str, session: Session = Depends(generate_session), current_user=Depends(get_current_user)):
"""Removes a recipe category from the database. Deleting a
category does not impact a recipe. The category will be removed
from any recipes that contain it"""

View file

@ -1,8 +1,9 @@
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends, File, Form, HTTPException
from fastapi.logger import logger
from fastapi.responses import FileResponse
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user
from mealie.schema.recipe import Recipe, RecipeURLIn
from mealie.schema.snackbar import SnackResponse
from mealie.services.image_services import read_image, write_image
@ -16,7 +17,11 @@ router = APIRouter(
@router.post("/create", status_code=201, response_model=str)
def create_from_json(data: Recipe, session: Session = Depends(generate_session)) -> str:
def create_from_json(
data: Recipe,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
) -> str:
""" Takes in a JSON string and loads data into the database as a new entry"""
recipe: Recipe = db.recipes.create(session, data.dict())
@ -24,7 +29,11 @@ def create_from_json(data: Recipe, session: Session = Depends(generate_session))
@router.post("/create-url", status_code=201, response_model=str)
def parse_recipe_url(url: RecipeURLIn, session: Session = Depends(generate_session)):
def parse_recipe_url(
url: RecipeURLIn,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Takes in a URL and attempts to scrape data and load it into the database """
recipe = create_from_url(url.url)
@ -41,7 +50,12 @@ def get_recipe(recipe_slug: str, session: Session = Depends(generate_session)):
@router.put("/{recipe_slug}")
def update_recipe(recipe_slug: str, data: Recipe, session: Session = Depends(generate_session)):
def update_recipe(
recipe_slug: str,
data: Recipe,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Updates a recipe by existing slug and data. """
recipe: Recipe = db.recipes.update(session, recipe_slug, data.dict())
@ -50,7 +64,11 @@ def update_recipe(recipe_slug: str, data: Recipe, session: Session = Depends(gen
@router.delete("/{recipe_slug}")
def delete_recipe(recipe_slug: str, session: Session = Depends(generate_session)):
def delete_recipe(
recipe_slug: str,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Deletes a recipe by slug """
try:
@ -77,6 +95,7 @@ def update_recipe_image(
image: bytes = File(...),
extension: str = Form(...),
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Removes an existing image and replaces it with the incoming file. """
response = write_image(recipe_slug, image, extension)

View file

@ -1,10 +1,9 @@
from fastapi import APIRouter, Depends
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends
from mealie.routes.deps import get_current_user
from mealie.schema.snackbar import SnackResponse
from sqlalchemy.orm.session import Session
from mealie.schema.snackbar import SnackResponse
from mealie.schema.snackbar import SnackResponse
router = APIRouter(tags=["Recipes"])
@ -27,7 +26,9 @@ def get_all_recipes_by_tag(tag: str, session: Session = Depends(generate_session
@router.delete("/{tag}")
async def delete_recipe_tag(tag: str, session: Session = Depends(generate_session)):
async def delete_recipe_tag(
tag: str, session: Session = Depends(generate_session), current_user=Depends(get_current_user)
):
"""Removes a recipe tag from the database. Deleting a
tag does not impact a recipe. The tag will be removed
from any recipes that contain it"""

View file

@ -57,7 +57,12 @@ async def get_single_page(
@router.put("/{id}")
async def update_single_age(data: CustomPageOut, id: int, session: Session = Depends(generate_session)):
async def update_single_age(
data: CustomPageOut,
id: int,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Removes a custom page from the database """
return db.custom_pages.update(session, id, data.dict())

View file

@ -1,13 +1,12 @@
from fastapi import APIRouter, Depends
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends
from mealie.routes.deps import get_current_user
from mealie.schema.settings import SiteSettings
from mealie.schema.snackbar import SnackResponse
from mealie.schema.user import GroupInDB, UserInDB
from sqlalchemy.orm.session import Session
from mealie.utils.post_webhooks import post_webhooks
from mealie.routes.deps import get_current_user
from sqlalchemy.orm.session import Session
router = APIRouter(prefix="/api/site-settings", tags=["Settings"])
@ -20,7 +19,11 @@ def get_main_settings(session: Session = Depends(generate_session)):
@router.put("")
def update_settings(data: SiteSettings, session: Session = Depends(generate_session)):
def update_settings(
data: SiteSettings,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Returns Site Settings """
db.settings.update(session, 1, data.dict())

View file

@ -1,9 +1,10 @@
from mealie.db.db_setup import generate_session
from fastapi import APIRouter, Depends
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user
from mealie.schema.snackbar import SnackResponse
from mealie.schema.theme import SiteTheme
from sqlalchemy.orm.session import Session
from mealie.schema.snackbar import SnackResponse
from mealie.db.database import db
router = APIRouter(prefix="/api", tags=["Themes"])
@ -16,7 +17,7 @@ def get_all_themes(session: Session = Depends(generate_session)):
@router.post("/themes/create")
def create_theme(data: SiteTheme, session: Session = Depends(generate_session)):
def create_theme(data: SiteTheme, session: Session = Depends(generate_session), current_user=Depends(get_current_user)):
""" Creates a site color theme database entry """
db.themes.create(session, data.dict())
@ -30,7 +31,12 @@ def get_single_theme(theme_name: str, session: Session = Depends(generate_sessio
@router.put("/themes/{theme_name}")
def update_theme(theme_name: str, data: SiteTheme, session: Session = Depends(generate_session)):
def update_theme(
theme_name: str,
data: SiteTheme,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
""" Update a theme database entry """
db.themes.update(session, theme_name, data.dict())
@ -38,7 +44,7 @@ def update_theme(theme_name: str, data: SiteTheme, session: Session = Depends(ge
@router.delete("/themes/{theme_name}")
def delete_theme(theme_name: str, session: Session = Depends(generate_session)):
def delete_theme(theme_name: str, session: Session = Depends(generate_session), current_user=Depends(get_current_user)):
""" Deletes theme from the database """
db.themes.delete(session, theme_name)

View file

@ -16,8 +16,8 @@ def backup_data():
}
def test_import(api_client, backup_data):
response = api_client.post("/api/backups/dev_sample_data_2021-Feb-13.zip/import", json=backup_data)
def test_import(api_client, backup_data, token):
response = api_client.post("/api/backups/dev_sample_data_2021-Feb-13.zip/import", json=backup_data, headers=token)
assert response.status_code == 200
for key, value in json.loads(response.content).items():

View file

@ -23,11 +23,10 @@ def get_meal_plan_template(first=None, second=None):
}
@pytest.fixture
def slug_1(api_client):
@pytest.fixture(scope="session")
def slug_1(api_client, token):
# Slug 1
slug_1 = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_test_data[0].url})
slug_1 = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_test_data[0].url}, headers=token)
slug_1 = json.loads(slug_1.content)
yield slug_1
@ -35,10 +34,10 @@ def slug_1(api_client):
api_client.delete(RECIPES_PREFIX + "/" + slug_1)
@pytest.fixture
def slug_2(api_client):
@pytest.fixture(scope="session")
def slug_2(api_client, token):
# Slug 2
slug_2 = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_test_data[1].url})
slug_2 = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_test_data[1].url}, headers=token)
slug_2 = json.loads(slug_2.content)
yield slug_2
@ -99,6 +98,6 @@ def test_delete_mealplan(api_client, token):
existing_mealplan = existing_mealplan[0]
plan_uid = existing_mealplan.get("uid")
response = api_client.delete(f"{MEALPLAN_PREFIX}/{plan_uid}")
response = api_client.delete(f"{MEALPLAN_PREFIX}/{plan_uid}", headers=token)
assert response.status_code == 200

View file

@ -21,11 +21,10 @@ def chowdown_zip():
zip_copy.unlink()
def test_upload_chowdown_zip(api_client, chowdown_zip):
def test_upload_chowdown_zip(api_client, chowdown_zip, token):
response = api_client.post(
f"{MIGRATIONS_PREFIX}/chowdown/upload",
files={"archive": chowdown_zip.open("rb")},
f"{MIGRATIONS_PREFIX}/chowdown/upload", files={"archive": chowdown_zip.open("rb")}, headers=token
)
assert response.status_code == 200
@ -33,10 +32,10 @@ def test_upload_chowdown_zip(api_client, chowdown_zip):
assert MIGRATION_DIR.joinpath("chowdown", chowdown_zip.name).is_file()
def test_import_chowdown_directory(api_client, chowdown_zip):
api_client.delete(f"{RECIPES_PREFIX}/roasted-okra") # TODO: Manage Test Data better
def test_import_chowdown_directory(api_client, chowdown_zip, token):
api_client.delete(f"{RECIPES_PREFIX}/roasted-okra", headers=token) # TODO: Manage Test Data better
selection = chowdown_zip.name
response = api_client.post(f"{MIGRATIONS_PREFIX}/chowdown/{selection}/import")
response = api_client.post(f"{MIGRATIONS_PREFIX}/chowdown/{selection}/import", headers=token)
assert response.status_code == 200
@ -48,9 +47,9 @@ def test_import_chowdown_directory(api_client, chowdown_zip):
assert response.status_code == 200
def test_delete_chowdown_migration_data(api_client, chowdown_zip):
def test_delete_chowdown_migration_data(api_client, chowdown_zip, token):
selection = chowdown_zip.name
response = api_client.delete(f"{MIGRATIONS_PREFIX}/chowdown/{selection}/delete")
response = api_client.delete(f"{MIGRATIONS_PREFIX}/chowdown/{selection}/delete", headers=token)
assert response.status_code == 200
assert not MIGRATION_DIR.joinpath(chowdown_zip.name).is_file()
@ -70,11 +69,9 @@ def nextcloud_zip():
zip_copy.unlink()
def test_upload_nextcloud_zip(api_client, nextcloud_zip):
def test_upload_nextcloud_zip(api_client, nextcloud_zip, token):
response = api_client.post(
f"{MIGRATIONS_PREFIX}/nextcloud/upload",
files={"archive": nextcloud_zip.open("rb")},
f"{MIGRATIONS_PREFIX}/nextcloud/upload", files={"archive": nextcloud_zip.open("rb")}, headers=token
)
assert response.status_code == 200
@ -82,9 +79,9 @@ def test_upload_nextcloud_zip(api_client, nextcloud_zip):
assert MIGRATION_DIR.joinpath("nextcloud", nextcloud_zip.name).is_file()
def test_import_nextcloud_directory(api_client, nextcloud_zip):
def test_import_nextcloud_directory(api_client, nextcloud_zip, token):
selection = nextcloud_zip.name
response = api_client.post(f"{MIGRATIONS_PREFIX}/nextcloud/{selection}/import")
response = api_client.post(f"{MIGRATIONS_PREFIX}/nextcloud/{selection}/import", headers=token)
assert response.status_code == 200
@ -96,9 +93,9 @@ def test_import_nextcloud_directory(api_client, nextcloud_zip):
assert response.status_code == 200
def test_delete__nextcloud_migration_data(api_client, nextcloud_zip):
def test_delete__nextcloud_migration_data(api_client, nextcloud_zip, token):
selection = nextcloud_zip.name
response = api_client.delete(f"{MIGRATIONS_PREFIX}/nextcloud/{selection}/delete")
response = api_client.delete(f"{MIGRATIONS_PREFIX}/nextcloud/{selection}/delete", headers=token)
assert response.status_code == 200
assert not MIGRATION_DIR.joinpath(nextcloud_zip.name).is_file()

View file

@ -7,22 +7,23 @@ from tests.utils.routes import RECIPES_ALL, RECIPES_CREATE, RECIPES_CREATE_URL,
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_create_by_url(api_client, recipe_data: RecipeTestData):
response = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_data.url})
def test_create_by_url(api_client, recipe_data: RecipeTestData, token):
api_client.delete(RECIPES_PREFIX + "/" + recipe_data.expected_slug, headers=token)
response = api_client.post(RECIPES_CREATE_URL, json={"url": recipe_data.url}, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == recipe_data.expected_slug
def test_create_by_json(api_client):
api_client.delete(f"{RECIPES_PREFIX}/banana-bread")
response = api_client.post(RECIPES_CREATE, json=raw_recipe)
def test_create_by_json(api_client, token):
api_client.delete(f"{RECIPES_PREFIX}/banana-bread", headers=token)
response = api_client.post(RECIPES_CREATE, json=raw_recipe, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == "banana-bread"
def test_create_no_image(api_client):
response = api_client.post(RECIPES_CREATE, json=raw_recipe_no_image)
def test_create_no_image(api_client, token):
response = api_client.post(RECIPES_CREATE, json=raw_recipe_no_image, headers=token)
assert response.status_code == 201
assert json.loads(response.text) == "banana-bread-no-image"
@ -46,8 +47,8 @@ def test_read_all_post(api_client):
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_read_update(api_client, recipe_data):
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}")
def test_read_update(api_client, recipe_data, token):
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", headers=token)
assert response.status_code == 200
recipe = json.loads(response.content)
@ -61,7 +62,7 @@ def test_read_update(api_client, recipe_data):
test_categories = ["one", "two", "three"]
recipe["recipeCategory"] = test_categories
response = api_client.put(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", json=recipe)
response = api_client.put(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", json=recipe, headers=token)
assert response.status_code == 200
assert json.loads(response.text) == recipe_data.expected_slug
@ -75,16 +76,16 @@ def test_read_update(api_client, recipe_data):
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_rename(api_client, recipe_data):
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}")
def test_rename(api_client, recipe_data, token):
response = api_client.get(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", headers=token)
assert response.status_code == 200
recipe = json.loads(response.content)
recipe = json.loads(response.text)
new_name = recipe.get("name") + "-rename"
new_slug = slugify(new_name)
recipe["name"] = new_name
response = api_client.put(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", json=recipe)
response = api_client.put(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", json=recipe, headers=token)
assert response.status_code == 200
assert json.loads(response.text) == new_slug
@ -93,6 +94,6 @@ def test_rename(api_client, recipe_data):
@pytest.mark.parametrize("recipe_data", recipe_test_data)
def test_delete(api_client, recipe_data):
response = api_client.delete(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}")
def test_delete(api_client, recipe_data, token):
response = api_client.delete(f"{RECIPES_PREFIX}/{recipe_data.expected_slug}", headers=token)
assert response.status_code == 200

View file

@ -1,14 +1,9 @@
import json
from mealie.schema.settings import SiteSettings
from mealie.schema.theme import SiteTheme
import pytest
from tests.utils.routes import (
SETTINGS_PREFIX,
SETTINGS_UPDATE,
THEMES_CREATE,
THEMES_PREFIX,
)
from mealie.schema.settings import SiteSettings
from mealie.schema.theme import SiteTheme
from tests.utils.routes import SETTINGS_PREFIX, SETTINGS_UPDATE, THEMES_CREATE, THEMES_PREFIX
@pytest.fixture(scope="function")
@ -45,11 +40,11 @@ def test_default_settings(api_client, default_settings):
assert json.loads(response.content) == default_settings
def test_update_settings(api_client, default_settings):
def test_update_settings(api_client, default_settings, token):
default_settings["language"] = "fr"
default_settings["showRecent"] = False
response = api_client.put(SETTINGS_UPDATE, json=default_settings)
response = api_client.put(SETTINGS_UPDATE, json=default_settings, headers=token)
assert response.status_code == 200
@ -63,12 +58,12 @@ def test_default_theme(api_client, default_theme):
assert json.loads(response.content) == default_theme
def test_create_theme(api_client, new_theme):
def test_create_theme(api_client, new_theme, token):
response = api_client.post(THEMES_CREATE, json=new_theme)
response = api_client.post(THEMES_CREATE, json=new_theme, headers=token)
assert response.status_code == 200
response = api_client.get(f"{THEMES_PREFIX}/{new_theme.get('name')}")
response = api_client.get(f"{THEMES_PREFIX}/{new_theme.get('name')}", headers=token)
assert response.status_code == 200
assert json.loads(response.content) == new_theme
@ -86,8 +81,8 @@ def test_read_theme(api_client, default_theme, new_theme):
assert json.loads(response.content) == theme
def test_delete_theme(api_client, default_theme, new_theme):
def test_delete_theme(api_client, default_theme, new_theme, token):
for theme in [default_theme, new_theme]:
response = api_client.delete(f"{THEMES_PREFIX}/{theme.get('name')}")
response = api_client.delete(f"{THEMES_PREFIX}/{theme.get('name')}", headers=token)
assert response.status_code == 200

View file

@ -6,12 +6,12 @@ class RecipeTestData:
recipe_test_data = [
RecipeTestData(
url="https://www.bonappetit.com/recipe/rustic-shrimp-toasts",
expected_slug="rustic-shrimp-toasts",
url="https://www.bonappetit.com/recipe/spinach-thepla-and-vaghareli-dahi",
expected_slug="thepla-recipe-with-vaghareli-dahi",
),
RecipeTestData(
url="https://www.allrecipes.com/recipe/282905/honey-garlic-shrimp/",
expected_slug="honey-garlic-shrimp",
url="https://www.bonappetit.com/recipe/classic-coleslaw",
expected_slug="traditional-coleslaw-recipe",
),
]