Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erreur 500 à la création d'une galerie avec un slug vide #6311

Merged
merged 1 commit into from
May 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion zds/gallery/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.urls import reverse

from zds.gallery.models import Gallery, Image, UserGallery
from zds.utils.validators import with_svg_validator
from zds.utils.validators import with_svg_validator, slugify_raise_on_invalid, InvalidSlugError


class GalleryForm(forms.ModelForm):
Expand Down Expand Up @@ -43,6 +43,13 @@ def clean(self):
if "title" in cleaned_data:
del cleaned_data["title"]

try:
slugify_raise_on_invalid(title)
except InvalidSlugError as e:
self._errors["title"] = self.error_class(
[_("Ce titre n'est pas autorisé, son slug est invalide {} !").format(e)]
)

return cleaned_data


Expand Down
12 changes: 12 additions & 0 deletions zds/gallery/tests/tests_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ def test_invalid_gallery_form_no_title(self):

self.assertFalse(form.is_valid())

def test_invalid_gallery_form_invalid_slug(self):
data = {"title": ":", "subtitle": "Test Subtitle"}
form = GalleryForm(data=data)

self.assertFalse(form.is_valid())

def test_valid_gallery_form_title_with_special_characters(self):
data = {"title": "Title:", "subtitle": "Test Subtitle"}
form = GalleryForm(data=data)

self.assertTrue(form.is_valid())


class UserGalleryFormTest(TestCase):
def setUp(self):
Expand Down
1 change: 0 additions & 1 deletion zds/tutorialv2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re

REPLACE_IMAGE_PATTERN = re.compile(r"(?P<start>)(?P<text>!\[.*?\]\()(?P<url>.+?)(?P<end>\))")
VALID_SLUG = re.compile(r"^[a-z0-9\-_]+$")
3 changes: 1 addition & 2 deletions zds/tutorialv2/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
from zds.tutorialv2.models.database import PublishableContent, ContentContributionRole, ContentSuggestion
from django.utils.translation import gettext_lazy as _
from zds.member.models import Profile
from zds.tutorialv2.utils import slugify_raise_on_invalid, InvalidSlugError
from zds.utils.forms import TagValidator, IncludeEasyMDE
from zds.utils.validators import with_svg_validator
from zds.utils.validators import with_svg_validator, slugify_raise_on_invalid, InvalidSlugError


class FormWithTitle(forms.Form):
Expand Down
3 changes: 2 additions & 1 deletion zds/tutorialv2/models/versioned.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from zds.tutorialv2.models.mixins import TemplatableContentModelMixin
from zds.tutorialv2.models import SINGLE_CONTAINER_CONTENT_TYPES, CONTENT_TYPES_BETA, CONTENT_TYPES_REQUIRING_VALIDATION
from zds.tutorialv2.utils import default_slug_pool, export_content, get_commit_author, InvalidOperationError
from zds.tutorialv2.utils import get_blob, InvalidSlugError, check_slug
from zds.tutorialv2.utils import get_blob
from zds.utils.validators import InvalidSlugError, check_slug
from zds.utils.misc import compute_hash
from zds.utils.templatetags.emarkdown import emarkdown
from zds.utils.uuslug_wrapper import slugify
Expand Down
4 changes: 1 addition & 3 deletions zds/tutorialv2/tests/tests_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@
get_target_tagged_tree_for_container,
get_target_tagged_tree_for_extract,
last_participation_is_old,
InvalidSlugError,
BadManifestError,
get_content_from_json,
get_commit_author,
slugify_raise_on_invalid,
check_slug,
)
from zds.utils.validators import slugify_raise_on_invalid, InvalidSlugError, check_slug
from zds.tutorialv2.publication_utils import publish_content, unpublish_content
from zds.tutorialv2.models.database import PublishableContent, PublishedContent, ContentReaction, ContentRead
from django.core.management import call_command
Expand Down
75 changes: 2 additions & 73 deletions zds/tutorialv2/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@

