Remove legacy moderation system

pull/11157/head
Matt Westcott 2023-10-26 17:15:56 +01:00 zatwierdzone przez Matt Westcott
rodzic cdac7dc7f5
commit ab86351a8d
33 zmienionych plików z 28 dodań i 1533 usunięć

Wyświetl plik

@ -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.

Wyświetl plik

@ -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

Wyświetl plik

@ -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:

Wyświetl plik

@ -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,

Wyświetl plik

@ -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":

Wyświetl plik

@ -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 %}

Wyświetl plik

@ -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 %}

Wyświetl plik

@ -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 %}

Wyświetl plik

@ -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:

Wyświetl plik

@ -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):
"""

Wyświetl plik

@ -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"]

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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">')

Wyświetl plik

@ -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):

Wyświetl plik

@ -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"),

Wyświetl plik

@ -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"

Wyświetl plik

@ -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(),

Wyświetl plik

@ -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())

Wyświetl plik

@ -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}
)

Wyświetl plik

@ -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")

Wyświetl plik

@ -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
)

Wyświetl plik

@ -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",
),
]

Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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":

Wyświetl plik

@ -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()

Wyświetl plik

@ -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()

Wyświetl plik

@ -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()

Wyświetl plik

@ -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])

Wyświetl plik

@ -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])

Wyświetl plik

@ -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> &amp; 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)