Porównaj commity

...

6 Commity

Autor SHA1 Wiadomość Data
Afonso Matos 175e671087
Merge 80dffaf107 into a09bba67cd 2024-05-09 09:05:31 +00:00
Matt Westcott a09bba67cd
Refactor image chooser pagination to check WAGTAILIMAGES_CHOOSER_PAGE_SIZE at runtime 2024-05-09 09:38:54 +01:00
Matt Westcott 6fa3985674 Release note for #11926 2024-05-08 12:34:39 +01:00
Jake Howard 84d9bd6fb6 Mention use of GitHub's security advisories 2024-05-08 12:34:39 +01:00
Jake Howard 37f9ae2ec6 Add note about bug bounties 2024-05-08 12:34:39 +01:00
Afonso 80dffaf107 Fix #11716: Failure in Dynamic Image ServeView
Added back a line that was removed in a previous commit,"rendition.file.open("rb")" in serve.py.
Also, created a test in admin/tests/viewsets , test_image_presence.py that confirms that
the issue has been resolved. The test looks for a status error code 500 in the display of an image,
something that happenned when the dynamic serve view failed. If it finds it, the test fails.
The test also passes when we dont't use a dynamic serve view.
2024-04-05 14:06:49 +01:00
9 zmienionych plików z 93 dodań i 8 usunięć

Wyświetl plik

@ -13,7 +13,9 @@ Changelog
* Fix: Preserve whitespace in comment replies (Elhussein Almasri)
* Docs: Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
* Docs: Document `restriction_type` field on PageViewRestriction (Shlomo Markowitz)
* Docs: Document Wagtail's bug bounty policy (Jake Howard)
* Maintenance: Use `DjangoJSONEncoder` instead of custom `LazyStringEncoder` to serialize Draftail config (Sage Abdullah)
* Maintenance: Refactor image chooser pagination to check `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` at runtime (Matt Westcott)
6.1 (01.05.2024)

Wyświetl plik

