mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-10-26 15:54:20 -04:00
fix: dash slug names (#5709)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
144d4caea6
commit
107dfc34de
@@ -22,6 +22,14 @@ class PermissionDenied(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SlugError(Exception):
|
||||
"""
|
||||
This exception is raised when the recipe name generates an invalid slug.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NoEntryFound(Exception):
|
||||
"""
|
||||
This exception is raised when a user tries to access a resource that does not exist.
|
||||
|
||||
@@ -4,6 +4,7 @@ from uuid import UUID
|
||||
|
||||
import orjson
|
||||
import sqlalchemy
|
||||
import sqlalchemy.exc
|
||||
from fastapi import (
|
||||
BackgroundTasks,
|
||||
Depends,
|
||||
@@ -80,13 +81,25 @@ class RecipeController(BaseRecipeController):
|
||||
|
||||
if thrownType == exceptions.PermissionDenied:
|
||||
self.logger.error("Permission Denied on recipe controller action")
|
||||
raise HTTPException(status_code=403, detail=ErrorResponse.respond(message="Permission Denied"))
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN, detail=ErrorResponse.respond(message="Permission Denied")
|
||||
)
|
||||
elif thrownType == exceptions.NoEntryFound:
|
||||
self.logger.error("No Entry Found on recipe controller action")
|
||||
raise HTTPException(status_code=404, detail=ErrorResponse.respond(message="No Entry Found"))
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=ErrorResponse.respond(message="No Entry Found")
|
||||
)
|
||||
elif thrownType == sqlalchemy.exc.IntegrityError:
|
||||
self.logger.error("SQL Integrity Error on recipe controller action")
|
||||
raise HTTPException(status_code=400, detail=ErrorResponse.respond(message="Recipe already exists"))
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail=ErrorResponse.respond(message="Recipe already exists")
|
||||
)
|
||||
elif thrownType == exceptions.SlugError:
|
||||
self.logger.error("Failed to generate a valid slug from recipe name")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=ErrorResponse.respond(message="Unable to generate recipe slug"),
|
||||
)
|
||||
else:
|
||||
self.logger.error("Unknown Error on recipe controller action")
|
||||
self.logger.exception(ex)
|
||||
|
||||
@@ -14,6 +14,7 @@ from sqlalchemy.orm import Session, joinedload, selectinload
|
||||
from sqlalchemy.orm.interfaces import LoaderOption
|
||||
|
||||
from mealie.core.config import get_app_dirs
|
||||
from mealie.core.exceptions import SlugError
|
||||
from mealie.db.models.users.users import User
|
||||
from mealie.schema._mealie import MealieModel, SearchType
|
||||
from mealie.schema._mealie.mealie_model import UpdatedAtField
|
||||
@@ -45,8 +46,13 @@ def create_recipe_slug(name: str, max_length: int = 250) -> str:
|
||||
|
||||
Returns:
|
||||
A truncated slug string
|
||||
|
||||
Raises:
|
||||
ValueError: If the name cannot be converted to a valid slug
|
||||
"""
|
||||
generated_slug = slugify(name)
|
||||
if not generated_slug:
|
||||
raise SlugError("Recipe name cannot be empty or contain only special characters")
|
||||
if len(generated_slug) > max_length:
|
||||
generated_slug = generated_slug[:max_length]
|
||||
return generated_slug
|
||||
|
||||
@@ -929,6 +929,13 @@ def test_create_recipe_with_extremely_long_slug(api_client: TestClient, unique_u
|
||||
assert updated_recipe["slug"] == slugify(new_name)
|
||||
|
||||
|
||||
def test_create_recipe_slug_not_empty(api_client: TestClient, unique_user: TestUser):
|
||||
recipe_name = "---" # will result in an empty slug
|
||||
|
||||
response = api_client.post(api_routes.recipes, json={"name": recipe_name}, headers=unique_user.token)
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_create_recipe_slug_length_validation(api_client: TestClient, unique_user: TestUser):
|
||||
"""Test that recipe slugs are properly truncated to a reasonable length."""
|
||||
very_long_name = "A" * 500 # 500 character name
|
||||
|
||||
Reference in New Issue
Block a user