from django.conf import settings
from zds.tutorialv2 import signals
from zds.tutorialv2 import VALID_SLUG
from zds.tutorialv2.models import CONTENT_TYPE_LIST
from zds.utils import get_current_user, old_slugify
from zds.utils import get_current_user
from zds.utils.models import Licence
from zds.utils.uuslug_wrapper import slugify
from zds.utils.validators import slugify_raise_on_invalid, InvalidSlugError, check_slug

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -450,76 +449,6 @@ def get_content_from_json(json, sha, slug_last_draft, public=False, max_title_le
return versioned


class InvalidSlugError(ValueError):
"""Error raised when a slug is invalid. Argument is the slug that cause the error.

``source`` can also be provided, being the sentence from witch the slug was generated, if any.
``had_source`` is set to ``True`` if the source is provided.

"""

def __init__(self, *args, **kwargs):

self.source = ""
self.had_source = False

if "source" in kwargs:
self.source = kwargs.pop("source")
self.had_source = True

super().__init__(*args, **kwargs)


def check_slug(slug):
"""
If the title is incorrect (only special chars so slug is empty).

:param slug: slug to test
:type slug: str
:return: `True` if slug is valid, false otherwise
:rtype: bool
"""

if not VALID_SLUG.match(slug):
return False

if not slug.replace("-", "").replace("_", ""):
return False

if len(slug) > settings.ZDS_APP["content"]["maximum_slug_size"]:
return False

return True


def slugify_raise_on_invalid(title, use_old_slugify=False):
"""
use uuslug to generate a slug but if the title is incorrect (only special chars or slug is empty), an exception
is raised.

:param title: to be slugified title
:type title: str
:param use_old_slugify: use the function `slugify()` defined in zds.utils instead of the one in uuslug. Usefull \
for retro-compatibility with the old article/tutorial module, SHOULD NOT be used for the new one !
:type use_old_slugify: bool
:raise InvalidSlugError: on incorrect slug
:return: the slugified title
:rtype: str
"""

if not isinstance(title, str):
raise InvalidSlugError("", source=title)
if not use_old_slugify:
slug = slugify(title)
else:
slug = old_slugify(title)

if not check_slug(slug):
raise InvalidSlugError(slug, source=title)

return slug


def fill_containers_from_json(json_sub, parent):
"""Function which call itself to fill container

Expand Down
2 changes: 1 addition & 1 deletion zds/tutorialv2/views/archives.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
BadArchiveError,
get_content_from_json,
BadManifestError,
InvalidSlugError,
default_slug_pool,
init_new_repo,
)
from zds.utils.validators import InvalidSlugError
from zds.utils.uuslug_wrapper import slugify


Expand Down
3 changes: 3 additions & 0 deletions zds/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import re

from django.template import defaultfilters

VALID_SLUG = re.compile(r"^[a-z0-9\-_]+$")

try:
from threading import local
Expand Down
74 changes: 74 additions & 0 deletions zds/utils/validators.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from django.conf import settings
from django.core import validators

from zds.utils import old_slugify, VALID_SLUG
from zds.utils.uuslug_wrapper import slugify


def with_svg_validator(value):
"""
Expand All @@ -12,3 +16,73 @@ def with_svg_validator(value):
return validators.FileExtensionValidator(allowed_extensions=validators.get_available_image_extensions() + ["svg"])(
value
)


def slugify_raise_on_invalid(title, use_old_slugify=False):
"""
use uuslug to generate a slug but if the title is incorrect (only special chars or slug is empty), an exception
is raised.

:param title: to be slugified title
:type title: str
:param use_old_slugify: use the function `slugify()` defined in zds.utils instead of the one in uuslug. Usefull \
for retro-compatibility with the old article/tutorial module, SHOULD NOT be used for the new one !
:type use_old_slugify: bool
:raise InvalidSlugError: on incorrect slug
:return: the slugified title
:rtype: str
"""

if not isinstance(title, str):
raise InvalidSlugError("", source=title)
if not use_old_slugify:
slug = slugify(title)
else:
slug = old_slugify(title)

if not check_slug(slug):
raise InvalidSlugError(slug, source=title)

return slug


class InvalidSlugError(ValueError):
"""Error raised when a slug is invalid. Argument is the slug that cause the error.

``source`` can also be provided, being the sentence from witch the slug was generated, if any.
``had_source`` is set to ``True`` if the source is provided.

"""

def __init__(self, *args, **kwargs):

self.source = ""
self.had_source = False

if "source" in kwargs:
self.source = kwargs.pop("source")
self.had_source = True

super().__init__(*args, **kwargs)


def check_slug(slug):
"""
If the title is incorrect (only special chars so slug is empty).

:param slug: slug to test
:type slug: str
:return: `True` if slug is valid, false otherwise
:rtype: bool
"""

if not VALID_SLUG.match(slug):
return False

if not slug.replace("-", "").replace("_", ""):
return False

if len(slug) > settings.ZDS_APP["content"]["maximum_slug_size"]:
return False

return True