Skip to content

Commit

Permalink
Defensive file access in news.html
Browse files Browse the repository at this point in the history
Prevent a 500 error when the image of a news article cannot be opened

Fix assertion for pipeline test

can_open_file templatetag condition changes
  • Loading branch information
calummackervoy committed Nov 26, 2024
1 parent d4244a2 commit 8f0779f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
3 changes: 2 additions & 1 deletion itou/templates/announcements/news.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends "layout/base.html" %}
{% load file_access %}
{% load theme_inclusion %}

{% block title %}Nouveautés {{ block.super }}{% endblock %}
Expand Down Expand Up @@ -32,7 +33,7 @@
{% for news_item in month_news.items.all %}
<div class="row mb-3">
<div class="col-12 col-md-4{% if news_item.image %} mb-3{% else %} d-none d-md-inline{% endif %}">
{% if news_item.image %}
{% if news_item.image|can_open_file %}
<img src="{{ news_item.image.url }}"
alt="{{ news_item.image_alt_text }}"
{% if not news_item.image_alt_text %}aria-hidden="true"{% endif %}
Expand Down
17 changes: 17 additions & 0 deletions itou/utils/templatetags/file_access.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django import template
from sentry_sdk.api import capture_exception


register = template.Library()


@register.filter
def can_open_file(file):
if not file:
return False
try:
with file.open():
return True
except FileNotFoundError as e:
capture_exception(e)
return False
20 changes: 19 additions & 1 deletion tests/www/announcements/test_views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import re
from unittest.mock import patch

import pytest
from django.core.files.storage import storages
from django.urls import reverse
from pytest_django.asserts import assertContains
from pytest_django.asserts import assertContains, assertNotContains

from itou.users.enums import UserKind
from tests.communications.factories import AnnouncementCampaignFactory, AnnouncementItemFactory
Expand Down Expand Up @@ -107,3 +111,17 @@ def assert_content_matches_snapshot(response):
AnnouncementItemFactory(user_kind_tags=[UserKind.PRESCRIBER])
client.force_login(JobSeekerFactory())
assert_content_matches_snapshot(client.get(url))

def test_rendering_invalid_file_does_not_crash(self, client):
user = JobSeekerFactory()
item = AnnouncementItemFactory(with_image=True, user_kind_tags=[user.kind])

with patch.object(storages["public"], "_open", side_effect=FileNotFoundError("File does not exist")):
response = client.get(reverse("announcements:news"))

self._assert_all_items_rendered(response, item.campaign)

# Contains placeholder image
assertNotContains(response, item.image.url)
pattern = re.compile(r"ico-bicro-important\.?[a-zA-Z0-9_]*\.?svg")
assert pattern.search(str(parse_response_to_soup(response, "#news-1 img.img-muted"))) is not None

0 comments on commit 8f0779f

Please sign in to comment.