@ -34,6 +34,12 @@ At any given time, the Wagtail team provides official security support for sever
When new releases are issued for security reasons, the accompanying notice will include a list of affected versions.
This list is comprised solely of supported versions of Wagtail: older versions may also be affected, but we do not investigate to determine that, and will not issue patches or new releases for those versions.
## Bug Bounties
Wagtail does not have a "Bug Bounty" program. Whilst we appreciate and accept reports from anyone, and will gladly give credit to you and/or your organisation, we aren't able to "reward" you for reporting the vulnerability.
["Beg Bounties"](https://www.troyhunt.com/beg-bounties/) are ever increasing among security researchers, and it's not something we condone or support.
## How Wagtail discloses security issues
Our process for taking a security issue from private discussion to public disclosure involves multiple steps.
@ -46,8 +52,8 @@ On the day of disclosure, we will take the following steps:
1. Apply the relevant patch(es) to Wagtail's codebase.
The commit messages for these patches will indicate that they are for security issues, but will not describe the issue in any detail; instead, they will warn of upcoming disclosure.
2. Issue the relevant release(s), by placing new packages on [the Python Package Index](https://pypi.org/project/wagtail/), tagging the new release(s) in Wagtail's GitHub repository and updating Wagtail's [release notes](../releases/index).
3. Post a public entry on [Wagtail's blog](https://wagtail.org/blog/), describing the issue and its resolution in detail, pointing to the relevant patches and new releases, and crediting the reporter of the issue (if the reporter wishes to be publicly identified).
4. Post a notice to the [Wagtail discussion board](https://github.com/wagtail/wagtail/discussions), [Slack workspace](https://wagtail.org/slack/) and Twitter feed ([\@WagtailCMS](https://twitter.com/wagtailcms)) that links to the blog post.
3. Publish a [security advisory](https://github.com/wagtail/wagtail/security/advisories?state=published) on Wagtail's GitHub repository. This describes the issue and its resolution in detail, pointing to the relevant patches and new releases, and crediting the reporter of the issue (if the reporter wishes to be publicly identified)
4. Post a notice to the [Wagtail discussion board](https://github.com/wagtail/wagtail/discussions), [Slack workspace](https://wagtail.org/slack/) and Twitter feed ([\@WagtailCMS](https://twitter.com/wagtailcms)) that links to the security advisory.
If a reported issue is believed to be particularly time-sensitive -- due to a known exploit in the wild, for example -- the time between advance notification and public disclosure may be shortened considerably.

Wyświetl plik

@ -30,11 +30,13 @@ depth: 1
* Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
* Document `restriction_type` field on PageViewRestriction (Shlomo Markowitz)
* Document Wagtail's bug bounty policy (Jake Howard)
### Maintenance
* Use `DjangoJSONEncoder` instead of custom `LazyStringEncoder` to serialize Draftail config (Sage Abdullah)
* Refactor image chooser pagination to check `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` at runtime (Matt Westcott)
## Upgrade considerations - changes affecting all projects

Wyświetl plik

@ -0,0 +1,49 @@
import io
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
from django.test import TestCase
from wagtail.test.utils import WagtailTestUtils
# This test was made in order to test the Dynamic Image Serve View.
# For this test you will need to change your "mysite" in order for its home_page.html to show
# an image.
# To do that, you need to ensure that you have (it can be dynamic) serve view in the template and update
# the urls.py. Problably an addition of "image = models.ForeignKey( get_image_model(), ...)"
# field to the HomePage class will also be needed
class TestImagePresence(WagtailTestUtils, TestCase):
def test_image_presence(self):
# Make request to localhost
response = requests.get("http://localhost:8000")
# Check if the request was successful
self.assertEqual(response.status_code, 200)
# Parse the HTML content of the response
soup = BeautifulSoup(response.content, "html.parser")
# Find img elements with src="/images/"
images = soup.find_all("img", src=lambda x: x and "/images/" in x)
# Check if at least one image was found
self.assertTrue(images)
# Check for images with error (status code 500)
for img in images:
img_src = img.get("src")
full_img_url = urljoin(
"http://localhost:8000", img_src
) # Construct full image URL
# Request the image
img_response = requests.get(full_img_url, stream=True)
# Check if the response is a properly opened file
if img_response.ok:
self.assertTrue(isinstance(img_response.raw, io.IOBase))
else:
self.fail(f"Error accessing image: {img_src}")

Wyświetl plik

@ -17,6 +17,10 @@ class ViewSet(WagtailMenuRegisterable):
For more information on how to use this class, see :ref:`using_base_viewset`.
"""
#: A special value that, when passed in a kwargs dict to construct a view, indicates that
#: the attribute should not be written and should instead be left as the view's initial value
UNDEFINED = object()
#: A name for this viewset, used as the default URL prefix and namespace.
name = None
@ -42,12 +46,13 @@ class ViewSet(WagtailMenuRegisterable):
in addition to any kwargs passed to this method. Items from get_common_view_kwargs will be
filtered to only include those that are valid for the given view_class.
"""
merged_kwargs = self.get_common_view_kwargs()
merged_kwargs.update(kwargs)
filtered_kwargs = {
key: value
for key, value in self.get_common_view_kwargs().items()
if hasattr(view_class, key)
for key, value in merged_kwargs.items()
if hasattr(view_class, key) and value is not self.UNDEFINED
}
filtered_kwargs.update(kwargs)
return view_class.as_view(**filtered_kwargs)
def inject_view_methods(self, view_class, method_names):

Wyświetl plik

@ -29,7 +29,7 @@ class ChooserViewSet(ViewSet):
) #: Label for the 'choose' button in the chooser widget, when an item has already been chosen
edit_item_text = _("Edit") #: Label for the 'edit' button in the chooser widget
per_page = 10 #: Number of results to show per page
per_page = ViewSet.UNDEFINED #: Number of results to show per page
#: A list of URL query parameters that should be passed on unmodified as part of any links or
#: form submissions within the chooser modal workflow.

Wyświetl plik

@ -1681,6 +1681,22 @@ class TestImageChooserView(WagtailTestUtils, TestCase):
response = self.get({"p": 9999})
self.assertEqual(response.status_code, 404)
@override_settings(WAGTAILIMAGES_CHOOSER_PAGE_SIZE=4)
def test_chooser_page_size(self):
images = [
Image(
title="Test image %i" % i,
file=get_test_image_file(size=(1, 1)),
)
for i in range(1, 12)
]
Image.objects.bulk_create(images)
response = self.get()
self.assertContains(response, "Page 1 of 3")
self.assertEqual(response.status_code, 200)
def test_filter_by_tag(self):
for i in range(0, 10):
image = Image.objects.create(

Wyświetl plik

@ -72,10 +72,15 @@ class ImageCreationFormMixin(CreationFormMixin):
class BaseImageChooseView(BaseChooseView):
template_name = "wagtailimages/chooser/chooser.html"
results_template_name = "wagtailimages/chooser/results.html"
per_page = 12
ordering = "-created_at"
construct_queryset_hook_name = "construct_image_chooser_queryset"
@property
def per_page(self):
# Make per_page into a property so that we can read back WAGTAILIMAGES_CHOOSER_PAGE_SIZE
# at runtime.
return getattr(settings, "WAGTAILIMAGES_CHOOSER_PAGE_SIZE", 20)
def get_object_list(self):
return (
permission_policy.instances_user_has_any_permission_for(
@ -309,7 +314,6 @@ class ImageChooserViewSet(ChooserViewSet):
preserve_url_parameters = ChooserViewSet.preserve_url_parameters + ["select_format"]
icon = "image"
per_page = getattr(settings, "WAGTAILIMAGES_CHOOSER_PAGE_SIZE", 10)
choose_one_text = _("Choose an image")
create_action_label = _("Upload")
create_action_clicked_label = _("Uploading…")

Wyświetl plik

@ -65,6 +65,7 @@ class ServeView(View):
mime_type = willow_image.mime_type
# Serve the file
rendition.file.open("rb")
return FileResponse(rendition.file, content_type=mime_type)
def redirect(self, rendition):