From 0ad6c7543ea1fb9795b2cc23338e41b13cf5138c Mon Sep 17 00:00:00 2001 From: Guillaume Bertholon Date: Wed, 30 Dec 2020 00:31:58 +0100 Subject: [PATCH] Limit upload file sizes --- gestiojeux/settings_base.py | 2 ++ inventory/migrations/0001_initial.py | 11 ++++++----- inventory/models.py | 24 ++++++++++++++++++------ website/validators.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 website/validators.py diff --git a/gestiojeux/settings_base.py b/gestiojeux/settings_base.py index 242a7e6..d200c1b 100644 --- a/gestiojeux/settings_base.py +++ b/gestiojeux/settings_base.py @@ -102,6 +102,8 @@ MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS = { } } +MARKDOWNX_UPLOAD_MAX_SIZE = 1024 * 1024 # Only 1 MiB for markdown uploads + # Update the search database on save HAYSTACK_SIGNAL_PROCESSOR = "haystack.signals.RealtimeSignalProcessor" diff --git a/inventory/migrations/0001_initial.py b/inventory/migrations/0001_initial.py index c622fdb..eaab918 100644 --- a/inventory/migrations/0001_initial.py +++ b/inventory/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# Generated by Django 3.1.2 on 2020-12-27 17:01 +# Generated by Django 3.1.2 on 2020-12-29 23:21 import autoslug.fields from django.conf import settings from django.db import migrations, models import django.db.models.deletion +import website.validators class Migration(migrations.Migration): @@ -19,7 +20,7 @@ class Migration(migrations.Migration): name='Category', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='nom')), + ('name', models.CharField(max_length=256, unique=True, verbose_name='nom')), ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True)), ], options={ @@ -31,7 +32,7 @@ class Migration(migrations.Migration): name='Game', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=256, verbose_name='titre')), + ('title', models.CharField(max_length=256, unique=True, verbose_name='titre du jeu')), ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='title', unique=True)), ('nb_player_min', models.PositiveSmallIntegerField(verbose_name='nombre de joueur·se·s minimum')), ('nb_player_max', models.PositiveSmallIntegerField(verbose_name='nombre de joueur·se·s maximum')), @@ -41,7 +42,7 @@ class Migration(migrations.Migration): ('illustrator', models.CharField(blank=True, max_length=256, verbose_name='illustrateur·trice')), ('editor', models.CharField(blank=True, max_length=256, verbose_name='éditeur')), ('description', models.TextField(blank=True, verbose_name='description')), - ('image', models.ImageField(blank=True, upload_to='game_img/', verbose_name='image')), + ('image', models.ImageField(blank=True, help_text="L'image doit peser 512 Kio au maximum", upload_to='game_img/', validators=[website.validators.MaxFileSizeValidator(512)], verbose_name='image')), ('missing_elements', models.TextField(blank=True, verbose_name='pièces manquantes')), ('category', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='inventory.category', verbose_name='catégorie')), ], @@ -55,7 +56,7 @@ class Migration(migrations.Migration): name='Tag', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='nom')), + ('name', models.CharField(max_length=256, unique=True, verbose_name='nom')), ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True)), ], options={ diff --git a/inventory/models.py b/inventory/models.py index 06bea86..75b04a7 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -2,11 +2,12 @@ from django.db import models from django.urls import reverse from django.core.exceptions import ValidationError from autoslug import AutoSlugField +from website.validators import MaxFileSizeValidator from comments.models import AbstractComment class Category(models.Model): - name = models.CharField(max_length=256, verbose_name="nom") + name = models.CharField(max_length=256, verbose_name="nom", unique=True) slug = AutoSlugField(populate_from="name", unique=True) class Meta: @@ -21,7 +22,7 @@ class Category(models.Model): class Tag(models.Model): - name = models.CharField(max_length=256, verbose_name="nom") + name = models.CharField(max_length=256, verbose_name="nom", unique=True) slug = AutoSlugField(populate_from="name", unique=True) class Meta: @@ -35,8 +36,9 @@ class Tag(models.Model): class Game(models.Model): - title = models.CharField(verbose_name="titre", max_length=256) + title = models.CharField(verbose_name="titre du jeu", max_length=256, unique=True) slug = AutoSlugField(populate_from="title", unique=True) + nb_player_min = models.PositiveSmallIntegerField( verbose_name="nombre de joueur·se·s minimum" ) @@ -52,6 +54,7 @@ class Game(models.Model): duration = models.CharField( max_length=256, blank=True, verbose_name="durée de partie" ) + game_designer = models.CharField( max_length=256, blank=True, verbose_name="game designer" ) @@ -59,12 +62,21 @@ class Game(models.Model): max_length=256, blank=True, verbose_name="illustrateur·trice" ) editor = models.CharField(max_length=256, blank=True, verbose_name="éditeur") - description = models.TextField(blank=True, verbose_name="description") + category = models.ForeignKey( Category, on_delete=models.RESTRICT, verbose_name="catégorie" ) tags = models.ManyToManyField(Tag, blank=True, verbose_name="tags") - image = models.ImageField(upload_to="game_img/", blank=True, verbose_name="image") + + description = models.TextField(blank=True, verbose_name="description") + image = models.ImageField( + upload_to="game_img/", + blank=True, + verbose_name="image", + help_text="L'image doit peser 512 Kio au maximum", + validators=[MaxFileSizeValidator(512)], + ) + missing_elements = models.TextField(blank=True, verbose_name="pièces manquantes") class Meta: @@ -79,7 +91,7 @@ class Game(models.Model): if self.nb_player_min > self.nb_player_max: raise ValidationError( { - "nb_player_max": "Le nombre de joueur·se·s maximum doit être supérieur au nombre de joueurs minimum" + "nb_player_max": "Le nombre de joueur·se·s maximum doit être supérieur au nombre de joueur·se·s minimum" } ) diff --git a/website/validators.py b/website/validators.py new file mode 100644 index 0000000..2fd9b4f --- /dev/null +++ b/website/validators.py @@ -0,0 +1,28 @@ +from django.core.exceptions import ValidationError +from django.utils.deconstruct import deconstructible + + +@deconstructible +class MaxFileSizeValidator: + """ + Reject all the files stored in a FileField (or ImageField) that are too heavy. + The size limit is given in Kio. + """ + + def __init__(self, size_limit): + self.size_limit = size_limit + + def __call__(self, value): + if value.size > self.size_limit * 1024: + raise ValidationError( + "La taille du fichier doit être inférieure à {} Kio".format( + self.size_limit + ), + code="file_too_big", + ) + + def __eq__(self, other): + return ( + isinstance(other, MaxFileSizeValidator) + and self.size_limit == other.size_limit + )