pouvoir désactiver le cache de requests_wrapper en ajoutant un paramètre ?nocache à l'URL de la page (#75916) #202

Merged
bdauvergne merged 2 commits from wip/75916-Pouvoir-prevenir-combo-pour-inva into main 2024-01-15 16:19:43 +01:00
6 changed files with 151 additions and 2 deletions

View File

@ -396,6 +396,7 @@ class WcsBlurpMixin:
cache_duration=self.cache_duration,
raise_if_not_cached=not (context.get('synchronous')),
log_errors=False,
django_request=context.get('request'),
)
returns.add(response.status_code)
response.raise_for_status()
@ -1197,6 +1198,7 @@ class WcsCardCell(CardMixin, CellBase):
cache_duration=5,
raise_if_not_cached=not synchronous,
log_errors=False,
django_request=context.get('request'),
)
response.raise_for_status()
except RequestException:
@ -1273,6 +1275,7 @@ class WcsCardCell(CardMixin, CellBase):
cache_duration=5,
raise_if_not_cached=not synchronous,
log_errors=False,
django_request=context.get('request'),
)
response.raise_for_status()
except RequestException:

View File

@ -11,7 +11,7 @@
{% endif %}
<div class="cell {{ cell.css_class_names }} {{ cell.asset_css_classes }}{% if cell.slug %} {{cell.slug}}{% endif %}{% if cell|shown_because_admin:request %} shown-because-admin{% endif %}"
{% if cell.slug and cell.use_slug_as_id %}id="{{ cell.slug }}"{% endif %}
data-ajax-cell-url="{{ site_base }}{{ cell.get_ajax_url }}"
data-ajax-cell-url="{{ site_base }}{{ cell.get_ajax_url }}{% if 'nocache' in request.GET and request.user.is_authenticated and not cell.ajax_refresh %}?nocache{% endif %}"
data-ajax-cell-loading-message="{{ cell.loading_message }}"
data-ajax-cell-error-message="{% trans "Loading error" %}"
{% if cell.ajax_refresh %}data-ajax-cell-refresh="{{ cell.ajax_refresh }}"{% endif %}

View File

@ -137,6 +137,10 @@ class Requests(RequestsSession):
federation_key=federation_key,
)
if django_request and 'nocache' in django_request.GET and django_request.user.is_authenticated:
# do not use cache if ?nocache is given and user is authenticated
invalidate_cache = True
if method == 'GET' and cache_duration:
# handle cache
cache_key = self.get_cache_key(url=url, params=kwargs.get('params', {}))

View File

