- {% url "content:view-version" pk=validation.content.pk slug=validation.content.slug version=validation.version as url_validation_version %}
+ {% url "content:validation-view" pk=validation.content.pk slug=validation.content.slug as url_validation_version %}
{{ validation.versioned_content.title }}
diff --git a/zds/tutorialv2/tests/tests_views/tests_contentvalidationview.py b/zds/tutorialv2/tests/tests_views/tests_contentvalidationview.py
new file mode 100644
index 0000000000..c634b93439
--- /dev/null
+++ b/zds/tutorialv2/tests/tests_views/tests_contentvalidationview.py
@@ -0,0 +1,76 @@
+from django.test import TestCase
+from django.urls import reverse
+
+from zds.tutorialv2.tests import TutorialTestMixin, override_for_contents
+from zds.member.tests.factories import ProfileFactory, StaffProfileFactory
+from zds.tutorialv2.tests.factories import PublishableContentFactory, ValidationFactory
+
+
+def request_validation(content):
+ """Emulate a proper validation request."""
+ ValidationFactory(content=content, status="PENDING")
+ content.sha_validation = content.sha_draft
+ content.save()
+
+
+@override_for_contents()
+class PermissionTests(TutorialTestMixin, TestCase):
+ """Test permissions and associated behaviors, such as redirections and status codes."""
+
+ def setUp(self):
+ # Create a content and put it in validation
+ self.author = ProfileFactory().user
+ content = PublishableContentFactory(author_list=[self.author])
+ request_validation(content)
+
+ # Data about the tested route
+ url_args = {"pk": content.pk, "slug": content.slug}
+ self.target_url = reverse("content:validation-view", kwargs=url_args)
+ self.login_url = reverse("member-login") + "?next=" + self.target_url
+
+ def test_not_authenticated(self):
+ """Test that unauthenticated users are redirected to the login page."""
+ self.client.logout() # ensure no user is authenticated
+ response = self.client.get(self.target_url)
+ self.assertRedirects(response, self.login_url)
+
+ def test_authenticated_author(self):
+ """Test that authors can reach the page."""
+ self.client.force_login(self.author)
+ response = self.client.get(self.target_url)
+ self.assertEqual(response.status_code, 200)
+
+ def test_authenticated_staff(self):
+ """Test that staffs can reach the page."""
+ staff = StaffProfileFactory().user
+ self.client.force_login(staff)
+ response = self.client.get(self.target_url)
+ self.assertEqual(response.status_code, 200)
+
+ def test_authenticated_outsider(self):
+ """Test that unauthorized users get a 403."""
+ outsider = ProfileFactory().user
+ self.client.force_login(outsider)
+ response = self.client.get(self.target_url)
+ self.assertEqual(response.status_code, 403)
+
+
+@override_for_contents()
+class FunctionalTests(TutorialTestMixin, TestCase):
+ """Test the behavior of the feature."""
+
+ def setUp(self):
+ # Create a content and put it in validation
+ self.author = StaffProfileFactory().user
+ content = PublishableContentFactory(author_list=[self.author])
+ request_validation(content)
+
+ # Data about the tested route
+ url_args = {"pk": content.pk, "slug": content.slug}
+ self.target_url = reverse("content:validation-view", kwargs=url_args)
+
+ def test_validation_actions_shown(self):
+ """Test that the validation page shows the validation actions."""
+ self.client.force_login(self.author)
+ response = self.client.get(self.target_url)
+ self.assertContains(response, "Validation")
diff --git a/zds/tutorialv2/urls/urls_contents.py b/zds/tutorialv2/urls/urls_contents.py
index ee0629f454..e3299d0db5 100644
--- a/zds/tutorialv2/urls/urls_contents.py
+++ b/zds/tutorialv2/urls/urls_contents.py
@@ -2,6 +2,8 @@
from django.views.generic.base import RedirectView
from zds.tutorialv2.views.contents import CreateContent, EditContent, EditContentLicense, DeleteContent
+from zds.tutorialv2.views.display.container import ContainerValidationView
+from zds.tutorialv2.views.display.content import ContentValidationView
from zds.tutorialv2.views.events import EventsList
from zds.tutorialv2.views.goals import EditGoals, MassEditGoals, ViewContentsByGoal
from zds.tutorialv2.views.labels import EditLabels, ViewContentsByLabel
@@ -73,6 +75,24 @@ def get_beta_pages():
return beta_pages
+def get_validation_pages():
+ base_pattern = "validation//"
+ pages = [
+ path(
+ f"{base_pattern}///",
+ ContainerValidationView.as_view(public_is_prioritary=False),
+ name="validation-view-container",
+ ),
+ path(
+ f"{base_pattern}//",
+ ContainerValidationView.as_view(public_is_prioritary=False),
+ name="validation-view-container",
+ ),
+ path(f"{base_pattern}/", ContentValidationView.as_view(), name="validation-view"),
+ ]
+ return pages
+
+
def get_version_pages():
base_pattern = "version///"
specific_version_page = [
@@ -91,6 +111,7 @@ def get_version_pages():
feeds
+ get_version_pages()
+ get_beta_pages()
+ + get_validation_pages()
+ [
path(
"voir//", ContentOfAuthor.as_view(type="ALL", context_object_name="contents"), name="find-all"
diff --git a/zds/tutorialv2/views/display/config.py b/zds/tutorialv2/views/display/config.py
index f98f5590f8..085da2fe31 100644
--- a/zds/tutorialv2/views/display/config.py
+++ b/zds/tutorialv2/views/display/config.py
@@ -474,3 +474,14 @@ def __init__(self, user, content: PublishableContent, versioned_content: Version
self.validation_actions.enabled = False
self.online_config.enabled = False
self.info_config.show_warn_typo = True
+
+
+class ConfigForValidationView(ViewConfig):
+ def __init__(self, user, content: PublishableContent, versioned_content: VersionedContent):
+ super().__init__(user, content, versioned_content)
+ self.beta_actions.enabled = False
+ self.administration_actions.enabled = False
+ self.validation_actions.enabled = True
+ self.validation_actions.show_validation_link = False
+ self.online_config.enabled = False
+ self.info_config.show_warn_typo = True
diff --git a/zds/tutorialv2/views/display/container.py b/zds/tutorialv2/views/display/container.py
index e041ef87e1..f1fececbc4 100644
--- a/zds/tutorialv2/views/display/container.py
+++ b/zds/tutorialv2/views/display/container.py
@@ -12,6 +12,7 @@
ConfigForOnlineView,
ConfigForBetaView,
ConfigForVersionView,
+ ConfigForValidationView,
)
@@ -187,3 +188,34 @@ def get_base_url(self):
route_parameters = {"pk": self.object.pk, "slug": self.object.slug}
url = reverse("content:beta-view", kwargs=route_parameters)
return url
+
+
+class ContainerValidationView(LoginRequiredMixin, ContainerBaseView):
+ """Show the validation page of a container."""
+
+ sha = None
+ warn_typo_public = False
+
+ def get_object(self, queryset=None):
+ obj = super().get_object(queryset)
+
+ if not obj.sha_validation:
+ raise Http404("Aucune version en validation n'existe pour ce contenu.")
+ else:
+ self.sha = obj.sha_validation
+
+ # make the slug always right in URLs resolution:
+ if "slug" in self.kwargs:
+ self.kwargs["slug"] = obj.slug
+
+ return obj
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["display_config"] = ConfigForValidationView(self.request.user, self.object, self.versioned_object)
+ return context
+
+ def get_base_url(self):
+ route_parameters = {"pk": self.object.pk, "slug": self.object.slug}
+ url = reverse("content:validation-view", kwargs=route_parameters)
+ return url
diff --git a/zds/tutorialv2/views/display/content.py b/zds/tutorialv2/views/display/content.py
index b5a46f158c..f9660b4fe9 100644
--- a/zds/tutorialv2/views/display/content.py
+++ b/zds/tutorialv2/views/display/content.py
@@ -43,6 +43,7 @@
ConfigForVersionView,
ConfigForOnlineView,
ConfigForBetaView,
+ ConfigForValidationView,
)
from zds.tutorialv2.views.goals import EditGoalsForm
from zds.tutorialv2.views.labels import EditLabelsForm
@@ -90,10 +91,6 @@ def get_context_data(self, **kwargs):
context["form_publication"] = PublicationForm(versioned, initial={"source": self.object.source})
context["gallery"] = self.object.gallery
context["alerts"] = self.object.alerts_on_this_content.all()
- data_form_revoke = {"version": self.versioned_object.sha_public}
- context["form_revoke"] = RevokeValidationForm(self.versioned_object, initial=data_form_revoke)
- data_form_unpublication = data_form_revoke
- context["form_unpublication"] = UnpublicationForm(self.versioned_object, initial=data_form_unpublication)
data_form_pick = data_form_revoke
context["form_pick"] = PickOpinionForm(self.versioned_object, initial=data_form_pick)
data_form_unpick = data_form_revoke
@@ -326,3 +323,36 @@ def get_base_url(self):
route_parameters = {"pk": self.object.pk, "slug": self.object.slug}
url = reverse("content:beta-view", kwargs=route_parameters)
return url
+
+
+class ContentValidationView(LoginRequiredMixin, ContentBaseView):
+ """Show the validation page of a content."""
+
+ must_be_author = False
+
+ sha = None
+
+ def get_object(self, queryset=None):
+ """Ensure that the version is set to validation, raise Http404 if there is no such version."""
+ obj = super().get_object(queryset)
+
+ if not obj.sha_validation:
+ raise Http404("Aucune version en validation n'existe pour ce contenu.")
+ else:
+ self.sha = obj.sha_validation
+
+ # make the slug always right in URLs resolution:
+ if "slug" in self.kwargs:
+ self.kwargs["slug"] = obj.slug
+
+ return obj
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["display_config"] = ConfigForValidationView(self.request.user, self.object, self.versioned_object)
+ return context
+
+ def get_base_url(self):
+ route_parameters = {"pk": self.object.pk, "slug": self.object.slug}
+ url = reverse("content:validation-view", kwargs=route_parameters)
+ return url
diff --git a/zds/tutorialv2/views/validations_contents.py b/zds/tutorialv2/views/validations_contents.py
index 7c6546db1a..2fc0218275 100644
--- a/zds/tutorialv2/views/validations_contents.py
+++ b/zds/tutorialv2/views/validations_contents.py
@@ -348,7 +348,7 @@ def post(self, request, *args, **kwargs):
version=validation.version,
action="reserve",
)
- redirect_url = get_content_version_url(validation.content, validation.version)
+ redirect_url = reverse("content:validation-view", args=[validation.content.pk, validation.content.slug])
return redirect(redirect_url)
|