Skip to content
Snippets Groups Projects
Commit 1053c9b5 authored by Erwan Rouchet's avatar Erwan Rouchet Committed by Bastien Abadie
Browse files

Handle an edge case in the HTML rendering for ListCorpusMLClasses

parent f91b1143
No related branches found
No related tags found
1 merge request!1823Handle an edge case in the HTML rendering for ListCorpusMLClasses
......@@ -327,13 +327,40 @@ class CorpusMLClassList(CorpusACLMixin, ListCreateAPIView):
search_fields = ['name']
permission_classes = (IsVerifiedOrReadOnly, )
@cached_property
def corpus(self):
role = Role.Guest
if self.request.method == 'POST':
role = Role.Contributor
return self.get_corpus(self.kwargs['pk'], role=role)
def check_permissions(self, *args, **kwargs):
"""
When a user only has a guest access to the corpus and tries to access this endpoint with a browser,
DRF's HTML renderer will try to get a serializer instance to build an HTML form from it.
To do so, it goes through the endpoint again with a request that has been faked to look like a POST,
even though the original request was GET. `get_serializer_context` tries to get the corpus to put in
the serializer, but `CorpusACLMixin.get_corpus` raises a PermissionDenied because we do not have
contributor access. This error normally causes a HTTP 403, but here the renderer does not handle it
and it turns into HTTP 500.
To avoid this error, the corpus is moved to a cached property that gets evaluated before the renderer
tries to render the response. That way, a corpus with only guest access is available and no error
occurs when a fake POST request is used. When an actual POST is made, get_corpus will cause its error
before the renderer renders a response; the error gets caught and sent to the renderer to show a
proper HTTP 403.
"""
super().check_permissions(*args, **kwargs)
self.corpus
def get_queryset(self):
return MLClass.objects.filter(corpus=self.get_corpus(self.kwargs['pk'])).using('default').order_by('name', 'id')
return MLClass.objects.filter(corpus=self.corpus).using('default').order_by('name', 'id')
def get_serializer_context(self):
context = super().get_serializer_context()
if self.request and self.request.method == 'POST':
context['corpus_id'] = self.get_corpus(self.kwargs['pk'], role=Role.Contributor)
if self.request.method == 'POST':
context['corpus_id'] = self.corpus
return context
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment