kopia lustrzana https://github.com/wagtail/wagtail
Remove legacy moderation system
rodzic
cdac7dc7f5
commit
ab86351a8d
|
@ -712,17 +712,6 @@ You can use the [`purge_revisions`](purge_revisions) command to delete old revis
|
|||
|
||||
The primary key of the object this revision belongs to.
|
||||
|
||||
.. attribute:: submitted_for_moderation
|
||||
|
||||
(boolean)
|
||||
|
||||
``True`` if this revision is in moderation.
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
This field is only used for the legacy moderation system. It has been deprecated and will be removed in a future release.
|
||||
|
||||
|
||||
.. attribute:: created_at
|
||||
|
||||
(date/time)
|
||||
|
@ -768,20 +757,6 @@ You can use the [`purge_revisions`](purge_revisions) command to delete old revis
|
|||
.. code-block:: python
|
||||
|
||||
Revision.page_revisions.all()
|
||||
|
||||
.. attribute:: submitted_revisions
|
||||
|
||||
This manager extends the default manager and is used to retrieve all of the ``Revision`` objects that are awaiting moderator approval.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Revision.submitted_revisions.all()
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
This manager is only used for the legacy moderation system. It has been deprecated and will be removed in a future release.
|
||||
```
|
||||
|
||||
### Methods and properties
|
||||
|
@ -794,22 +769,6 @@ You can use the [`purge_revisions`](purge_revisions) command to delete old revis
|
|||
|
||||
This method retrieves this revision as an instance of its object's specific class. If the revision belongs to a page, it will be an instance of the :class:`~wagtail.models.Page`'s specific subclass.
|
||||
|
||||
.. automethod:: approve_moderation
|
||||
|
||||
Calling this on a revision that's in moderation will mark it as approved and publish it.
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
This method is only used for the legacy moderation system. It has been deprecated and will be removed in a future release.
|
||||
|
||||
.. automethod:: reject_moderation
|
||||
|
||||
Calling this on a revision that's in moderation will mark it as rejected.
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
This method is only used for the legacy moderation system. It has been deprecated and will be removed in a future release.
|
||||
|
||||
.. automethod:: is_latest_revision
|
||||
|
||||
Returns ``True`` if this revision is the object's latest revision.
|
||||
|
|
|
@ -185,8 +185,6 @@ class CopyPageAction:
|
|||
for revision in page.revisions.all():
|
||||
use_as_latest_revision = revision.pk == page.latest_revision_id
|
||||
revision.pk = None
|
||||
# RemovedInWagtail60Warning
|
||||
revision.submitted_for_moderation = False
|
||||
revision.approved_go_live_at = None
|
||||
revision.object_id = page_copy.id
|
||||
|
||||
|
|
|
@ -168,10 +168,6 @@ class PublishRevisionAction:
|
|||
|
||||
object.save()
|
||||
|
||||
# RemovedInWagtail60Warning
|
||||
revision.submitted_for_moderation = False
|
||||
object.revisions.update(submitted_for_moderation=False)
|
||||
|
||||
self._after_publish()
|
||||
|
||||
if object.live:
|
||||
|
|
|
@ -24,7 +24,6 @@ class RevertToPageRevisionAction:
|
|||
revision,
|
||||
user=None,
|
||||
log_action="wagtail.revert",
|
||||
submitted_for_moderation=False, # RemovedInWagtail60Warning
|
||||
approved_go_live_at=None,
|
||||
changed=True,
|
||||
clean=True,
|
||||
|
@ -33,7 +32,6 @@ class RevertToPageRevisionAction:
|
|||
self.revision = revision
|
||||
self.user = user
|
||||
self.log_action = log_action
|
||||
self.submitted_for_moderation = submitted_for_moderation
|
||||
self.approved_go_live_at = approved_go_live_at
|
||||
self.changed = changed
|
||||
self.clean = clean
|
||||
|
@ -61,7 +59,6 @@ class RevertToPageRevisionAction:
|
|||
previous_revision=self.revision,
|
||||
user=self.user,
|
||||
log_action=self.log_action,
|
||||
submitted_for_moderation=self.submitted_for_moderation,
|
||||
approved_go_live_at=self.approved_go_live_at,
|
||||
changed=self.changed,
|
||||
clean=self.clean,
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
"""Handles rendering of the list of actions in the footer of the page create/edit views."""
|
||||
import warnings
|
||||
|
||||
from django.conf import settings
|
||||
from django.forms import Media
|
||||
from django.template.loader import render_to_string
|
||||
|
@ -10,7 +8,6 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from wagtail import hooks
|
||||
from wagtail.admin.ui.components import Component
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class ActionMenuItem(Component):
|
||||
|
@ -100,15 +97,6 @@ class SubmitForModerationMenuItem(ActionMenuItem):
|
|||
icon_name = "resubmit"
|
||||
|
||||
def is_shown(self, context):
|
||||
legacy_setting = getattr(settings, "WAGTAIL_MODERATION_ENABLED", None)
|
||||
if legacy_setting is not None:
|
||||
warnings.warn(
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
if not legacy_setting:
|
||||
return False
|
||||
|
||||
if not getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
|
||||
return False
|
||||
|
||||
|
@ -175,15 +163,6 @@ class RestartWorkflowMenuItem(ActionMenuItem):
|
|||
icon_name = "login"
|
||||
|
||||
def is_shown(self, context):
|
||||
legacy_setting = getattr(settings, "WAGTAIL_MODERATION_ENABLED", None)
|
||||
if legacy_setting is not None:
|
||||
warnings.warn(
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
if not legacy_setting:
|
||||
return False
|
||||
|
||||
if not getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
|
||||
return False
|
||||
elif context["view"] == "edit":
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
{% if page_revisions_for_moderation %}
|
||||
{% panel id="awaiting-moderation" heading=_("Pages awaiting moderation") %}
|
||||
<table class="listing">
|
||||
<col />
|
||||
<col width="30%"/>
|
||||
<col width="15%"/>
|
||||
<col width="15%"/>
|
||||
<thead class="w-sr-only">
|
||||
<tr>
|
||||
<th class="title">{% trans "Title" %}</th>
|
||||
<th>{% trans "Parent" %}</th>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th>{% trans "Edited" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for revision in page_revisions_for_moderation %}
|
||||
{% page_permissions revision.content_object as page_perms %}
|
||||
<tr>
|
||||
<td class="title" valign="top">
|
||||
<div class="title-wrapper">
|
||||
{% if page_perms.can_edit %}
|
||||
<a href="{% url 'wagtailadmin_pages:edit' revision.object_id %}" title="{% trans 'Edit this page' %}">{{ revision.content_object.specific_deferred.get_admin_display_title }}</a>
|
||||
{% elif revision.content_object.is_previewable %}
|
||||
<a href="{% url 'wagtailadmin_pages:preview_for_moderation' revision.id %}" title="{% trans 'Preview this page' %}">{{ revision.content_object.specific_deferred.get_admin_display_title }}</a>
|
||||
{% else %}
|
||||
{{ revision.content_object.specific_deferred.get_admin_display_title }}
|
||||
{% endif %}
|
||||
|
||||
{% i18n_enabled as show_locale_labels %}
|
||||
{% if show_locale_labels and revision.content_object.locale_id %}
|
||||
{% locale_label_from_id revision.content_object.locale_id as locale_label %}
|
||||
{% status locale_label classname="w-status--label" %}
|
||||
{% endif %}
|
||||
{% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=revision.content_object %}
|
||||
{% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=revision.content_object %}
|
||||
</div>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
{% dropdown toggle_icon="dots-horizontal" toggle_aria_label=_("Actions") %}
|
||||
<form action="{% url 'wagtailadmin_pages:approve_moderation' revision.id %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<button type="submit">{% trans 'Approve' %}</button>
|
||||
</form>
|
||||
<form action="{% url 'wagtailadmin_pages:reject_moderation' revision.id %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<button type="submit">{% trans 'Reject' %}</button>
|
||||
</form>
|
||||
{% if page_perms.can_edit %}
|
||||
<a href="{% url 'wagtailadmin_pages:edit' revision.object_id %}">{% trans 'Edit' %}</a>
|
||||
{% endif %}
|
||||
{% if revision.content_object.is_previewable %}
|
||||
<a href="{% url 'wagtailadmin_pages:preview_for_moderation' revision.id %}" target="_blank" rel="noreferrer">{% trans 'Preview' %}</a>
|
||||
{% endif %}
|
||||
{% enddropdown %}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<a href="{% url 'wagtailadmin_explore' revision.content_object.get_parent.id %}">{{ revision.content_object.get_parent.specific_deferred.get_admin_display_title }}</a>
|
||||
</td>
|
||||
<td class="type" valign="top">
|
||||
{{ revision.content_object.page_type_display_name }}
|
||||
</td>
|
||||
<td valign="top">
|
||||
{% blocktrans with name=revision.user|user_display_name asvar description %}by {{ name }}{% endblocktrans %}
|
||||
{% human_readable_date revision.created_at description %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endpanel %}
|
||||
{% endif %}
|
|
@ -1,12 +0,0 @@
|
|||
{% extends "wagtailadmin/userbar/item_base.html" %}
|
||||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block item_content %}
|
||||
<form action="{% url 'wagtailadmin_pages:approve_moderation' self.revision.id %}" target="_parent" method="post">
|
||||
{% csrf_token %}
|
||||
<button type="submit" value="{% trans 'Approve' %}" class="button" role="menuitem">
|
||||
{% icon name="check" classname="w-action-icon" %}
|
||||
{% trans 'Approve' %}
|
||||
</button>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,12 +0,0 @@
|
|||
{% extends "wagtailadmin/userbar/item_base.html" %}
|
||||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block item_content %}
|
||||
<form action="{% url 'wagtailadmin_pages:reject_moderation' self.revision.id %}" target="_parent" method="post">
|
||||
{% csrf_token %}
|
||||
<button type="submit" value="{% trans 'Reject' %}" class="button" role="menuitem">
|
||||
{% icon name="cross" classname="w-action-icon" %}
|
||||
{% trans 'Reject' %}
|
||||
</button>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -7,10 +7,8 @@ from wagtail.admin.userbar import (
|
|||
AccessibilityItem,
|
||||
AddPageItem,
|
||||
AdminItem,
|
||||
ApproveModerationEditPageItem,
|
||||
EditPageItem,
|
||||
ExplorePageItem,
|
||||
RejectModerationEditPageItem,
|
||||
)
|
||||
from wagtail.models import PAGE_TEMPLATE_VAR, Page, Revision
|
||||
from wagtail.users.models import UserProfile
|
||||
|
@ -70,8 +68,6 @@ def wagtailuserbar(context, position="bottom-right"):
|
|||
AdminItem(),
|
||||
ExplorePageItem(revision.content_object),
|
||||
EditPageItem(revision.content_object),
|
||||
ApproveModerationEditPageItem(revision),
|
||||
RejectModerationEditPageItem(revision),
|
||||
AccessibilityItem(),
|
||||
]
|
||||
else:
|
||||
|
|
|
@ -27,7 +27,6 @@ from wagtail.test.testapp.models import (
|
|||
)
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.timestamps import submittable_timestamp
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class TestPageCreation(WagtailTestUtils, TestCase):
|
||||
|
@ -1228,27 +1227,6 @@ class TestPageCreation(WagtailTestUtils, TestCase):
|
|||
"Submit for moderation</button>",
|
||||
)
|
||||
|
||||
@override_settings(WAGTAIL_MODERATION_ENABLED=False)
|
||||
def test_legacy_hide_moderation_button(self):
|
||||
"""
|
||||
Tests that if WAGTAIL_MODERATION_ENABLED is set to False, the "Submit for Moderation" button is not shown.
|
||||
"""
|
||||
# RemovedInWagtail60Warning: Remove this test in favour of test_hide_moderation_button
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "simplepage", self.root_page.id),
|
||||
)
|
||||
)
|
||||
self.assertNotContains(
|
||||
response,
|
||||
'<button type="submit" name="action-submit" value="Submit for moderation" class="button">Submit for moderation</button>',
|
||||
)
|
||||
|
||||
@override_settings(WAGTAIL_WORKFLOW_ENABLED=False)
|
||||
def test_hide_moderation_button(self):
|
||||
"""
|
||||
|
|
|
@ -47,7 +47,6 @@ from wagtail.test.utils import WagtailTestUtils
|
|||
from wagtail.test.utils.form_data import inline_formset, nested_form_data
|
||||
from wagtail.test.utils.timestamps import submittable_timestamp
|
||||
from wagtail.users.models import UserProfile
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
from wagtail.utils.timestamps import render_timestamp
|
||||
|
||||
|
||||
|
@ -2528,66 +2527,6 @@ class TestIssue3982(WagtailTestUtils, TestCase):
|
|||
)
|
||||
)
|
||||
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove the following tests when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
|
||||
def _approve_page(self, parent):
|
||||
self.client.post(
|
||||
reverse("wagtailadmin_pages:add", args=("tests", "simplepage", parent.pk)),
|
||||
{
|
||||
"title": "Hello, world!",
|
||||
"content": "Some content",
|
||||
"slug": "hello-world",
|
||||
},
|
||||
follow=True,
|
||||
)
|
||||
page = SimplePage.objects.get()
|
||||
self.assertFalse(page.live)
|
||||
revision = Revision.page_revisions.get(object_id=page.id)
|
||||
revision.submitted_for_moderation = True
|
||||
revision.save()
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:approve_moderation", args=(revision.pk,)),
|
||||
follow=True,
|
||||
)
|
||||
page = SimplePage.objects.get()
|
||||
self.assertTrue(page.live)
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
return response, page
|
||||
|
||||
def test_approve_accessible(self):
|
||||
"""
|
||||
Edit a page under the site root, check the flash message has a valid
|
||||
"View live" button.
|
||||
"""
|
||||
response, page = self._approve_page(Page.objects.get(pk=2))
|
||||
self.assertIsNotNone(page.url)
|
||||
self.assertTrue(
|
||||
any(
|
||||
"View live" in message.message and page.url in message.message
|
||||
for message in response.context["messages"]
|
||||
)
|
||||
)
|
||||
|
||||
def test_approve_inaccessible(self):
|
||||
"""
|
||||
Edit a page outside of the site root, check the flash message does
|
||||
not have a "View live" button.
|
||||
"""
|
||||
response, page = self._approve_page(Page.objects.get(pk=1))
|
||||
self.assertIsNone(page.url)
|
||||
self.assertFalse(
|
||||
any(
|
||||
"View live" in message.message
|
||||
for message in response.context["messages"]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestParentalM2M(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
|
|
@ -1,516 +0,0 @@
|
|||
import logging
|
||||
from itertools import chain
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.contrib.messages import constants as message_constants
|
||||
from django.core import mail
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page, Revision
|
||||
from wagtail.signals import page_published
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.users.models import UserProfile
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class TestApproveRejectModeration(WagtailTestUtils, TestCase):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test class when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
|
||||
def setUp(self):
|
||||
self.submitter = self.create_superuser(
|
||||
username="submitter",
|
||||
email="submitter@email.com",
|
||||
password="password",
|
||||
)
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
# Create a page and submit it for moderation
|
||||
root_page = Page.objects.get(id=2)
|
||||
self.page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=False,
|
||||
has_unpublished_changes=True,
|
||||
)
|
||||
root_page.add_child(instance=self.page)
|
||||
|
||||
self.page.save_revision(user=self.submitter, submitted_for_moderation=True)
|
||||
self.revision = self.page.get_latest_revision()
|
||||
|
||||
def test_approve_moderation_view(self):
|
||||
"""
|
||||
This posts to the approve moderation view and checks that the page was approved
|
||||
"""
|
||||
# Connect a mock signal handler to page_published signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_published.connect(mock_handler)
|
||||
|
||||
try:
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:approve_moderation",
|
||||
args=(self.revision.id,),
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the dashboard
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
|
||||
page = Page.objects.get(id=self.page.id)
|
||||
# Page must be live
|
||||
self.assertTrue(
|
||||
page.live, msg="Approving moderation failed to set live=True"
|
||||
)
|
||||
# Page should now have no unpublished changes
|
||||
self.assertFalse(
|
||||
page.has_unpublished_changes,
|
||||
msg="Approving moderation failed to set has_unpublished_changes=False",
|
||||
)
|
||||
|
||||
# Check that the page_published signal was fired
|
||||
self.assertEqual(mock_handler.call_count, 1)
|
||||
mock_call = mock_handler.mock_calls[0][2]
|
||||
|
||||
self.assertEqual(mock_call["sender"], self.page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], self.page)
|
||||
self.assertIsInstance(mock_call["instance"], self.page.specific_class)
|
||||
finally:
|
||||
page_published.disconnect(mock_handler)
|
||||
|
||||
def test_approve_moderation_when_later_revision_exists(self):
|
||||
self.page.title = "Goodbye world!"
|
||||
self.page.save_revision(user=self.submitter, submitted_for_moderation=False)
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:approve_moderation", args=(self.revision.id,)
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the dashboard
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
|
||||
page = Page.objects.get(id=self.page.id)
|
||||
# Page must be live
|
||||
self.assertTrue(page.live, msg="Approving moderation failed to set live=True")
|
||||
# Page content should be the submitted version, not the published one
|
||||
self.assertEqual(page.title, "Hello world!")
|
||||
# Page should still have unpublished changes
|
||||
self.assertTrue(
|
||||
page.has_unpublished_changes,
|
||||
msg="has_unpublished_changes incorrectly cleared on approve_moderation when a later revision exists",
|
||||
)
|
||||
|
||||
def test_approve_moderation_view_bad_revision_id(self):
|
||||
"""
|
||||
This tests that the approve moderation view handles invalid revision ids correctly
|
||||
"""
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:approve_moderation", args=(12345,))
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_approve_moderation_view_bad_permissions(self):
|
||||
"""
|
||||
This tests that the approve moderation view doesn't allow users without moderation permissions
|
||||
"""
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:approve_moderation", args=(self.revision.id,))
|
||||
)
|
||||
|
||||
# Check that the user received a 302 redirected response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_reject_moderation_view(self):
|
||||
"""
|
||||
This posts to the reject moderation view and checks that the page was rejected
|
||||
"""
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.reject_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:reject_moderation", args=(self.revision.id,)
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the dashboard
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
|
||||
# Page must not be live
|
||||
self.assertFalse(Page.objects.get(id=self.page.id).live)
|
||||
|
||||
# Revision must no longer be submitted for moderation
|
||||
self.assertFalse(
|
||||
Revision.page_revisions.get(id=self.revision.id).submitted_for_moderation
|
||||
)
|
||||
|
||||
def test_reject_moderation_view_bad_revision_id(self):
|
||||
"""
|
||||
This tests that the reject moderation view handles invalid revision ids correctly
|
||||
"""
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:reject_moderation", args=(12345,))
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_reject_moderation_view_bad_permissions(self):
|
||||
"""
|
||||
This tests that the reject moderation view doesn't allow users without moderation permissions
|
||||
"""
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:reject_moderation", args=(self.revision.id,))
|
||||
)
|
||||
|
||||
# Check that the user received a 302 redirected response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_preview_for_moderation(self):
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"The simple page 'Hello world! (simple page)' is undergoing moderation "
|
||||
"in the legacy moderation system. Complete the moderation of this page "
|
||||
"before upgrading Wagtail. Support for the legacy moderation system will "
|
||||
"be completely removed in a future release. For more details, refer to "
|
||||
"https://docs.wagtail.org/en/stable/releases/2.10.html#move-to-new-configurable-moderation-system-workflow",
|
||||
):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:preview_for_moderation",
|
||||
args=(self.revision.id,),
|
||||
)
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "tests/simple_page.html")
|
||||
self.assertContains(response, "Hello world!")
|
||||
|
||||
|
||||
class TestNotificationPreferences(WagtailTestUtils, TestCase):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test class when the deprecation period for the legacy
|
||||
# moderation system ends. This test has been replaced by
|
||||
# wagtail.admin.tests.test_workflows.TestPageNotificationPreferences.
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
# Create two moderator users for testing 'submitted' email
|
||||
self.moderator = self.create_superuser(
|
||||
"moderator", "moderator@email.com", "password"
|
||||
)
|
||||
self.moderator2 = self.create_superuser(
|
||||
"moderator2", "moderator2@email.com", "password"
|
||||
)
|
||||
|
||||
# Create a submitter for testing 'rejected' and 'approved' emails
|
||||
self.submitter = self.create_user(
|
||||
"submitter", "submitter@email.com", "password"
|
||||
)
|
||||
|
||||
# User profiles for moderator2 and the submitter
|
||||
self.moderator2_profile = UserProfile.get_for_user(self.moderator2)
|
||||
self.submitter_profile = UserProfile.get_for_user(self.submitter)
|
||||
|
||||
# Create a page and submit it for moderation
|
||||
self.child_page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=False,
|
||||
)
|
||||
self.root_page.add_child(instance=self.child_page)
|
||||
|
||||
# POST data to edit the page
|
||||
self.post_data = {
|
||||
"title": "I've been edited!",
|
||||
"content": "Some content",
|
||||
"slug": "hello-world",
|
||||
"action-submit": "Submit",
|
||||
}
|
||||
|
||||
def submit(self):
|
||||
return self.client.post(
|
||||
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
||||
self.post_data,
|
||||
)
|
||||
|
||||
def silent_submit(self):
|
||||
"""
|
||||
Sets up the child_page as needing moderation, without making a request
|
||||
"""
|
||||
self.child_page.save_revision(
|
||||
user=self.submitter, submitted_for_moderation=True
|
||||
)
|
||||
self.revision = self.child_page.get_latest_revision()
|
||||
|
||||
def approve(self):
|
||||
return self.client.post(
|
||||
reverse("wagtailadmin_pages:approve_moderation", args=(self.revision.id,))
|
||||
)
|
||||
|
||||
def reject(self):
|
||||
return self.client.post(
|
||||
reverse("wagtailadmin_pages:reject_moderation", args=(self.revision.id,))
|
||||
)
|
||||
|
||||
def test_vanilla_profile(self):
|
||||
# Check that the vanilla profile has rejected notifications on
|
||||
self.assertIs(self.submitter_profile.rejected_notifications, True)
|
||||
|
||||
# Check that the vanilla profile has approved notifications on
|
||||
self.assertIs(self.submitter_profile.approved_notifications, True)
|
||||
|
||||
def test_approved_notifications(self):
|
||||
# Set up the page version
|
||||
self.silent_submit()
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Approve
|
||||
self.approve()
|
||||
|
||||
# Submitter must receive an approved email
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].to, ["submitter@email.com"])
|
||||
self.assertEqual(
|
||||
mail.outbox[0].subject,
|
||||
'The page "Hello world! (simple page)" has been approved',
|
||||
)
|
||||
|
||||
def test_approved_notifications_preferences_respected(self):
|
||||
# Submitter doesn't want 'approved' emails
|
||||
self.submitter_profile.approved_notifications = False
|
||||
self.submitter_profile.save()
|
||||
|
||||
# Set up the page version
|
||||
self.silent_submit()
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Approve
|
||||
self.approve()
|
||||
|
||||
# No email to send
|
||||
self.assertEqual(len(mail.outbox), 0)
|
||||
|
||||
def test_rejected_notifications(self):
|
||||
# Set up the page version
|
||||
self.silent_submit()
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.reject_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Reject
|
||||
self.reject()
|
||||
|
||||
# Submitter must receive a rejected email
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].to, ["submitter@email.com"])
|
||||
self.assertEqual(
|
||||
mail.outbox[0].subject,
|
||||
'The page "Hello world! (simple page)" has been rejected',
|
||||
)
|
||||
|
||||
def test_rejected_notification_preferences_respected(self):
|
||||
# Submitter doesn't want 'rejected' emails
|
||||
self.submitter_profile.rejected_notifications = False
|
||||
self.submitter_profile.save()
|
||||
|
||||
# Set up the page version
|
||||
self.silent_submit()
|
||||
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.reject_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Reject
|
||||
self.reject()
|
||||
|
||||
# No email to send
|
||||
self.assertEqual(len(mail.outbox), 0)
|
||||
|
||||
@override_settings(WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS=False)
|
||||
def test_disable_superuser_notification(self):
|
||||
# Add one of the superusers to the moderator group
|
||||
self.moderator.groups.add(Group.objects.get(name="Moderators"))
|
||||
|
||||
response = self.submit()
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the non-moderator superuser is not being notified
|
||||
expected_emails = 1
|
||||
self.assertEqual(len(mail.outbox), expected_emails)
|
||||
# Use chain as the 'to' field is a list of recipients
|
||||
email_to = list(chain.from_iterable([m.to for m in mail.outbox]))
|
||||
self.assertIn(self.moderator.email, email_to)
|
||||
self.assertNotIn(self.moderator2.email, email_to)
|
||||
|
||||
@mock.patch.object(
|
||||
EmailMultiAlternatives, "send", side_effect=IOError("Server down")
|
||||
)
|
||||
def test_email_send_error(self, mock_fn):
|
||||
logging.disable(logging.CRITICAL)
|
||||
# Approve
|
||||
self.silent_submit()
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
response = self.approve()
|
||||
logging.disable(logging.NOTSET)
|
||||
|
||||
# An email that fails to send should return a message rather than crash the page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
response = self.client.get(reverse("wagtailadmin_home"))
|
||||
|
||||
# There should be one "approved" message and one "failed to send notifications"
|
||||
messages = list(response.context["messages"])
|
||||
self.assertEqual(len(messages), 2)
|
||||
self.assertEqual(messages[0].level, message_constants.SUCCESS)
|
||||
self.assertEqual(messages[1].level, message_constants.ERROR)
|
||||
|
||||
def test_email_headers(self):
|
||||
# Submit
|
||||
self.submit()
|
||||
|
||||
msg_headers = set(mail.outbox[0].message().items())
|
||||
headers = {("Auto-Submitted", "auto-generated")}
|
||||
self.assertTrue(
|
||||
headers.issubset(msg_headers),
|
||||
msg="Message is missing the Auto-Submitted header.",
|
||||
)
|
||||
|
||||
|
||||
class TestApproveRejectModerationWithoutUser(WagtailTestUtils, TestCase):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test class when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
# This test works similarly to TestApproveRejectModeration, but it
|
||||
# doesn't specify the user when saving the revision.
|
||||
|
||||
def setUp(self):
|
||||
self.submitter = self.create_superuser(
|
||||
username="submitter",
|
||||
email="submitter@email.com",
|
||||
password="password",
|
||||
)
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
# Create a page and submit it for moderation
|
||||
root_page = Page.objects.get(id=2)
|
||||
self.page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=False,
|
||||
has_unpublished_changes=True,
|
||||
)
|
||||
root_page.add_child(instance=self.page)
|
||||
|
||||
# save_revision without user
|
||||
self.page.save_revision(submitted_for_moderation=True)
|
||||
self.revision = self.page.get_latest_revision()
|
||||
|
||||
def test_approve_moderation_view_without_user(self):
|
||||
"""
|
||||
This posts to the approve moderation view and checks that the page was approved
|
||||
"""
|
||||
# Connect a mock signal handler to page_published signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_published.connect(mock_handler)
|
||||
|
||||
try:
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
):
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:approve_moderation",
|
||||
args=(self.revision.id,),
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the dashboard
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
|
||||
page = Page.objects.get(id=self.page.id)
|
||||
# Page must be live
|
||||
self.assertTrue(
|
||||
page.live, msg="Approving moderation failed to set live=True"
|
||||
)
|
||||
# Page should now have no unpublished changes
|
||||
self.assertFalse(
|
||||
page.has_unpublished_changes,
|
||||
msg="Approving moderation failed to set has_unpublished_changes=False",
|
||||
)
|
||||
|
||||
# Check that the page_published signal was fired
|
||||
self.assertEqual(mock_handler.call_count, 1)
|
||||
mock_call = mock_handler.mock_calls[0][2]
|
||||
|
||||
self.assertEqual(mock_call["sender"], self.page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], self.page)
|
||||
self.assertIsInstance(mock_call["instance"], self.page.specific_class)
|
||||
finally:
|
||||
page_published.disconnect(mock_handler)
|
|
@ -637,20 +637,3 @@ class TestDisablePreviewButton(WagtailTestUtils, TestCase):
|
|||
)
|
||||
self.assertNotContains(response, "Preview")
|
||||
self.assertNotContains(response, preview_url)
|
||||
|
||||
def disable_preview_in_moderation_list(self):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
stream_page = StreamPage(title="stream page", body=[("text", "hello")])
|
||||
self.root_page.add_child(instance=stream_page)
|
||||
latest_revision = stream_page.save_revision(
|
||||
user=self.user, submitted_for_moderation=True
|
||||
)
|
||||
|
||||
response = self.client.get(reverse("wagtailadmin_home"))
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_for_moderation", args=(latest_revision.id,)
|
||||
)
|
||||
self.assertNotContains(response, '<li class="preview">')
|
||||
self.assertNotContains(response, 'data-action="%s"' % preview_url)
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import GroupPagePermission, Page
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class TestModerationList(WagtailTestUtils, TestCase):
|
||||
"""Test moderation list rendered by `wagtailadmin_home` view"""
|
||||
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test class when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
# For workflows, this has been covered in
|
||||
# wagtail.admin.tests.test_workflows.TestDashboardWithPages
|
||||
|
||||
def setUp(self):
|
||||
# Create a submitter
|
||||
submitter = self.create_user(
|
||||
username="submitter",
|
||||
email="submitter@email.com",
|
||||
password="password",
|
||||
)
|
||||
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create a page
|
||||
self.page = SimplePage(
|
||||
title="Wagtail, the powerful CMS for modern websites",
|
||||
slug="wagtail",
|
||||
content="Fast, elegant, open source",
|
||||
)
|
||||
|
||||
self.root_page.add_child(instance=self.page)
|
||||
|
||||
# Submit it for moderation
|
||||
self.page.save_revision(user=submitter, submitted_for_moderation=True)
|
||||
|
||||
# Create a revision
|
||||
self.revision = self.page.get_latest_revision()
|
||||
|
||||
self.edit_page_url = reverse(
|
||||
"wagtailadmin_pages:edit", args=(self.revision.object_id,)
|
||||
)
|
||||
self.preview_page_url = reverse(
|
||||
"wagtailadmin_pages:preview_for_moderation", args=(self.revision.id,)
|
||||
)
|
||||
|
||||
def login_as_moderator_without_edit(self):
|
||||
# Create moderators group without edit permissions
|
||||
moderators_group = Group.objects.create(name="Moderators without edit")
|
||||
|
||||
admin_permission = Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
|
||||
moderators_group.permissions.add(admin_permission)
|
||||
|
||||
# Create group permissions
|
||||
GroupPagePermission.objects.create(
|
||||
group=moderators_group,
|
||||
page=self.root_page,
|
||||
permission_type="publish",
|
||||
)
|
||||
|
||||
# Create a moderator without edit permissions
|
||||
moderator = self.create_user(
|
||||
username="moderator", email="moderator@email.com", password="password"
|
||||
)
|
||||
|
||||
moderator.groups.add(moderators_group)
|
||||
|
||||
self.login(moderator)
|
||||
|
||||
def get(self):
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"You have pages undergoing moderation in the legacy moderation system. "
|
||||
"Complete the moderation of these pages before upgrading Wagtail. "
|
||||
"Support for the legacy moderation system will be completely removed "
|
||||
"in a future release. For more details, refer to "
|
||||
"https://docs.wagtail.org/en/stable/releases/2.10.html#move-to-new-configurable-moderation-system-workflow",
|
||||
):
|
||||
return self.client.get(reverse("wagtailadmin_home"))
|
||||
|
||||
def test_edit_page(self):
|
||||
# Login as moderator
|
||||
self.login()
|
||||
|
||||
response = self.get()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/home.html")
|
||||
|
||||
# Check response
|
||||
self.assertContains(response, self.edit_page_url, count=2)
|
||||
|
||||
# page should contain Approve and Reject forms including a valid CSRF token
|
||||
self.assertRegex(
|
||||
response.content.decode("utf-8"),
|
||||
r'<input type="hidden" name="csrfmiddlewaretoken" value="\w+">',
|
||||
)
|
||||
|
||||
def test_preview_for_moderation(self):
|
||||
# Login as moderator without edit permissions
|
||||
self.login_as_moderator_without_edit()
|
||||
|
||||
response = self.get()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/home.html")
|
||||
|
||||
# Check response
|
||||
self.assertContains(response, self.preview_page_url, count=2)
|
||||
self.assertNotContains(response, self.edit_page_url)
|
|
@ -11,7 +11,6 @@ from wagtail.coreutils import get_dummy_request
|
|||
from wagtail.models import PAGE_TEMPLATE_VAR, Page, Site
|
||||
from wagtail.test.testapp.models import BusinessChild, BusinessIndex, SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class TestUserbarTag(WagtailTestUtils, TestCase):
|
||||
|
@ -52,27 +51,6 @@ class TestUserbarTag(WagtailTestUtils, TestCase):
|
|||
|
||||
self.assertIn("<!-- Wagtail user bar embed code -->", content)
|
||||
|
||||
def test_userbar_tag_revision(self):
|
||||
self.homepage.save_revision(user=self.user, submitted_for_moderation=True)
|
||||
revision = self.homepage.get_latest_revision()
|
||||
template = Template("{% load wagtailuserbar %}{% wagtailuserbar %}")
|
||||
context = Context(
|
||||
{
|
||||
PAGE_TEMPLATE_VAR: self.homepage,
|
||||
"request": self.dummy_request(self.user, revision_id=revision.id),
|
||||
}
|
||||
)
|
||||
with self.assertNumQueries(7), self.assertWarnsRegex(
|
||||
RemovedInWagtail60Warning,
|
||||
"ModerationEditPageItem is deprecated\. "
|
||||
"If you explicitly use this in your code, "
|
||||
"remove it from your construct_wagtail_userbar hook\.",
|
||||
):
|
||||
content = template.render(context)
|
||||
|
||||
self.assertIn("<!-- Wagtail user bar embed code -->", content)
|
||||
self.assertIn("Approve", content)
|
||||
|
||||
def test_userbar_does_not_break_without_request(self):
|
||||
template = Template("{% load wagtailuserbar %}{% wagtailuserbar %}boom")
|
||||
content = template.render(Context({}))
|
||||
|
@ -439,70 +417,3 @@ class TestUserbarAddLink(WagtailTestUtils, TestCase):
|
|||
soup = self.get_soup(response.content)
|
||||
link = soup.find("a", attrs={"href": expected_url})
|
||||
self.assertIsNone(link)
|
||||
|
||||
|
||||
class TestUserbarModeration(WagtailTestUtils, TestCase):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test class when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
# The userbar is yet to support workflows:
|
||||
# https://github.com/wagtail/wagtail/issues/9106
|
||||
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
self.request = get_dummy_request(site=Site.objects.first())
|
||||
self.request.user = self.user
|
||||
self.homepage = Page.objects.get(id=2)
|
||||
# Use a specific page model to use our template that has {% wagtailuserbar %}
|
||||
self.page = SimplePage(title="Martabak", content="Lezat", live=True)
|
||||
self.homepage.add_child(instance=self.page)
|
||||
self.page.save_revision(submitted_for_moderation=True)
|
||||
self.revision = self.page.get_latest_revision()
|
||||
self.request.revision_id = self.revision.id
|
||||
|
||||
def test_userbar_moderation(self):
|
||||
response = self.page.serve(self.request)
|
||||
with self.assertWarnsRegex(
|
||||
RemovedInWagtail60Warning,
|
||||
"ModerationEditPageItem is deprecated\. "
|
||||
"If you explicitly use this in your code, "
|
||||
"remove it from your construct_wagtail_userbar hook\.",
|
||||
):
|
||||
response.render()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, '<template id="wagtail-userbar-template">')
|
||||
|
||||
expected_approve_html = """
|
||||
<form action="/admin/pages/moderation/{}/approve/" target="_parent" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken">
|
||||
<div class="w-action">
|
||||
<input type="submit" value="Approve" class="button" />
|
||||
</div>
|
||||
</form>
|
||||
""".format(
|
||||
self.revision.id
|
||||
)
|
||||
self.assertTagInHTML(expected_approve_html, response.content.decode())
|
||||
|
||||
expected_reject_html = """
|
||||
<form action="/admin/pages/moderation/{}/reject/" target="_parent" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken">
|
||||
<div class="w-action">
|
||||
<input type="submit" value="Reject" class="button" />
|
||||
</div>
|
||||
</form>
|
||||
""".format(
|
||||
self.revision.id
|
||||
)
|
||||
self.assertTagInHTML(expected_reject_html, response.content.decode())
|
||||
|
||||
def test_userbar_moderation_anonymous_user_cannot_see(self):
|
||||
self.request.user = AnonymousUser()
|
||||
|
||||
response = self.page.serve(self.request)
|
||||
response.render()
|
||||
|
||||
# Check that the user received a forbidden message
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, '<template id="wagtail-userbar-template">')
|
||||
|
|
|
@ -18,7 +18,9 @@ from wagtail.admin.menu import MenuItem
|
|||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import RestaurantTag
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
from wagtail.utils.deprecation import (
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
|
||||
|
||||
class TestHome(WagtailTestUtils, TestCase):
|
||||
|
|
|
@ -9,7 +9,6 @@ from wagtail.admin.views.pages import (
|
|||
edit,
|
||||
history,
|
||||
lock,
|
||||
moderation,
|
||||
move,
|
||||
ordering,
|
||||
preview,
|
||||
|
@ -87,21 +86,6 @@ urlpatterns = [
|
|||
workflow.PreviewRevisionForTask.as_view(),
|
||||
name="workflow_preview",
|
||||
),
|
||||
path(
|
||||
"moderation/<int:revision_id>/approve/",
|
||||
moderation.approve_moderation,
|
||||
name="approve_moderation",
|
||||
),
|
||||
path(
|
||||
"moderation/<int:revision_id>/reject/",
|
||||
moderation.reject_moderation,
|
||||
name="reject_moderation",
|
||||
),
|
||||
path(
|
||||
"moderation/<int:revision_id>/preview/",
|
||||
moderation.preview_for_moderation,
|
||||
name="preview_for_moderation",
|
||||
),
|
||||
path("<int:page_id>/privacy/", page_privacy.set_privacy, name="set_privacy"),
|
||||
path("<int:page_id>/lock/", lock.LockView.as_view(), name="lock"),
|
||||
path("<int:page_id>/unlock/", lock.UnlockView.as_view(), name="unlock"),
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import warnings
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class BaseItem:
|
||||
template = "wagtailadmin/userbar/item_base.html"
|
||||
|
@ -245,40 +241,3 @@ class EditPageItem(BaseItem):
|
|||
return ""
|
||||
|
||||
return super().render(request)
|
||||
|
||||
|
||||
class ModeratePageItem(BaseItem):
|
||||
def __init__(self, revision):
|
||||
self.revision = revision
|
||||
|
||||
def render(self, request):
|
||||
if not self.revision.id:
|
||||
return ""
|
||||
|
||||
if not self.revision.submitted_for_moderation:
|
||||
return ""
|
||||
|
||||
if not request.user.has_perm("wagtailadmin.access_admin"):
|
||||
return ""
|
||||
|
||||
if not self.revision.content_object.permissions_for_user(
|
||||
request.user
|
||||
).can_publish():
|
||||
return ""
|
||||
|
||||
warnings.warn(
|
||||
f"{self.__class__.__name__} is deprecated. "
|
||||
"If you explicitly use this in your code, remove it from your "
|
||||
"construct_wagtail_userbar hook.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
|
||||
return super().render(request)
|
||||
|
||||
|
||||
class ApproveModerationEditPageItem(ModeratePageItem):
|
||||
template = "wagtailadmin/userbar/item_page_approve.html"
|
||||
|
||||
|
||||
class RejectModerationEditPageItem(ModeratePageItem):
|
||||
template = "wagtailadmin/userbar/item_page_reject.html"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import itertools
|
||||
import re
|
||||
import warnings
|
||||
from typing import Any, Mapping, Union
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -28,7 +27,6 @@ from wagtail.models import (
|
|||
get_default_page_content_type,
|
||||
)
|
||||
from wagtail.permission_policies.pages import PagePermissionPolicy
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
@ -94,35 +92,6 @@ class WhatsNewInWagtailVersionPanel(Component):
|
|||
return super().render_html(parent_context)
|
||||
|
||||
|
||||
class PagesForModerationPanel(Component):
|
||||
name = "pages_for_moderation"
|
||||
template_name = "wagtailadmin/home/pages_for_moderation.html"
|
||||
order = 200
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
request = parent_context["request"]
|
||||
context = super().get_context_data(parent_context)
|
||||
revisions = (
|
||||
PagePermissionPolicy()
|
||||
._revisions_for_moderation(request.user)
|
||||
.select_related("user")
|
||||
.order_by("-created_at")
|
||||
)
|
||||
if revisions:
|
||||
warnings.warn(
|
||||
"You have pages undergoing moderation in the legacy moderation system. "
|
||||
"Complete the moderation of these pages before upgrading Wagtail. "
|
||||
"Support for the legacy moderation system will be completely removed "
|
||||
"in a future release. For more details, refer to "
|
||||
"https://docs.wagtail.org/en/stable/releases/2.10.html#move-to-new-configurable-moderation-system-workflow",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
context["page_revisions_for_moderation"] = revisions
|
||||
context["request"] = request
|
||||
context["csrf_token"] = parent_context["csrf_token"]
|
||||
return context
|
||||
|
||||
|
||||
class UserObjectsInWorkflowModerationPanel(Component):
|
||||
name = "user_objects_in_workflow_moderation"
|
||||
template_name = "wagtailadmin/home/user_objects_in_workflow_moderation.html"
|
||||
|
@ -347,7 +316,6 @@ class HomeView(WagtailAdminTemplateMixin, TemplateView):
|
|||
# WhatsNewInWagtailVersionPanel(),
|
||||
UpgradeNotificationPanel(),
|
||||
WorkflowObjectsToModeratePanel(),
|
||||
PagesForModerationPanel(),
|
||||
UserObjectsInWorkflowModerationPanel(),
|
||||
RecentEditsPanel(),
|
||||
LockedPagesPanel(),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import json
|
||||
import warnings
|
||||
from urllib.parse import quote
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -36,7 +35,6 @@ from wagtail.models import (
|
|||
PageSubscription,
|
||||
WorkflowState,
|
||||
)
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
from wagtail.utils.timestamps import render_timestamp
|
||||
|
||||
|
||||
|
@ -48,34 +46,6 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
else:
|
||||
return ["wagtailadmin/pages/edit.html"]
|
||||
|
||||
def add_legacy_moderation_warning(self):
|
||||
# Check for revisions still undergoing moderation and warn - this is for the old moderation system
|
||||
if self.latest_revision and self.latest_revision.submitted_for_moderation:
|
||||
buttons = []
|
||||
|
||||
if self.page.live:
|
||||
buttons.append(self.get_compare_with_live_message_button())
|
||||
|
||||
messages.warning(
|
||||
self.request,
|
||||
_("This page is currently awaiting moderation"),
|
||||
buttons=buttons,
|
||||
)
|
||||
|
||||
page_type = self.page._meta.verbose_name
|
||||
page_title = self.page.get_admin_display_title()
|
||||
|
||||
warnings.warn(
|
||||
f"The {page_type} '{page_title}' is undergoing moderation in "
|
||||
"the legacy moderation system. Complete the moderation of this page "
|
||||
"before upgrading Wagtail. Support for the legacy moderation system "
|
||||
"will be completely removed in a future release. For more details, "
|
||||
"refer to "
|
||||
"https://docs.wagtail.org/en/stable/releases/2.10.html#move-to-new-configurable-moderation-system-workflow",
|
||||
RemovedInWagtail60Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
def add_save_confirmation_message(self):
|
||||
if self.is_reverting:
|
||||
message = _(
|
||||
|
@ -453,7 +423,6 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
for_user=self.request.user,
|
||||
)
|
||||
self.has_unsaved_changes = False
|
||||
self.add_legacy_moderation_warning()
|
||||
self.page_for_status = self.get_page_for_status()
|
||||
|
||||
return self.render_to_response(self.get_context_data())
|
||||
|
@ -864,7 +833,6 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
)
|
||||
self.has_unsaved_changes = True
|
||||
|
||||
self.add_legacy_moderation_warning()
|
||||
self.page_for_status = self.get_page_for_status()
|
||||
|
||||
return self.render_to_response(self.get_context_data())
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
import warnings
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.http import require_GET
|
||||
|
||||
from wagtail.admin import messages
|
||||
from wagtail.admin.mail import send_moderation_notification
|
||||
from wagtail.models import Revision
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
def approve_moderation(request, revision_id):
|
||||
revision = get_object_or_404(Revision.page_revisions, id=revision_id)
|
||||
if not revision.content_object.permissions_for_user(request.user).can_publish():
|
||||
raise PermissionDenied
|
||||
|
||||
if not revision.submitted_for_moderation:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
if request.method == "POST":
|
||||
revision.approve_moderation(user=request.user)
|
||||
|
||||
message = _("Page '%(page_title)s' published.") % {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
}
|
||||
buttons = []
|
||||
if revision.content_object.url is not None:
|
||||
buttons.append(
|
||||
messages.button(
|
||||
revision.content_object.url, _("View live"), new_window=False
|
||||
)
|
||||
)
|
||||
buttons.append(
|
||||
messages.button(
|
||||
reverse("wagtailadmin_pages:edit", args=(revision.content_object.id,)),
|
||||
_("Edit"),
|
||||
)
|
||||
)
|
||||
messages.success(request, message, buttons=buttons)
|
||||
|
||||
if not send_moderation_notification(revision, "approved", request.user):
|
||||
messages.error(request, _("Failed to send approval notifications"))
|
||||
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
|
||||
def reject_moderation(request, revision_id):
|
||||
revision = get_object_or_404(Revision.page_revisions, id=revision_id)
|
||||
if not revision.content_object.permissions_for_user(request.user).can_publish():
|
||||
raise PermissionDenied
|
||||
|
||||
if not revision.submitted_for_moderation:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
if request.method == "POST":
|
||||
revision.reject_moderation(user=request.user)
|
||||
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '%(page_title)s' rejected for publication.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse(
|
||||
"wagtailadmin_pages:edit", args=(revision.content_object.id,)
|
||||
),
|
||||
_("Edit"),
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
if not send_moderation_notification(revision, "rejected", request.user):
|
||||
messages.error(request, _("Failed to send rejection notifications"))
|
||||
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
|
||||
@require_GET
|
||||
def preview_for_moderation(request, revision_id):
|
||||
revision = get_object_or_404(Revision.page_revisions, id=revision_id)
|
||||
if not revision.content_object.permissions_for_user(request.user).can_publish():
|
||||
raise PermissionDenied
|
||||
|
||||
if not revision.submitted_for_moderation:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
page = revision.as_object()
|
||||
page_type = page._meta.verbose_name
|
||||
page_title = page.get_admin_display_title()
|
||||
|
||||
warnings.warn(
|
||||
f"The {page_type} '{page_title}' is undergoing moderation in "
|
||||
"the legacy moderation system. Complete the moderation of this page "
|
||||
"before upgrading Wagtail. Support for the legacy moderation system "
|
||||
"will be completely removed in a future release. For more details, "
|
||||
"refer to "
|
||||
"https://docs.wagtail.org/en/stable/releases/2.10.html#move-to-new-configurable-moderation-system-workflow",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
|
||||
try:
|
||||
preview_mode = page.default_preview_mode
|
||||
except IndexError:
|
||||
raise PermissionDenied
|
||||
|
||||
return page.make_preview_request(
|
||||
request, preview_mode, extra_request_attrs={"revision_id": revision_id}
|
||||
)
|
|
@ -87,42 +87,7 @@ class Command(BaseCommand):
|
|||
set_expired=True, log_action="wagtail.unpublish.scheduled"
|
||||
)
|
||||
|
||||
# 2. get all object revisions for moderation that have been expired
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
expired_revs = [
|
||||
r
|
||||
for r in Revision.objects.filter(submitted_for_moderation=True)
|
||||
if revision_date_expired(r)
|
||||
]
|
||||
if dryrun:
|
||||
self.stdout.write("\n---------------------------------")
|
||||
if expired_revs:
|
||||
self.stdout.write(
|
||||
"Expired revisions to be dropped from moderation queue:"
|
||||
)
|
||||
self.stdout.write("Expiry datetime\t\tSlug\t\tName")
|
||||
self.stdout.write("---------------\t\t----\t\t----")
|
||||
for er in expired_revs:
|
||||
rev_data = er.content
|
||||
self.stdout.write(
|
||||
"{}\t{}\t{}".format(
|
||||
dateparse.parse_datetime(
|
||||
rev_data.get("expire_at")
|
||||
).strftime("%Y-%m-%d %H:%M"),
|
||||
rev_data.get("slug"),
|
||||
rev_data.get("title"),
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.stdout.write("No expired revision to be dropped from moderation.")
|
||||
else:
|
||||
for er in expired_revs:
|
||||
er.submitted_for_moderation = False
|
||||
er.save()
|
||||
|
||||
# 3. get all revisions that need to be published
|
||||
# 2. get all revisions that need to be published
|
||||
revs_for_publishing = Revision.objects.filter(
|
||||
approved_go_live_at__lt=timezone.now()
|
||||
).order_by("approved_go_live_at")
|
||||
|
|
|
@ -61,11 +61,7 @@ def purge_revisions(days=None, pages=True, non_pages=True):
|
|||
elif non_pages:
|
||||
objects = Revision.objects.not_page_revisions()
|
||||
|
||||
# exclude revisions which have been submitted for moderation in the old system
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
purgeable_revisions = objects.exclude(submitted_for_moderation=True).exclude(
|
||||
purgeable_revisions = objects.exclude(
|
||||
# and exclude revisions with an approved_go_live_at date
|
||||
approved_go_live_at__isnull=False
|
||||
)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 4.2.6 on 2023-10-26 15:44
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("wagtailcore", "0090_remove_grouppagepermission_permission_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="revision",
|
||||
name="submitted_for_moderation",
|
||||
),
|
||||
]
|
|
@ -44,7 +44,7 @@ from django.utils import timezone
|
|||
from django.utils import translation as translation
|
||||
from django.utils.cache import patch_cache_control
|
||||
from django.utils.encoding import force_bytes, force_str
|
||||
from django.utils.functional import Promise, cached_property, classproperty
|
||||
from django.utils.functional import Promise, cached_property
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.text import capfirst, slugify
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
@ -369,7 +369,6 @@ class RevisionMixin(models.Model):
|
|||
def save_revision(
|
||||
self,
|
||||
user=None,
|
||||
submitted_for_moderation=False, # RemovedInWagtail60Warning
|
||||
approved_go_live_at=None,
|
||||
changed=True,
|
||||
log_action=False,
|
||||
|
@ -380,7 +379,6 @@ class RevisionMixin(models.Model):
|
|||
Creates and saves a revision.
|
||||
|
||||
:param user: The user performing the action.
|
||||
:param submitted_for_moderation: **Deprecated** – Indicates whether the object was submitted for moderation.
|
||||
:param approved_go_live_at: The date and time the revision is approved to go live.
|
||||
:param changed: Indicates whether there were any content changes.
|
||||
:param log_action: Flag for logging the action. Pass ``True`` to also create a log entry. Can be passed an action string.
|
||||
|
@ -396,7 +394,6 @@ class RevisionMixin(models.Model):
|
|||
revision = Revision.objects.create(
|
||||
content_object=self,
|
||||
base_content_type=self.get_base_content_type(),
|
||||
submitted_for_moderation=submitted_for_moderation,
|
||||
user=user,
|
||||
approved_go_live_at=approved_go_live_at,
|
||||
content=self.serializable_data(),
|
||||
|
@ -1631,7 +1628,6 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
|
|||
def save_revision(
|
||||
self,
|
||||
user=None,
|
||||
submitted_for_moderation=False,
|
||||
approved_go_live_at=None,
|
||||
changed=True,
|
||||
log_action=False,
|
||||
|
@ -1663,7 +1659,6 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
|
|||
revision = Revision.objects.create(
|
||||
content_object=self,
|
||||
base_content_type=self.get_base_content_type(),
|
||||
submitted_for_moderation=submitted_for_moderation,
|
||||
user=user,
|
||||
approved_go_live_at=approved_go_live_at,
|
||||
content=self.serializable_data(),
|
||||
|
@ -1724,14 +1719,6 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
|
|||
content_changed=changed,
|
||||
)
|
||||
|
||||
if submitted_for_moderation:
|
||||
logger.info(
|
||||
'Page submitted for moderation: "%s" id=%d revision_id=%d',
|
||||
self.title,
|
||||
self.id,
|
||||
revision.id,
|
||||
)
|
||||
|
||||
return revision
|
||||
|
||||
def get_latest_revision_as_object(self):
|
||||
|
@ -2698,12 +2685,6 @@ class RevisionQuerySet(models.QuerySet):
|
|||
def not_page_revisions(self):
|
||||
return self.exclude(self.page_revisions_q())
|
||||
|
||||
def submitted(self):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
return self.filter(submitted_for_moderation=True)
|
||||
|
||||
def for_instance(self, instance):
|
||||
return self.filter(
|
||||
content_type=ContentType.objects.get_for_model(
|
||||
|
@ -2740,10 +2721,6 @@ class Revision(models.Model):
|
|||
max_length=255,
|
||||
verbose_name=_("object id"),
|
||||
)
|
||||
# RemovedInWagtail60Warning
|
||||
submitted_for_moderation = models.BooleanField(
|
||||
verbose_name=_("submitted for moderation"), default=False, db_index=True
|
||||
)
|
||||
created_at = models.DateTimeField(db_index=True, verbose_name=_("created at"))
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
|
@ -2763,7 +2740,6 @@ class Revision(models.Model):
|
|||
|
||||
objects = RevisionsManager()
|
||||
page_revisions = PageRevisionsManager()
|
||||
_submitted_revisions = SubmittedRevisionsManager()
|
||||
|
||||
content_object = GenericForeignKey(
|
||||
"content_type", "object_id", for_concrete_model=False
|
||||
|
@ -2775,14 +2751,6 @@ class Revision(models.Model):
|
|||
def base_content_object(self):
|
||||
return self.base_content_type.get_object_for_this_type(pk=self.object_id)
|
||||
|
||||
@classproperty
|
||||
def submitted_revisions(self):
|
||||
warnings.warn(
|
||||
"SubmittedRevisionsManager is deprecated and will be removed in a future release.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
return self._submitted_revisions
|
||||
|
||||
def save(self, user=None, *args, **kwargs):
|
||||
# Set default value for created_at to now
|
||||
# We cannot use auto_now_add as that will override
|
||||
|
@ -2797,12 +2765,6 @@ class Revision(models.Model):
|
|||
self.base_content_type_id = self.content_type_id
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
if self.submitted_for_moderation:
|
||||
# ensure that all other revisions of this object have the 'submitted for moderation' flag unset
|
||||
Revision.objects.filter(
|
||||
base_content_type_id=self.base_content_type_id,
|
||||
object_id=self.object_id,
|
||||
).exclude(id=self.id).update(submitted_for_moderation=False)
|
||||
|
||||
if (
|
||||
self.approved_go_live_at is None
|
||||
|
@ -2832,49 +2794,6 @@ class Revision(models.Model):
|
|||
def as_object(self):
|
||||
return self.content_object.with_content_json(self.content)
|
||||
|
||||
def approve_moderation(self, user=None):
|
||||
warnings.warn(
|
||||
"Revision.approve_moderation() is deprecated and will be removed in a future release.",
|
||||
RemovedInWagtail60Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
if self.submitted_for_moderation:
|
||||
logger.info(
|
||||
'Page moderation approved: "%s" id=%d revision_id=%d',
|
||||
self.content_object.title,
|
||||
self.content_object.id,
|
||||
self.id,
|
||||
)
|
||||
log(
|
||||
instance=self.as_object(),
|
||||
action="wagtail.moderation.approve",
|
||||
user=user,
|
||||
revision=self,
|
||||
)
|
||||
self.publish()
|
||||
|
||||
def reject_moderation(self, user=None):
|
||||
warnings.warn(
|
||||
"Revision.reject_moderation() is deprecated and will be removed in a future release.",
|
||||
RemovedInWagtail60Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
if self.submitted_for_moderation:
|
||||
logger.info(
|
||||
'Page moderation rejected: "%s" id=%d revision_id=%d',
|
||||
self.content_object.title,
|
||||
self.content_object.id,
|
||||
self.id,
|
||||
)
|
||||
log(
|
||||
instance=self.as_object(),
|
||||
action="wagtail.moderation.reject",
|
||||
user=user,
|
||||
revision=self,
|
||||
)
|
||||
self.submitted_for_moderation = False
|
||||
self.save(update_fields=["submitted_for_moderation"])
|
||||
|
||||
def is_latest_revision(self):
|
||||
if self.id is None:
|
||||
# special case: a revision without an ID is presumed to be newly-created and is thus
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
import warnings
|
||||
|
||||
from django.contrib.auth import get_permission_codename, get_user_model
|
||||
from django.db.models import CharField, Q
|
||||
from django.db.models.functions import Cast
|
||||
|
||||
from wagtail.models import GroupPagePermission, Page, Revision
|
||||
from wagtail.permission_policies.base import OwnershipPermissionPolicy
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class PagePermissionPolicy(OwnershipPermissionPolicy):
|
||||
|
@ -245,10 +242,3 @@ class PagePermissionPolicy(OwnershipPermissionPolicy):
|
|||
Cast("pk", output_field=CharField()), flat=True
|
||||
)
|
||||
)
|
||||
|
||||
def revisions_for_moderation(self, user):
|
||||
warnings.warn(
|
||||
"The PagePermissionPolicy.revisions_for_moderation() method is deprecated.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
return self._revisions_for_moderation(user)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""Handles rendering of the list of actions in the footer of the snippet create/edit views."""
|
||||
import warnings
|
||||
from functools import lru_cache
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -14,7 +13,6 @@ from wagtail import hooks
|
|||
from wagtail.admin.ui.components import Component
|
||||
from wagtail.models import DraftStateMixin, LockableMixin, WorkflowMixin
|
||||
from wagtail.snippets.permissions import get_permission_name
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class ActionMenuItem(Component):
|
||||
|
@ -86,15 +84,6 @@ class SubmitForModerationMenuItem(ActionMenuItem):
|
|||
icon_name = "resubmit"
|
||||
|
||||
def is_shown(self, context):
|
||||
legacy_setting = getattr(settings, "WAGTAIL_MODERATION_ENABLED", None)
|
||||
if legacy_setting is not None:
|
||||
warnings.warn(
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
if not legacy_setting:
|
||||
return False
|
||||
|
||||
if not getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
|
||||
return False
|
||||
|
||||
|
@ -176,15 +165,6 @@ class RestartWorkflowMenuItem(ActionMenuItem):
|
|||
icon_name = "login"
|
||||
|
||||
def is_shown(self, context):
|
||||
legacy_setting = getattr(settings, "WAGTAIL_MODERATION_ENABLED", None)
|
||||
if legacy_setting is not None:
|
||||
warnings.warn(
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
RemovedInWagtail60Warning,
|
||||
)
|
||||
if not legacy_setting:
|
||||
return False
|
||||
|
||||
if not getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
|
||||
return False
|
||||
if context["view"] != "edit":
|
||||
|
|
|
@ -7,7 +7,6 @@ from django.urls import reverse
|
|||
from wagtail.models import Workflow, WorkflowContentType, WorkflowState
|
||||
from wagtail.test.testapp.models import FullFeaturedSnippet, ModeratedModel
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
# This module serves to gather snippets-equivalent of workflows-related tests
|
||||
# that are found throughout page-specific test modules, e.g. test_create_page.py,
|
||||
|
@ -67,17 +66,6 @@ class TestCreateView(BaseWorkflowsTestCase):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, 'name="action-submit"')
|
||||
|
||||
@override_settings(WAGTAIL_MODERATION_ENABLED=False)
|
||||
def test_get_workflow_buttons_not_shown_when_moderation_disabled(self):
|
||||
# Note: remove this when all legacy moderation code has been removed
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
):
|
||||
response = self.get()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, 'name="action-submit"')
|
||||
|
||||
def test_post_submit_for_moderation(self):
|
||||
response = self.post({"text": "Newly created", "action-submit": "Submit"})
|
||||
object = self.model.objects.get(text="Newly created")
|
||||
|
@ -132,17 +120,6 @@ class TestEditView(BaseWorkflowsTestCase):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, 'name="action-submit"')
|
||||
|
||||
@override_settings(WAGTAIL_MODERATION_ENABLED=False)
|
||||
def test_get_workflow_buttons_not_shown_when_moderation_disabled(self):
|
||||
# Note: remove this when all legacy moderation code has been removed
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"WAGTAIL_MODERATION_ENABLED is deprecated. Use WAGTAIL_WORKFLOW_ENABLED instead.",
|
||||
):
|
||||
response = self.get()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, 'name="action-submit"')
|
||||
|
||||
def test_post_submit_for_moderation(self):
|
||||
response = self.post({"text": "Edited!", "action-submit": "Submit"})
|
||||
self.object.refresh_from_db()
|
||||
|
|
|
@ -305,7 +305,7 @@ class TestPublishScheduledPagesCommand(WagtailTestUtils, TestCase):
|
|||
page.save_revision(approved_go_live_at=timezone.now() - timedelta(days=1))
|
||||
|
||||
page.title = "Goodbye world!"
|
||||
page.save_revision(submitted_for_moderation=False)
|
||||
page.save_revision()
|
||||
|
||||
management.call_command("publish_scheduled_pages")
|
||||
|
||||
|
@ -402,38 +402,6 @@ class TestPublishScheduledPagesCommand(WagtailTestUtils, TestCase):
|
|||
self.assertTrue(p.live)
|
||||
self.assertFalse(p.expired)
|
||||
|
||||
def test_expired_pages_are_dropped_from_mod_queue(self):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=False,
|
||||
expire_at=timezone.now() - timedelta(days=1),
|
||||
)
|
||||
self.root_page.add_child(instance=page)
|
||||
|
||||
page.save_revision(submitted_for_moderation=True)
|
||||
|
||||
p = Page.objects.get(slug="hello-world")
|
||||
self.assertFalse(p.live)
|
||||
self.assertTrue(
|
||||
Revision.page_revisions.filter(
|
||||
object_id=p.id, submitted_for_moderation=True
|
||||
).exists()
|
||||
)
|
||||
|
||||
management.call_command("publish_scheduled_pages")
|
||||
|
||||
p = Page.objects.get(slug="hello-world")
|
||||
self.assertFalse(
|
||||
Revision.page_revisions.filter(
|
||||
object_id=p.id, submitted_for_moderation=True
|
||||
).exists()
|
||||
)
|
||||
|
||||
|
||||
class TestPublishScheduledCommand(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
@ -540,7 +508,7 @@ class TestPublishScheduledCommand(WagtailTestUtils, TestCase):
|
|||
self.snippet.save_revision(approved_go_live_at=go_live_at)
|
||||
|
||||
self.snippet.text = "Goodbye world!"
|
||||
self.snippet.save_revision(submitted_for_moderation=False)
|
||||
self.snippet.save_revision()
|
||||
|
||||
management.call_command("publish_scheduled")
|
||||
|
||||
|
@ -660,19 +628,6 @@ class TestPurgeRevisionsCommandForPages(TestCase):
|
|||
self.assertRevisionExists(revision_2)
|
||||
|
||||
def test_revisions_in_moderation_or_workflow_not_purged(self):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove the lines until the first assertion when the deprecation period#
|
||||
# for the legacy moderation system ends.
|
||||
revision = self.object.save_revision(submitted_for_moderation=True)
|
||||
|
||||
# Save a new revision to ensure that the moderated revision
|
||||
# is not the latest one
|
||||
self.object.save_revision()
|
||||
|
||||
self.run_command()
|
||||
|
||||
self.assertRevisionExists(revision)
|
||||
|
||||
workflow = Workflow.objects.create(name="test_workflow")
|
||||
task_1 = Task.objects.create(name="test_task_1")
|
||||
user = get_user_model().objects.first()
|
||||
|
|
|
@ -1479,38 +1479,9 @@ class TestCopyPage(TestCase):
|
|||
msg="Child objects in revisions were not given a new primary key",
|
||||
)
|
||||
|
||||
def test_copy_page_copies_revisions_and_doesnt_submit_for_moderation(self):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
christmas_event.save_revision(submitted_for_moderation=True)
|
||||
|
||||
# Copy it
|
||||
new_christmas_event = christmas_event.copy(
|
||||
update_attrs={"title": "New christmas event", "slug": "new-christmas-event"}
|
||||
)
|
||||
|
||||
# Check that the old revision is still submitted for moderation
|
||||
self.assertTrue(
|
||||
christmas_event.revisions.order_by("created_at")
|
||||
.first()
|
||||
.submitted_for_moderation
|
||||
)
|
||||
|
||||
# Check that the new revision is not submitted for moderation
|
||||
self.assertFalse(
|
||||
new_christmas_event.revisions.order_by("created_at")
|
||||
.first()
|
||||
.submitted_for_moderation
|
||||
)
|
||||
|
||||
def test_copy_page_copies_revisions_and_doesnt_change_created_at(self):
|
||||
christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this line when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
christmas_event.save_revision(submitted_for_moderation=True)
|
||||
christmas_event.save_revision()
|
||||
|
||||
# Set the created_at of the revision to a time in the past
|
||||
revision = christmas_event.get_latest_revision()
|
||||
|
|
|
@ -5,7 +5,6 @@ from wagtail.models import GroupPagePermission, Page, get_default_page_content_t
|
|||
from wagtail.permission_policies.pages import PagePermissionPolicy
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.tests.test_permission_policies import PermissionPolicyTestUtils
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class PermissionPolicyTestCase(PermissionPolicyTestUtils, WagtailTestUtils, TestCase):
|
||||
|
@ -520,16 +519,3 @@ class TestPagePermissionPolicy(PermissionPolicyTestCase):
|
|||
),
|
||||
[self.superuser],
|
||||
)
|
||||
|
||||
def test_get_revisions_for_moderation(self):
|
||||
# RemovedInWagtail60Warning
|
||||
# Remove this test when the deprecation period for the legacy
|
||||
# moderation system ends.
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"The PagePermissionPolicy.revisions_for_moderation() method is deprecated.",
|
||||
):
|
||||
revisions = self.policy.revisions_for_moderation(self.superuser)
|
||||
|
||||
revision = self.reports_page.save_revision(submitted_for_moderation=True)
|
||||
self.assertCountEqual(revisions, [revision])
|
||||
|
|
|
@ -10,7 +10,6 @@ from wagtail.test.testapp.models import (
|
|||
RevisableModel,
|
||||
SimplePage,
|
||||
)
|
||||
from wagtail.utils.deprecation import RemovedInWagtail60Warning
|
||||
|
||||
|
||||
class TestRevisableModel(TestCase):
|
||||
|
@ -169,12 +168,3 @@ class TestRevisableModel(TestCase):
|
|||
# The id is used as a tie breaker
|
||||
self.assertEqual(first.created_at, second.created_at)
|
||||
self.assertLess(first.id, second.id)
|
||||
|
||||
def test_submitted_revisions_manager(self):
|
||||
self.instance.save_revision()
|
||||
revision = self.instance.save_revision(submitted_for_moderation=True)
|
||||
with self.assertWarnsMessage(
|
||||
RemovedInWagtail60Warning,
|
||||
"SubmittedRevisionsManager is deprecated and will be removed in a future release.",
|
||||
):
|
||||
self.assertEqual(list(Revision.submitted_revisions.all()), [revision])
|
||||
|
|
|
@ -242,7 +242,7 @@ class TestRichTextField(TestCase):
|
|||
def test_get_searchable_content(self):
|
||||
christmas_page = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
christmas_page.body = '<p><b>Merry Christmas from <a href="https://wagtail.org/">Wagtail!</a></b> & co.</p>'
|
||||
christmas_page.save_revision(submitted_for_moderation=False)
|
||||
christmas_page.save_revision()
|
||||
|
||||
body_field = christmas_page._meta.get_field("body")
|
||||
value = body_field.value_from_object(christmas_page)
|
||||
|
@ -252,7 +252,7 @@ class TestRichTextField(TestCase):
|
|||
def test_get_searchable_content_whitespace(self):
|
||||
christmas_page = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
christmas_page.body = "<p>buttery<br />mashed</p><p>po<i>ta</i>toes</p>"
|
||||
christmas_page.save_revision(submitted_for_moderation=False)
|
||||
christmas_page.save_revision()
|
||||
|
||||
body_field = christmas_page._meta.get_field("body")
|
||||
value = body_field.value_from_object(christmas_page)
|
||||
|
|
Ładowanie…
Reference in New Issue