From 6152b3bb36ef0a65dd50d8b43d9aefa2ca4f0ada Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Sat, 17 Feb 2018 21:21:08 +0100
Subject: [PATCH] Added API endpoint for listing public instance settings

---
 api/config/api_urls.py                 |  5 +++++
 api/config/settings/common.py          |  1 +
 api/funkwhale_api/instance/__init__.py |  0
 api/funkwhale_api/instance/urls.py     |  7 +++++++
 api/funkwhale_api/instance/views.py    | 25 +++++++++++++++++++++++++
 api/tests/conftest.py                  | 10 +++++++++-
 api/tests/instance/test_preferences.py | 22 ++++++++++++++++++++++
 7 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 api/funkwhale_api/instance/__init__.py
 create mode 100644 api/funkwhale_api/instance/urls.py
 create mode 100644 api/funkwhale_api/instance/views.py
 create mode 100644 api/tests/instance/test_preferences.py

diff --git a/api/config/api_urls.py b/api/config/api_urls.py
index d64eeb5f..c7ebc4ed 100644
--- a/api/config/api_urls.py
+++ b/api/config/api_urls.py
@@ -1,5 +1,6 @@
 from rest_framework import routers
 from django.conf.urls import include, url
+from funkwhale_api.instance import views as instance_views
 from funkwhale_api.music import views
 from funkwhale_api.playlists import views as playlists_views
 from rest_framework_jwt import views as jwt_views
@@ -25,6 +26,10 @@ router.register(
 v1_patterns = router.urls
 
 v1_patterns += [
+    url(r'^instance/',
+        include(
+            ('funkwhale_api.instance.urls', 'instance'),
+            namespace='instance')),
     url(r'^providers/',
         include(
             ('funkwhale_api.providers.urls', 'providers'),
diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index 6f821dfb..2761f915 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -60,6 +60,7 @@ THIRD_PARTY_APPS = (
 LOCAL_APPS = (
     'funkwhale_api.users',  # custom users app
     # Your stuff: custom apps go here
+    'funkwhale_api.instance',
     'funkwhale_api.music',
     'funkwhale_api.favorites',
     'funkwhale_api.radios',
diff --git a/api/funkwhale_api/instance/__init__.py b/api/funkwhale_api/instance/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/api/funkwhale_api/instance/urls.py b/api/funkwhale_api/instance/urls.py
new file mode 100644
index 00000000..2f2b46b8
--- /dev/null
+++ b/api/funkwhale_api/instance/urls.py
@@ -0,0 +1,7 @@
+from django.conf.urls import url
+from . import views
+
+
+urlpatterns = [
+    url(r'^settings/$', views.InstanceSettings.as_view(), name='settings'),
+]
diff --git a/api/funkwhale_api/instance/views.py b/api/funkwhale_api/instance/views.py
new file mode 100644
index 00000000..44ee2287
--- /dev/null
+++ b/api/funkwhale_api/instance/views.py
@@ -0,0 +1,25 @@
+from rest_framework import views
+from rest_framework.response import Response
+
+from dynamic_preferences.api import serializers
+from dynamic_preferences.registries import global_preferences_registry
+
+
+class InstanceSettings(views.APIView):
+    permission_classes = []
+    authentication_classes = []
+
+    def get(self, request, *args, **kwargs):
+        manager = global_preferences_registry.manager()
+        manager.all()
+        all_preferences = manager.model.objects.all().order_by(
+            'section', 'name'
+        )
+        api_preferences = [
+            p
+            for p in all_preferences
+            if getattr(p.preference, 'show_in_api', False)
+        ]
+        data = serializers.GlobalPreferenceSerializer(
+            api_preferences, many=True).data
+        return Response(data, status=200)
diff --git a/api/tests/conftest.py b/api/tests/conftest.py
index 6c0cffa4..4d7a6fa9 100644
--- a/api/tests/conftest.py
+++ b/api/tests/conftest.py
@@ -3,6 +3,7 @@ import shutil
 import pytest
 from django.core.cache import cache as django_cache
 from dynamic_preferences.registries import global_preferences_registry
+from rest_framework.test import APIClient
 
 from funkwhale_api.taskapp import celery
 
@@ -29,7 +30,9 @@ def factories(db):
 
 @pytest.fixture
 def preferences(db):
-    yield global_preferences_registry.manager()
+    manager = global_preferences_registry.manager()
+    manager.all()
+    yield manager
 
 
 @pytest.fixture
@@ -48,6 +51,11 @@ def logged_in_client(db, factories, client):
     delattr(client, 'user')
 
 
+@pytest.fixture
+def api_client(client):
+    return APIClient()
+
+
 @pytest.fixture
 def superuser_client(db, factories, client):
     user = factories['users.SuperUser']()
diff --git a/api/tests/instance/test_preferences.py b/api/tests/instance/test_preferences.py
new file mode 100644
index 00000000..c89bfa34
--- /dev/null
+++ b/api/tests/instance/test_preferences.py
@@ -0,0 +1,22 @@
+from django.urls import reverse
+
+from dynamic_preferences.api import serializers
+
+
+def test_can_list_settings_via_api(preferences, api_client):
+    url = reverse('api:v1:instance:settings')
+    all_preferences = preferences.model.objects.all()
+    expected_preferences = {
+        p.preference.identifier(): p
+        for p in all_preferences
+        if getattr(p.preference, 'show_in_api', False)}
+
+    assert len(expected_preferences) > 0
+
+    response = api_client.get(url)
+    assert response.status_code == 200
+    assert len(response.data) == len(expected_preferences)
+
+    for p in response.data:
+        i = '__'.join([p['section'], p['name']])
+        assert i in expected_preferences
-- 
GitLab