@ -8,6 +8,7 @@ from unittest import mock
import pytest
import requests
import responses
from django.apps import apps
from django.conf import settings
from django.contrib.auth.models import User
@ -890,6 +891,74 @@ def test_json_cell_validity(context):
assert ValidityInfo.objects.exists() is False
@responses.activate
def test_json_cell_nocache(app, freezer):
User.objects.create(username='foo')
page = Page(id=1, title='example page', slug='index')
page.save()
cell = JsonCell(id=1)
cell.placeholder = 'content'
cell.page = page
cell.order = 0
cell.url = 'http://json.example.com'
cell.template_string = '{{ json|json_script:"foo"}}'
cell.save()
counter = 0
def content_callback(request):
nonlocal counter
counter += 1
return (200, {'Content-Type': 'application/json'}, json.dumps({'counter': counter}))
responses.add_callback(responses.GET, 'http://json.example.com', callback=content_callback)
# normal behaviour:
# first call, nothing in cache, asynchronous loading of the celle is used
resp = app.get('/')
cell_pyquery = resp.pyquery('.cell')
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/data_jsoncell-1/'
assert cell_pyquery.text() == 'Loading...'
assert counter == 0
resp = app.get(cell_url)
assert json.loads(resp.pyquery('script').text())['counter'] == 1
assert counter == 1
# second call, cache is used
resp = app.get('/')
cell_pyquery = resp.pyquery('.cell')
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/data_jsoncell-1/'
assert cell_pyquery.text() == '{"counter": 1}'
assert counter == 1
# third call, ?nocache parameter used, but not connected: cache is still used
resp = app.get('/?nocache')
cell_pyquery = resp.pyquery('.cell')
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/data_jsoncell-1/'
assert cell_pyquery.text() == '{"counter": 1}'
assert counter == 1
# fourth call, ?nocache & connected: cache is ignored, asynchronous loading
# is used, ?nocache is added to the cell ajax url
app.set_user('foo')
resp = app.get('/?nocache')
cell_pyquery = resp.pyquery('.cell')
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/data_jsoncell-1/?nocache'
assert cell_pyquery.text() == 'Loading...'
assert counter == 1
resp = app.get(cell_url)
assert json.loads(resp.pyquery('script').text())['counter'] == 2
assert counter == 2
def test_manager_json_cell_tabs(app, admin_user):
page = Page.objects.create(title='example page', slug='example-page')
JsonCell.objects.create(

View File

@ -1,3 +1,4 @@
import copy
import json
import re
import sys
@ -5,8 +6,9 @@ from io import StringIO
from unittest import mock
import pytest
import responses
from django.apps import apps
from django.contrib.auth.models import AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.core.cache import cache
from django.core.management import call_command
from django.test.client import RequestFactory
@ -4258,6 +4260,75 @@ def test_card_cell_assets(mock_send, settings, app, admin_user):
assert 'Logo — %s' % cell2.get_label_for_asset() in resp.text
@responses.activate
def test_card_cell_nocache(app, freezer):
from . import utils
cache.clear()
User.objects.create(username='foo')
responses.get(
'http://127.0.0.1:8999/api/cards/card_model_1/@schema', json=utils.WCS_CARDDEF_SCHEMAS['card_model_1']
)
data = copy.deepcopy(utils.WCS_CARDS_DATA['card_model_1'])
responses.get('http://127.0.0.1:8999/api/cards/card_model_1/list', json={'data': data})
page = Page(id=1, title='example page', slug='index')
page.save()
cell = WcsCardCell(id=1, page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
assert len(responses.calls) == 1
resp = app.get('/')
cell_pyquery = list(resp.pyquery('.cell').items())[0]
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/wcs_wcscardcell-1/'
assert cell_pyquery.text() == 'Loading...'
assert len(responses.calls) == 2
# value of FieldB
resp = app.get(cell_url)
assert list(resp.pyquery('div.value').items())[1].text() == 'yes'
assert len(responses.calls) == 2
# change value of FieldB for first card
assert data[0]['fields']['fieldb'] is True
data[0]['fields']['fieldb'] = False
responses.replace(responses.GET, 'http://127.0.0.1:8999/api/cards/card_model_1/list', json={'data': data})
# nocache, no user
resp = app.get('/?nocache')
cell_pyquery = list(resp.pyquery('.cell').items())[0]
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/wcs_wcscardcell-1/'
assert cell_pyquery.text() == 'Loading...'
assert len(responses.calls) == 2
# value of FieldB
resp = app.get(cell_url)
assert list(resp.pyquery('div.value').items())[1].text() == 'yes'
assert len(responses.calls) == 2
# nocache, user
app.set_user('foo')
resp = app.get('/?nocache')
cell_pyquery = list(resp.pyquery('.cell').items())[0]
cell_url = cell_pyquery[0].attrib['data-ajax-cell-url']
assert cell_url == '/ajax/cell/1/wcs_wcscardcell-1/?nocache'
assert cell_pyquery.text() == 'Loading...'
assert len(responses.calls) == 3
# value of FieldB
resp = app.get(cell_url)
assert list(resp.pyquery('div.value').items())[1].text() == 'no'
assert len(responses.calls) == 5
def get_output_of_command(command, *args, **kwargs):
old_stdout = sys.stdout
output = sys.stdout = StringIO()

View File

@ -39,6 +39,7 @@ deps =
git+https://git.entrouvert.org/entrouvert/publik-django-templatetags.git
pre-commit
uwsgidecorators
responses
allowlist_externals =
./getlasso3.sh
commands =
@ -73,6 +74,7 @@ deps =
git+https://git.entrouvert.org/debian/django-ckeditor.git
git+https://git.entrouvert.org/publik-django-templatetags.git
uwsgidecorators
responses
allowlist_externals =
./getlasso3.sh
./pylint.sh