diff --git a/config/settings/dev.py b/config/settings/dev.py index 3bbe04a92..0700a2237 100644 --- a/config/settings/dev.py +++ b/config/settings/dev.py @@ -61,3 +61,4 @@ MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/" # noqa: F405 CSP_DEFAULT_SRC = ("*",) +CSP_IMG_SRC += ("localhost:9000",) # noqa: F405 diff --git a/lacommunaute/forum/factories.py b/lacommunaute/forum/factories.py index 4b1428622..eaa77bad4 100644 --- a/lacommunaute/forum/factories.py +++ b/lacommunaute/forum/factories.py @@ -17,6 +17,9 @@ class ForumFactory(BaseForumFactory): class Meta: skip_postgeneration_save = True + class Params: + with_image = factory.Trait(image=factory.django.ImageField(filename="banner.jpg")) + @factory.post_generation def with_public_perms(self, create, extracted, **kwargs): if not create or not extracted: @@ -41,4 +44,4 @@ def with_child(self, create, extracted, **kwargs): if not create or not extracted: return - ForumFactory(parent=self, with_public_perms=True) + ForumFactory(parent=self, with_public_perms=True, with_image=True) diff --git a/lacommunaute/forum/migrations/0013_alter_forum_image.py b/lacommunaute/forum/migrations/0013_alter_forum_image.py new file mode 100644 index 000000000..0991a4959 --- /dev/null +++ b/lacommunaute/forum/migrations/0013_alter_forum_image.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.6 on 2024-05-21 14:55 + +import storages.backends.s3 +from django.conf import settings +from django.db import migrations, models + +import lacommunaute.forum.models + + +class Migration(migrations.Migration): + dependencies = [ + ("forum", "0012_forum_short_description_alter_forum_kind"), + ] + + operations = [ + migrations.AlterField( + model_name="forum", + name="image", + field=models.ImageField( + storage=storages.backends.s3.S3Storage( + bucket_name=settings.AWS_STORAGE_BUCKET_NAME, file_overwrite=False + ), + upload_to="", + validators=[lacommunaute.forum.models.validate_image_size], + ), + ), + ] diff --git a/lacommunaute/forum/models.py b/lacommunaute/forum/models.py index 9b591ac5c..1e5abedde 100644 --- a/lacommunaute/forum/models.py +++ b/lacommunaute/forum/models.py @@ -1,15 +1,18 @@ import uuid +from django.conf import settings from django.contrib.auth.models import Group from django.contrib.contenttypes.fields import GenericRelation from django.db import models from django.urls import reverse from django.utils.functional import cached_property from machina.apps.forum.abstract_models import AbstractForum +from storages.backends.s3boto3 import S3Boto3Storage from lacommunaute.forum.enums import Kind as Forum_Kind from lacommunaute.forum_conversation.models import Topic from lacommunaute.forum_upvote.models import UpVote +from lacommunaute.utils.validators import validate_image_size class ForumQuerySet(models.QuerySet): @@ -28,6 +31,10 @@ class Forum(AbstractForum): short_description = models.CharField( max_length=400, blank=True, null=True, verbose_name="Description courte (SEO)" ) + image = models.ImageField( + storage=S3Boto3Storage(bucket_name=settings.AWS_STORAGE_BUCKET_NAME, file_overwrite=False), + validators=[validate_image_size], + ) upvotes = GenericRelation(UpVote, related_query_name="forum") diff --git a/lacommunaute/forum/tests/test_categoryforum_listview.py b/lacommunaute/forum/tests/test_categoryforum_listview.py index aa491c7d4..82e60e469 100644 --- a/lacommunaute/forum/tests/test_categoryforum_listview.py +++ b/lacommunaute/forum/tests/test_categoryforum_listview.py @@ -3,7 +3,7 @@ from pytest_django.asserts import assertContains, assertNotContains from lacommunaute.forum.enums import Kind as ForumKind -from lacommunaute.forum.factories import ForumFactory +from lacommunaute.forum.factories import CategoryForumFactory, ForumFactory from lacommunaute.forum.models import Forum from lacommunaute.users.factories import UserFactory @@ -45,3 +45,12 @@ def test_display_create_category_button(client, db): user.save() response = client.get(url) assertContains(response, reverse("forum_extension:create_category"), status_code=200) + + +def test_display_banners(client, db): + forum = CategoryForumFactory(with_child=True, with_public_perms=True) + ForumFactory(parent=forum, with_public_perms=True, with_image=True) + url = reverse("forum_extension:forum", kwargs={"pk": forum.pk, "slug": forum.slug}) + response = client.get(url) + for child in forum.get_children(): + assertContains(response, child.image.url.split("=")[0]) diff --git a/lacommunaute/forum/tests/tests_model.py b/lacommunaute/forum/tests/tests_model.py index 1c887068f..d683a3026 100644 --- a/lacommunaute/forum/tests/tests_model.py +++ b/lacommunaute/forum/tests/tests_model.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.db import IntegrityError from django.test import TestCase @@ -57,3 +58,14 @@ def test_upvotes_count(self): self.assertEqual(forum.upvotes_count(), 0) forum.upvotes.create(voter=UserFactory()) self.assertEqual(forum.upvotes_count(), 1) + + def test_image_is_imagefield(self): + forum = ForumFactory() + self.assertEqual(forum.image.field.__class__.__name__, "ImageField") + + def test_image_url(self): + forum = ForumFactory(image="test.jpg") + self.assertEqual( + forum.image.url.split("?")[0], f"{settings.MEDIA_URL}{settings.AWS_STORAGE_BUCKET_NAME}/{forum.image.name}" + ) + self.assertIn("AWSAccessKeyId=", forum.image.url) diff --git a/lacommunaute/forum/tests/tests_views.py b/lacommunaute/forum/tests/tests_views.py index a0590af0d..ac854fb54 100644 --- a/lacommunaute/forum/tests/tests_views.py +++ b/lacommunaute/forum/tests/tests_views.py @@ -421,3 +421,9 @@ def test_filtered_queryset_on_tag(self): ) self.assertContains(response, topic.subject) self.assertNotContains(response, self.topic.subject) + + def test_banner_display_on_subcategory_forum(self): + category_forum = CategoryForumFactory(with_child=True, with_public_perms=True) + forum = category_forum.get_children().first() + response = self.client.get(reverse("forum_extension:forum", kwargs={"pk": forum.pk, "slug": forum.slug})) + self.assertContains(response, forum.image.url.split("=")[0]) diff --git a/lacommunaute/forum_file/models.py b/lacommunaute/forum_file/models.py index f443141b9..ec8ffb205 100644 --- a/lacommunaute/forum_file/models.py +++ b/lacommunaute/forum_file/models.py @@ -1,17 +1,10 @@ from django.conf import settings -from django.core.exceptions import ValidationError from django.db import models from machina.models.abstract_models import DatedModel from storages.backends.s3boto3 import S3Boto3Storage from lacommunaute.users.models import User - - -def validate_image_size(value): - max_size = 1024 * 1024 * 8 - - if value.size > max_size: - raise ValidationError("L'image ne doit pas dépasser 1 Mo") +from lacommunaute.utils.validators import validate_image_size class PublicFile(DatedModel): diff --git a/lacommunaute/forum_file/tests/test_models.py b/lacommunaute/forum_file/tests/test_models.py index e8e26a36b..11c8921f2 100644 --- a/lacommunaute/forum_file/tests/test_models.py +++ b/lacommunaute/forum_file/tests/test_models.py @@ -32,11 +32,5 @@ def test_get_file_url(db, public_file): assert public_file.get_file_url() == expected_file_url -def test_size_validator(db, public_file): - with pytest.raises(Exception): - public_file.file.size = 1024 * 1024 * 8 + 1 - public_file.save() - - def test_file_field_is_imagefield(db): assert isinstance(PublicFile._meta.get_field("file"), ImageField) diff --git a/lacommunaute/templates/forum/forum_detail.html b/lacommunaute/templates/forum/forum_detail.html index 96d310a5c..b2aeb36d0 100644 --- a/lacommunaute/templates/forum/forum_detail.html +++ b/lacommunaute/templates/forum/forum_detail.html @@ -41,7 +41,8 @@
{{ node.obj.name }}
- {% if node.obj.short_description %}