From 2a9fc9861e25051adb7a8726fece0bc82809f3c4 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 8 Apr 2020 23:36:56 +0200 Subject: [PATCH 2/2] views: block upload when MAX_DOCUMENTS_PER_USER limit is reached (#41491) --- fargo/fargo/views.py | 41 +++++++++++++++++++++++++-------- fargo/templates/fargo/home.html | 11 ++++++++- tests/test_public.py | 21 +++++++++++++++++ 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/fargo/fargo/views.py b/fargo/fargo/views.py index c14038f..b9912c1 100644 --- a/fargo/fargo/views.py +++ b/fargo/fargo/views.py @@ -34,6 +34,7 @@ from django.contrib.auth import views as auth_views from django.utils.http import quote from django.utils.translation import ugettext as _ from django.utils.decorators import method_decorator +from django.utils.functional import cached_property from django.conf import settings from django_tables2 import SingleTableMixin @@ -53,7 +54,22 @@ class Logger(object): self.logger = logging.getLogger(__name__) -class CommonUpload(Logger, CreateView): +class Documents(object): + def get_queryset(self): + return models.UserDocument.objects \ + .filter(user=self.request.user) \ + .select_related('document', 'user') + + @cached_property + def count(self): + return self.get_queryset().filter(origin__isnull=True).count() + + @cached_property + def full(self): + return self.count >= settings.FARGO_MAX_DOCUMENTS_PER_USER + + +class CommonUpload(Logger, Documents, CreateView): form_class = forms.UploadForm model = models.UserDocument template_name = 'fargo/upload.html' @@ -77,20 +93,18 @@ class Upload(CommonUpload): homepage = reverse('home') return self.request.GET.get(REDIRECT_FIELD_NAME, homepage) + def dispatch(self, request, *args, **kwargs): + if self.full: + return HttpResponseRedirect(self.get_success_url()) + return super(Upload, self).dispatch(request, *args, **kwargs) + def post(self, request, *args, **kwargs): if 'cancel' in request.POST: return HttpResponseRedirect(self.get_success_url()) return super(Upload, self).post(request, *args, **kwargs) -class Documents(object): - def get_queryset(self): - return models.UserDocument.objects \ - .filter(user=self.request.user) \ - .select_related('document', 'user') - - -class Homepage(Documents, SingleTableMixin, CommonUpload): +class Homepage(SingleTableMixin, CommonUpload): '''Show documents of users, eventually paginate and sort them.''' template_name = 'fargo/home.html' form_class = forms.UploadForm @@ -108,8 +122,17 @@ class Homepage(Documents, SingleTableMixin, CommonUpload): max_size = ctx['max_portfolio_size'] = settings.FARGO_MAX_DOCUMENT_BOX_SIZE ctx['occupancy_ratio'] = float(occupancy) / max_size ctx['occupancy_ratio_percent'] = float(occupancy) * 100.0 / max_size + ctx['max_documents_per_user'] = settings.FARGO_MAX_DOCUMENTS_PER_USER + ctx['full'] = self.full + ctx['count'] = self.count return ctx + def post(self, request, *args, **kwargs): + if self.full: + return HttpResponseRedirect('') + return super(CommonUpload, self).post(request, *args, **kwargs) + + class PickView(object): def dispatch(self, request, *args, **kwargs): diff --git a/fargo/templates/fargo/home.html b/fargo/templates/fargo/home.html index 8fa78b3..963489c 100644 --- a/fargo/templates/fargo/home.html +++ b/fargo/templates/fargo/home.html @@ -51,7 +51,15 @@ {% if not table.page %} {% endif %} - + + {% if full %} +
+ {% blocktrans trimmed %} + The limit of {{ max_documents_per_user }} documents per user is reached. + You cannot add more documents anymore. + {% endblocktrans %} +
+ {% else %}
{% csrf_token %} {{ form.non_field_errors }} @@ -70,6 +78,7 @@
+ {% endif %} {% endblock %} diff --git a/tests/test_public.py b/tests/test_public.py index b2cc3d2..700a6f7 100644 --- a/tests/test_public.py +++ b/tests/test_public.py @@ -129,3 +129,24 @@ def test_delete(app, john_doe, jane_doe): resp = app.get('/') assert 'monfichier.txt' not in resp.text resp = app.get(delete_url, status=404) + + +def test_max_documents_per_user(app, private_settings, john_doe): + private_settings.FARGO_MAX_DOCUMENTS_PER_USER = 1 + login(app, user=john_doe) + response1 = app.get('/') + assert len(response1.forms) == 2 + form = response1.form + form['content'] = Upload('monfichier.pdf', b'coin', 'application/pdf') + response2 = form.submit().follow() + assert 'monfichier.pdf' in response2.text + assert len(response2.forms) == 0 + + response2 = form.submit().follow() + assert 'monfichier.pdf' in response2.text + assert len(response2.forms) == 0 + + assert UserDocument.objects.count() == 1 + + response = app.get('/upload/') + assert response.location == '/' -- 2.24.0