Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug grtlv 404 caching issue on logged out learn articles and hcsat #3641

Draft
wants to merge 9 commits into
base: develop
Choose a base branch
from
7 changes: 6 additions & 1 deletion core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
SECTION_SLUGS as EXPORTPLAN_SLUGS,
SECTIONS as EXPORTPLAN_URL_MAP,
)
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect

# If we make a Redirect appear as a Snippet, we can sync it via Wagtail-Transfer
register_snippet(Redirect)
Expand Down Expand Up @@ -764,7 +766,9 @@ def serve(self, request):
return self._redirect_to_parent_module()


class DetailPage(settings.FEATURE_DEA_V2 and CMSGenericPageAnonymous or CMSGenericPage, mixins.HCSATMixin):
class DetailPage(
settings.FEATURE_DEA_V2 and CMSGenericPageAnonymous or CMSGenericPage, mixins.HCSATMixin, WagtailCacheMixin
):
estimated_read_duration = models.DurationField(null=True, blank=True)
parent_page_types = [
'core.CuratedListPage', # TEMPORARY: remove after topics refactor migration has run
Expand Down Expand Up @@ -1094,6 +1098,7 @@ def form_valid(self, form, request):
return JsonResponse({'pk': hcsat.pk})
return HttpResponseRedirect(self.get_success_url(request))

@method_decorator(csrf_protect, name='post')
def serve(self, request, *args, **kwargs):
self.handle_page_view(request)

Expand Down
63 changes: 63 additions & 0 deletions core/templatetags/clear_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from django import template
from django.core.cache import cache
from urllib.parse import quote
from hashlib import md5

register = template.Library()


class ClearCacheNode(template.Node):
def __init__(self, fragment_name, vary_on):
self.fragment_name = fragment_name
self.vary_on = vary_on

def render(self, context):
# Build a unicode key for this fragment and all vary-on's.
args = md5(
u':'.join([quote(template.Variable('request').resolve(var, context)) for var in self.vary_on]).encode(
'utf-8'
)
)
from django.core.cache.utils import make_template_fragment_key

cache_key = 'template.cache.%s.%s' % (self.fragment_name, args.hexdigest())
print('clear-cache key', cache_key)
from django.core.cache import cache

key = make_template_fragment_key('hcsat')

result2 = cache.delete(key)
result1 = cache.delete_many(keys=cache.keys('*hcsat*'))
result = cache.delete(cache_key)
print('result', result)
print('result1', result1)
print('result2', result2)
return ''


@register.simple_tag
def clear_cache(parser, token):
"""
This will clear the cache for a template fragment

Usage::

{% load clearcache %}
{% clearcache [fragment_name] %}

This tag also supports varying by a list of arguments::

{% load clearcache %}
{% clearcache [fragment_name] [var1] [var2] .. %}

The set of arguments must be the same as the original cache tag (except for expire_time).
"""
try:
tokens = token.split_contents()
print('tokens', tokens)
except ValueError:
raise template.TemplateSyntaxError('%r tag requires at least one argument' % token.contents.split()[0])
return ClearCacheNode(tokens[1], tokens[2:])


register.tag('clear_cache', clear_cache)
1 change: 1 addition & 0 deletions core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def anonymous_user_required(function):
name='campaign-site',
),
path('api/signed-url/', views.SignedURLView.as_view(), name='signed-url'),
path('api/getcsrftoken/', views.CSRFView.as_view(), name='csrftoken'),
# WHEN ADDING TO THIS LIST CONSIDER WHETHER YOU SHOULD ALSO ADD THE URL NAME
# TO core.views.StaticViewSitemap
]
Expand Down
16 changes: 16 additions & 0 deletions core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
from domestic.models import DomesticDashboard, TopicLandingPage
from export_academy.models import Event
from sso.views import SSOBusinessUserLogoutView
from django.views.decorators.cache import never_cache
from django.middleware.csrf import get_token
from rest_framework.views import APIView

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -966,3 +969,16 @@ def get_context_data(self, **kwargs):
ukea_events=ukea_events,
market_guide=market_guide,
)


@method_decorator(never_cache, name='dispatch')
class CSRFView(APIView):
permission_classes = []
authentication_classes = []

def _get_token(self, request):
token = get_token(request)
return JsonResponse(status=200, data={'csrftoken': token})

def dispatch(self, request, *args, **kwargs):
return self._get_token(request)
13 changes: 12 additions & 1 deletion domestic/static/javascript/hcsat-feedback-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,21 @@ class CsatFormHandler {
this.resetForm();
}
try {
const oldCsrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value
const csrfTokenFetch = await fetch('/api/getcsrftoken/', {
method: 'GET',
headers: {
'cache_control': 'no-cache',
}
})
const csrfTokenJson = await csrfTokenFetch.json()
const csrfToken = csrfTokenJson.csrftoken
console.log('csrfToken:',csrfToken)
const response = await fetch(`${url}?js_enabled=True`, {
method: 'POST',
headers: {
'X-CSRFToken': formData.get('csrfmiddlewaretoken'),
'cache_control': 'no-cache',
'X-CSRFToken': oldCsrfToken,
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
Expand Down
8 changes: 8 additions & 0 deletions learn/templates/learn/detail_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ <h3 class="govuk-heading-s">Explore the topic</h3>
{% endif %}
<div class="govuk-!-padding-0">{% include 'learn/promo.html' with bg_class='great-bg-light-blue' %}</div>
{% block body_inline_feedback %}{% endblock %}
{% load clear_cache %}
{% clear_cache hcsat %}
{% load cache %}
{% cache 500 hcsat %}
{% block hcsat %}
{% if not csat_complete %}
<section id="hcsat_section"
class="govuk-!-padding-bottom-6 great-bg-white clearfix govuk-!-margin-top-0 great-border-thin-top-lighter-blue">
Expand All @@ -103,6 +108,9 @@ <h3 class="govuk-heading-s">Explore the topic</h3>
</section>
{% endif %}
{% endblock %}
{% endcache %}
{% clear_cache hcsat %}
{% endblock %}
{% block body_js %}
{{ block.super }}
<script src="{% static 'javascript/govuk.js' %}"></script>
Expand Down