Browse Source

Upload blank avatar image in admin (#1240)

* Add blank avatar setting image

* Make blank avatar configurable

* Add tests for blank avatar image validation
Rafał Pitoń 6 years ago
parent
commit
5a972770aa

+ 2 - 2
misago/conf/admin/forms/analytics.py

@@ -45,13 +45,13 @@ class ChangeAnalyticsSettingsForm(ChangeSettingsForm):
             return None
 
         if upload.content_type != "text/html":
-            raise forms.ValidationError(_("Uploaded file type is not HTML."))
+            raise forms.ValidationError(_("Submitted file type is not HTML."))
 
         file_content = upload.read().decode("utf-8")
         content_match = GOOGLE_SITE_VERIFICATION.match(file_content)
         if not content_match:
             raise forms.ValidationError(
-                _("Uploaded file did not contain a verification code.")
+                _("Submitted file doesn't contain a verification code.")
             )
 
         return content_match.group(1)

+ 3 - 5
misago/conf/admin/forms/general.py

@@ -47,7 +47,7 @@ class ChangeGeneralSettingsForm(ChangeSettingsForm):
         help_text=_("Image that will displayed in forum navbar."),
         required=False,
     )
-    logo_delete = forms.BooleanField(label=_("Delete current logo"), required=False)
+    logo_delete = forms.BooleanField(label=_("Delete logo image"), required=False)
     logo_small = forms.ImageField(
         label=_("Small logo"),
         help_text=_(
@@ -57,7 +57,7 @@ class ChangeGeneralSettingsForm(ChangeSettingsForm):
         required=False,
     )
     logo_small_delete = forms.BooleanField(
-        label=_("Delete current small logo"), required=False
+        label=_("Delete small logo image"), required=False
     )
     logo_text = forms.CharField(
         label=_("Text"),
@@ -78,9 +78,7 @@ class ChangeGeneralSettingsForm(ChangeSettingsForm):
         ),
         required=False,
     )
-    og_image_delete = forms.BooleanField(
-        label=_("Delete current image"), required=False
-    )
+    og_image_delete = forms.BooleanField(label=_("Delete image"), required=False)
     og_image_avatar_on_profile = YesNoSwitch(
         label=_("Replace image with avatar on user profiles")
     )

+ 34 - 0
misago/conf/admin/forms/users.py

@@ -2,6 +2,7 @@ from django import forms
 from django.utils.translation import gettext_lazy as _
 
 from ....admin.forms import YesNoSwitch
+from ... import settings
 from .base import ChangeSettingsForm
 
 
@@ -12,6 +13,7 @@ class ChangeUsersSettingsForm(ChangeSettingsForm):
         "avatar_upload_limit",
         "default_avatar",
         "default_gravatar_fallback",
+        "blank_avatar",
         "signature_length_max",
         "subscribe_reply",
         "subscribe_start",
@@ -35,6 +37,7 @@ class ChangeUsersSettingsForm(ChangeSettingsForm):
     username_length_max = forms.IntegerField(
         label=_("Maximum allowed username length"), min_value=2, max_value=20
     )
+
     allow_custom_avatars = YesNoSwitch(
         label=_("Allow custom avatar uploads"),
         help_text=_(
@@ -68,9 +71,23 @@ class ChangeUsersSettingsForm(ChangeSettingsForm):
         ],
         widget=forms.RadioSelect(),
     )
+    blank_avatar = forms.ImageField(
+        label=_("Blank avatar"),
+        help_text=_(
+            "Blank avatar is displayed in the interface when user's avatar is not "
+            "available: when user was deleted or is guest. Uploaded image should be "
+            "a square"
+        ),
+        required=False,
+    )
+    blank_avatar_delete = forms.BooleanField(
+        label=_("Delete custom blank avatar"), required=False
+    )
+
     signature_length_max = forms.IntegerField(
         label=_("Maximum allowed signature length"), min_value=10, max_value=5000
     )
+
     subscribe_start = forms.ChoiceField(
         label=_("Started threads"),
         choices=[
@@ -95,3 +112,20 @@ class ChangeUsersSettingsForm(ChangeSettingsForm):
         ],
         widget=forms.RadioSelect(),
     )
