diff --git a/setup.py b/setup.py index 05cdf363..410a95a7 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ def get_requirements(fname='requirements.txt'): setup( name="unicms", - version='0.11.6', + version='0.11.7', description="uniCMS is a Django Web Content Management System", author='Giuseppe De Marco, Francesco Filicetti', author_email='giuseppe.demarco@unical.it, francesco.filicetti@unical.it', diff --git a/src/cms/api/exceptions.py b/src/cms/api/exceptions.py index db0fa52d..fdae98e8 100644 --- a/src/cms/api/exceptions.py +++ b/src/cms/api/exceptions.py @@ -1,7 +1,7 @@ import logging from django.core.exceptions import PermissionDenied - +from rest_framework.exceptions import ValidationError logger = logging.getLogger(__name__) @@ -10,3 +10,10 @@ class LoggedPermissionDenied(PermissionDenied): def __init__(self, *args, **kwargs): logger.warning(f'API {kwargs.get("classname")} {kwargs.get("resource")} permission denied') + + +class LoggedValidationException(ValidationError): + + def __init__(self, detail, *args, **kwargs): + logger.warning(f'API {kwargs.get("classname")} {kwargs.get("resource")}: {detail}') + super().__init__(detail) diff --git a/src/cms/api/tests/test_webpath.py b/src/cms/api/tests/test_webpath.py index 31e64427..b969c2c8 100644 --- a/src/cms/api/tests/test_webpath.py +++ b/src/cms/api/tests/test_webpath.py @@ -1,3 +1,4 @@ +import datetime import logging from django.core.exceptions import ObjectDoesNotExist @@ -227,7 +228,7 @@ def test_put(self): # edit child parent ebu_child = ContextUnitTest.create_editorialboard_user(user=user, - webpath=ContextUnitTest.create_webpath(), + webpath=ContextUnitTest.create_webpath(path=datetime.datetime.now().strftime("%f")), permission=3, is_active=True) child = ebu_child.webpath @@ -238,7 +239,8 @@ def test_put(self): 'pk': child.pk}) # change parent - new_parent = ContextUnitTest.create_webpath(site=site) + new_parent = ContextUnitTest.create_webpath(site=site, + path=datetime.datetime.now().strftime("%f")) child_json = {'site': site.pk, 'parent': new_parent.pk, 'name': 'child name', diff --git a/src/cms/api/views/webpath.py b/src/cms/api/views/webpath.py index 0cae0edd..ce170b00 100644 --- a/src/cms/api/views/webpath.py +++ b/src/cms/api/views/webpath.py @@ -17,7 +17,7 @@ from rest_framework.views import APIView from . generics import UniCMSCachedRetrieveUpdateDestroyAPIView, UniCMSListCreateAPIView, UniCMSListSelectOptionsAPIView -from .. exceptions import LoggedPermissionDenied +from .. exceptions import LoggedPermissionDenied, LoggedValidationException from .. serializers import UniCMSFormSerializer @@ -59,7 +59,12 @@ def post(self, request, *args, **kwargs): if not publisher_perms or not parent_locks_ok: raise LoggedPermissionDenied(classname=self.__class__.__name__, resource=request.method) - webpath = serializer.save() + try: + webpath = serializer.save() + except Exception as e: + raise LoggedValidationException(classname=self.__class__.__name__, + resource=request.method, + detail=e) # add permission to webpath if not publisher_perms['allow_descendant']: EditorialBoardEditors.objects.create(user=request.user, @@ -114,7 +119,13 @@ def patch(self, request, *args, **kwargs): if not has_permission: raise LoggedPermissionDenied(classname=self.__class__.__name__, resource=request.method) - return super().patch(request, *args, **kwargs) + try: + return super().patch(request, *args, **kwargs) + except Exception as e: + raise LoggedValidationException(classname=self.__class__.__name__, + resource=request.method, + detail=e) + def put(self, request, *args, **kwargs): item = self.get_queryset().first() @@ -137,7 +148,12 @@ def put(self, request, *args, **kwargs): if not has_permission: raise LoggedPermissionDenied(classname=self.__class__.__name__, resource=request.method) - return super().put(request, *args, **kwargs) + try: + return super().put(request, *args, **kwargs) + except Exception as e: + raise LoggedValidationException(classname=self.__class__.__name__, + resource=request.method, + detail=e) def delete(self, request, *args, **kwargs): item = self.get_queryset().first() diff --git a/src/cms/contexts/models.py b/src/cms/contexts/models.py index 33788d45..805b5ff1 100644 --- a/src/cms/contexts/models.py +++ b/src/cms/contexts/models.py @@ -142,6 +142,13 @@ def save(self, *args, **kwargs): if fullpath != self.fullpath: self.fullpath = fullpath + existent = WebPath.objects.filter(site=self.site, + fullpath=self.fullpath)\ + .exclude(pk=self.pk)\ + .first() + if existent: + raise Exception(f'Existent path "{self.get_full_path()}". Change it') + super(WebPath, self).save(*args, **kwargs) # update also its childs for child_path in WebPath.objects.filter(parent=self): diff --git a/src/cms/contexts/serializers.py b/src/cms/contexts/serializers.py index 383e9293..32e83332 100644 --- a/src/cms/contexts/serializers.py +++ b/src/cms/contexts/serializers.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.utils.text import slugify from cms.api.serializers import UniCMSCreateUpdateSerializer, UniCMSContentTypeClass @@ -83,6 +84,24 @@ def to_representation(self, instance): data['permission_label'] = context_permissions[permission] return data + def validate_path(self, value): + """ + slugify path + """ + return slugify(value) + + def create(self, validated_data): + try: + return WebPath.objects.create(**validated_data) + except Exception as e: + raise e + + def update(self, instance, validated_data): + try: + return super().update(instance, validated_data) + except Exception as e: + raise e + class WebPathSelectOptionsSerializer(serializers.ModelSerializer): diff --git a/src/cms/contexts/tests.py b/src/cms/contexts/tests.py index 7302b687..13e0bc54 100644 --- a/src/cms/contexts/tests.py +++ b/src/cms/contexts/tests.py @@ -1,3 +1,4 @@ +import datetime import logging from django.contrib.auth import get_user_model @@ -61,9 +62,10 @@ def create_webpath(cls, **kwargs): def create_editorialboard_user(cls, **kwargs): data = {'user': cls.create_user() if not kwargs.get('user') else kwargs['user'], 'permission': 1, - 'webpath': cls.create_webpath(), + 'webpath': kwargs.get('webpath') or cls.create_webpath(path=datetime.datetime.now().strftime("%f")), 'is_active': True} for k,v in kwargs.items(): + if k == 'webpath': continue data[k] = v obj = EditorialBoardEditors.objects.create(**data) obj.serialize() @@ -154,8 +156,8 @@ def test_editorialboard_user(self): assert perm # test parent permissions - parent = self.create_webpath() - webpath = self.create_webpath(parent=parent) + parent = self.create_webpath(path="path-1") + webpath = self.create_webpath(path="path-2", parent=parent) user = ebe.user ebe.delete() parent_ebe = self.create_editorialboard_user(user=user, @@ -164,7 +166,7 @@ def test_editorialboard_user(self): EditorialBoardEditors.get_permission(user=user, webpath=webpath) # test no permission webpath - webpath = self.create_webpath() + webpath = self.create_webpath(path="path-3") EditorialBoardEditors.get_permission(user=user, webpath=webpath, check_all=False) diff --git a/src/cms/pages/tests.py b/src/cms/pages/tests.py index 820ee8da..22e29b88 100644 --- a/src/cms/pages/tests.py +++ b/src/cms/pages/tests.py @@ -1,4 +1,5 @@ import logging +import datetime from django.conf import settings from django.test import Client, RequestFactory, TestCase @@ -56,11 +57,18 @@ def create_page(cls, **kwargs): page_template_block = TemplateUnitTest.create_page_block_template() page_template = page_template_block.template + if kwargs.get('webpath'): + webpath = kwargs.get('webpath') + elif kwargs.get('webpath_path'): + webpath = ContextUnitTest.create_webpath(path=kwargs.pop('webpath_path')) + else: + webpath = ContextUnitTest.create_webpath(path=datetime.datetime.now().strftime("%f")) + data = {'is_active': 1, 'draft_of': None, 'name': "Portale dell'Università della Calabria", 'title': 'titolo pagina', - 'webpath': kwargs.get('webpath', None) or ContextUnitTest.create_webpath(), + 'webpath': kwargs.get('webpath', None) or webpath, 'base_template': page_template, 'description': '', 'date_start': timezone.localtime(), @@ -323,7 +331,8 @@ def test_load_menu(cls): def test_home_page(self): - obj = self.create_page(date_end=timezone.localtime()) + obj = self.create_page(date_end=timezone.localtime(), + webpath_path='/') url = reverse('unicms:cms_dispatch') res = self.client.get(url) assert res.status_code == 200 @@ -333,7 +342,7 @@ def test_home_page(self): def test_show_template_blocks_sections(self): - self.create_page() + self.create_page(webpath_path='/') user = ContextUnitTest.create_user(is_staff=1) self.client.force_login(user) url = reverse('unicms:cms_dispatch') diff --git a/src/cms/publications/tests.py b/src/cms/publications/tests.py index 350275bb..a680fad0 100644 --- a/src/cms/publications/tests.py +++ b/src/cms/publications/tests.py @@ -1,3 +1,4 @@ +import datetime import logging from django.conf import settings @@ -47,10 +48,12 @@ def create_pub(cls, count = 4, **kwargs): 'note':'', 'relevance':'0', } + if kwargs.get('webpath_path'): + webpath = ContextUnitTest.create_webpath(path=kwargs.pop('webpath_path')) + else: + webpath = ContextUnitTest.create_webpath(path=datetime.datetime.now().strftime("%f")) for k,v in kwargs.items(): data[k] = v - - webpath = ContextUnitTest.create_webpath() category = PageUnitTest.create_category() for i in range(count): obj = Publication.objects.create(**data) @@ -230,7 +233,7 @@ def test_api_pub_detail(self): def test_publication_handler_view(self): - pub = self.enrich_pub() + pub = self.enrich_pub(webpath_path='/') webpath=pub.related_contexts[0].webpath page = PageUnitTest.create_page(webpath=webpath) @@ -246,13 +249,12 @@ def test_publication_handler_view(self): def test_publication_handler_list(self): - pub = self.enrich_pub() + pub = self.enrich_pub(webpath_path='/') webpath=pub.related_contexts[0].webpath page = PageUnitTest.create_page(webpath=webpath) req = Client(HTTP_HOST='example.org') user = ContextUnitTest.create_user(is_staff=1) req.force_login(user) - url = reverse('unicms:cms_dispatch') lurl = f'{url}{settings.CMS_PUBLICATION_LIST_PREFIX_PATH}' res = req.get(lurl)