From ff566b79dc36103a740c4694d1d983a2f6ed0581 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 17 Sep 2019 11:03:32 +0200 Subject: [PATCH] See #872: banner setting --- .../instance/dynamic_preferences_registry.py | 26 ++++++++++++ api/funkwhale_api/instance/nodeinfo.py | 4 ++ api/tests/instance/test_nodeinfo.py | 6 ++- api/tests/instance/test_preferences.py | 10 +++++ front/src/components/admin/SettingsGroup.vue | 41 ++++++++++++++++++- front/src/views/admin/Settings.vue | 1 + 6 files changed, 86 insertions(+), 2 deletions(-) diff --git a/api/funkwhale_api/instance/dynamic_preferences_registry.py b/api/funkwhale_api/instance/dynamic_preferences_registry.py index 1e6f3147c..ed2cef527 100644 --- a/api/funkwhale_api/instance/dynamic_preferences_registry.py +++ b/api/funkwhale_api/instance/dynamic_preferences_registry.py @@ -1,4 +1,6 @@ from django.forms import widgets +from django.core.validators import FileExtensionValidator + from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry @@ -129,3 +131,27 @@ class CustomCSS(types.StringPreference): ) widget = widgets.Textarea field_kwargs = {"required": False} + + +class ImageWidget(widgets.ClearableFileInput): + pass + + +class ImagePreference(types.FilePreference): + widget = ImageWidget + field_kwargs = { + "validators": [ + FileExtensionValidator(allowed_extensions=["png", "jpg", "jpeg", "webp"]) + ] + } + + +@global_preferences_registry.register +class Banner(ImagePreference): + show_in_api = True + section = instance + name = "banner" + verbose_name = "Banner image" + default = None + help_text = "This banner will be displayed on your pod's landing and about page. At least 600x100px recommended." + field_kwargs = {"required": False} diff --git a/api/funkwhale_api/instance/nodeinfo.py b/api/funkwhale_api/instance/nodeinfo.py index 1d401fbca..dc495108e 100644 --- a/api/funkwhale_api/instance/nodeinfo.py +++ b/api/funkwhale_api/instance/nodeinfo.py @@ -3,6 +3,7 @@ import memoize.djangocache import funkwhale_api from funkwhale_api.common import preferences from funkwhale_api.federation import actors, models as federation_models +from funkwhale_api.federation import utils as federation_utils from funkwhale_api.moderation import models as moderation_models from funkwhale_api.music import utils as music_utils @@ -17,6 +18,7 @@ def get(): share_stats = all_preferences.get("instance__nodeinfo_stats_enabled") allow_list_enabled = all_preferences.get("moderation__allow_list_enabled") allow_list_public = all_preferences.get("moderation__allow_list_public") + banner = all_preferences.get("instance__banner") unauthenticated_report_types = all_preferences.get( "moderation__unauthenticated_report_types" ) @@ -42,6 +44,7 @@ def get(): "longDescription": all_preferences.get("instance__long_description"), "terms": all_preferences.get("instance__terms"), "nodeName": all_preferences.get("instance__name"), + "banner": federation_utils.full_url(banner.url) if banner else None, "library": { "federationEnabled": all_preferences.get("federation__enabled"), "federationNeedsApproval": all_preferences.get( @@ -59,6 +62,7 @@ def get(): ], }, } + if share_stats: getter = memo(lambda: stats.get(), max_age=600) statistics = getter() diff --git a/api/tests/instance/test_nodeinfo.py b/api/tests/instance/test_nodeinfo.py index f85f34b25..d30873ec2 100644 --- a/api/tests/instance/test_nodeinfo.py +++ b/api/tests/instance/test_nodeinfo.py @@ -3,10 +3,12 @@ import pytest import funkwhale_api from funkwhale_api.instance import nodeinfo from funkwhale_api.federation import actors +from funkwhale_api.federation import utils as federation_utils from funkwhale_api.music import utils as music_utils -def test_nodeinfo_dump(preferences, mocker): +def test_nodeinfo_dump(preferences, mocker, avatar): + preferences["instance__banner"] = avatar preferences["instance__nodeinfo_stats_enabled"] = True preferences["moderation__unauthenticated_report_types"] = [ "takedown_request", @@ -39,6 +41,7 @@ def test_nodeinfo_dump(preferences, mocker): "longDescription": preferences["instance__long_description"], "nodeName": preferences["instance__name"], "terms": preferences["instance__terms"], + "banner": federation_utils.full_url(preferences["instance__banner"].url), "library": { "federationEnabled": preferences["federation__enabled"], "federationNeedsApproval": preferences[ @@ -107,6 +110,7 @@ def test_nodeinfo_dump_stats_disabled(preferences, mocker): "longDescription": preferences["instance__long_description"], "nodeName": preferences["instance__name"], "terms": preferences["instance__terms"], + "banner": None, "library": { "federationEnabled": preferences["federation__enabled"], "federationNeedsApproval": preferences[ diff --git a/api/tests/instance/test_preferences.py b/api/tests/instance/test_preferences.py index b465be9d3..06d1024fb 100644 --- a/api/tests/instance/test_preferences.py +++ b/api/tests/instance/test_preferences.py @@ -34,3 +34,13 @@ def test_instance_settings(pref, value, preferences): preferences[pref] = value assert preferences[pref] == value + + +def test_instance_banner_assign_file_properly(preferences, avatar): + preferences["instance__banner"] = avatar + + avatar.seek(0) + banner = preferences["instance__banner"].read() + + assert len(banner) > 0 + assert banner == avatar.read() diff --git a/front/src/components/admin/SettingsGroup.vue b/front/src/components/admin/SettingsGroup.vue index 0c0774bbe..afaebfc54 100644 --- a/front/src/components/admin/SettingsGroup.vue +++ b/front/src/components/admin/SettingsGroup.vue @@ -61,6 +61,14 @@ class="ui search selection dropdown"> +
+ +
+ +

Current image

+ +
+