+
+    def clean_blank_avatar(self):
+        upload = self.cleaned_data.get("blank_avatar")
+        if not upload or upload == self.initial.get("blank_avatar"):
+            return None
+
+        if upload.image.width != upload.image.height:
+            raise forms.ValidationError(_("Submitted image is not a square."))
+
+        min_size = max(settings.MISAGO_AVATARS_SIZES)
+        if upload.image.width < min_size:
+            raise forms.ValidationError(
+                _("Submitted image's edge should be at least %(size)s pixels long.")
+                % {"size": min_size}
+            )
+
+        return upload

+ 0 - 2
misago/conf/admin/tests/test_google_site_verification.py

@@ -1,5 +1,3 @@
-from io import BytesIO
-
 import pytest
 
 from django.core.files.uploadedfile import SimpleUploadedFile

+ 2 - 2
misago/conf/context_processors.py

@@ -10,7 +10,7 @@ BLANK_AVATAR_URL = static(settings.MISAGO_BLANK_AVATAR)
 
 def conf(request):
     return {
-        "BLANK_AVATAR_URL": BLANK_AVATAR_URL,
+        "BLANK_AVATAR_URL": request.settings.blank_avatar or BLANK_AVATAR_URL,
         "DEBUG": settings.DEBUG,
         "LANGUAGE_CODE_SHORT": get_language()[:2],
         "LOGIN_REDIRECT_URL": settings.LOGIN_REDIRECT_URL,
@@ -50,7 +50,7 @@ def preload_settings_json(request):
 
     request.frontend_context.update(
         {
-            "BLANK_AVATAR_URL": BLANK_AVATAR_URL,
+            "BLANK_AVATAR_URL": request.settings.blank_avatar or BLANK_AVATAR_URL,
             "CSRF_COOKIE_NAME": settings.CSRF_COOKIE_NAME,
             "ENABLE_DELETE_OWN_ACCOUNT": settings.MISAGO_ENABLE_DELETE_OWN_ACCOUNT,
             "ENABLE_DOWNLOAD_OWN_DATA": settings.MISAGO_ENABLE_DOWNLOAD_OWN_DATA,

+ 1 - 1
misago/conf/defaults.py

@@ -219,7 +219,7 @@ MISAGO_AVATARS_SIZES = [400, 200, 150, 100, 64, 50, 30]
 
 # Path to blank avatar image used for guests and removed users.
 
-MISAGO_BLANK_AVATAR = "blank-avatar.png"
+MISAGO_BLANK_AVATAR = "misago/img/blank-avatar.png"
 
 
 # Threads lists pagination settings

+ 1 - 0
misago/conf/migrations/0004_create_settings.py

@@ -14,6 +14,7 @@ default_settings = [
         "dry_value": 1536,
         "is_public": True,
     },
+    {"setting": "blank_avatar", "python_type": "image"},
     {"setting": "captcha_type", "dry_value": "no", "is_public": True},
     {"setting": "default_avatar", "dry_value": "gravatar"},
     {"setting": "default_gravatar_fallback", "dry_value": "dynamic"},

BIN
misago/static/blank-avatar.png


+ 5 - 0
misago/templates/misago/admin/conf/users_settings.html

@@ -21,6 +21,11 @@
     {% form_row form.avatar_upload_limit %}
     {% form_row form.default_avatar %}
     {% form_row form.default_gravatar_fallback %}
+    {% with form.blank_avatar_delete as delete_field %}
+      {% with form_settings.blank_avatar as setting %}
+        {% form_image_row form.blank_avatar delete_field=delete_field size=setting.image_size dimensions=setting.image_dimensions %}
+      {% endwith %}
+    {% endwith %}
 
   </fieldset>
 </div>

+ 3 - 1
misago/users/views/avatarserver.py

@@ -4,6 +4,8 @@ from django.templatetags.static import static
 
 from ...conf import settings
 
+BLANK_AVATAR_URL = static(settings.MISAGO_BLANK_AVATAR)
+
 User = get_user_model()
 
 
@@ -23,4 +25,4 @@ def user_avatar(request, pk, size):
 
 
 def blank_avatar(request):
-    return redirect(static(settings.MISAGO_BLANK_AVATAR))
+    return redirect(request.settings.blank_avatar or BLANK_AVATAR_URL)