Repository: nextcloud/appstore

Issue:
Need to return all apps on >=NC16
For https://github.com/nextcloud/server/pull/14578

We to deliver the full app list when on NC 16. No server side filtering as the admin gets the option to force enable the app.

CC: @MorrisJobke @blizzz 


Discussion:
I would propose to either

1) add a separate query parameter that returns all apps
or 
2) create a separate API endpoint


@BernhardPosselt 
>  2. create a separate API endpoint

I would prefer that
Fine by me.
    GET /api/v1/apps.json 

I suppose

Resolving patch:
diff --git a/nextcloudappstore/api/v1/urls.py b/nextcloudappstore/api/v1/urls.py
--- a/nextcloudappstore/api/v1/urls.py
+++ b/nextcloudappstore/api/v1/urls.py
@@ -2,9 +2,9 @@
 from django.views.decorators.http import etag
 from nextcloudappstore.api.v1.views import AppView, AppReleaseView, \
     CategoryView, SessionObtainAuthToken, RegenerateAuthToken, AppRatingView, \
-    AppRegisterView, NextcloudReleaseView
+    AppRegisterView, NextcloudReleaseView, AppsView
 from nextcloudappstore.core.caching import app_ratings_etag, categories_etag, \
-    apps_etag, nextcloud_release_etag
+    apps_etag, nextcloud_release_etag, apps_all_etag
 from nextcloudappstore.core.versioning import SEMVER_REGEX
 
 app_name = 'v1'
@@ -15,6 +15,8 @@
         name='platforms'),
     url(r'^platform/(?P<version>\d+\.\d+\.\d+)/apps\.json$',
         etag(apps_etag)(AppView.as_view()), name='app'),
+    url(r'^apps\.json$',
+        etag(apps_all_etag)(AppsView.as_view()), name='apps'),
     url(r'^apps/releases/?$', AppReleaseView.as_view(),
         name='app-release-create'),
     url(r'^apps/?$', AppRegisterView.as_view(), name='app-register'),
diff --git a/nextcloudappstore/api/v1/views.py b/nextcloudappstore/api/v1/views.py
--- a/nextcloudappstore/api/v1/views.py
+++ b/nextcloudappstore/api/v1/views.py
@@ -28,6 +28,18 @@
 from nextcloudappstore.core.versioning import version_in_spec
 from nextcloudappstore.user.facades import update_token
 
+APP_PREFETCH_LIST = [
+    'authors',
+    'screenshots',
+    'categories',
+    'translations',
+    'releases__translations',
+    'releases__phpextensiondependencies__php_extension',
+    'releases__databasedependencies__database',
+    'releases__shell_commands',
+    'releases__licenses',
+]
+
 
 class CategoryView(ListAPIView):
     queryset = Category.objects.prefetch_related('translations').all()
@@ -44,6 +56,11 @@ class NextcloudReleaseView(ListAPIView):
     serializer_class = NextcloudReleaseSerializer
 
 
+class AppsView(ListAPIView):
+    queryset = App.objects.prefetch_related(*APP_PREFETCH_LIST).all()
+    serializer_class = AppSerializer
+
+
 class AppView(DestroyAPIView):
     authentication_classes = (authentication.TokenAuthentication,
                               authentication.BasicAuthentication,)
@@ -53,18 +70,8 @@ class AppView(DestroyAPIView):
 
     def get(self, request, *args, **kwargs):
         version = self.kwargs['version']
-        prefetch = [
-            'authors',
-            'screenshots',
-            'categories',
-            'translations',
-            'releases__translations',
-            'releases__phpextensiondependencies__php_extension',
-            'releases__databasedependencies__database',
-            'releases__shell_commands',
-            'releases__licenses',
-        ]
-        working_apps = App.objects.get_compatible(version, prefetch=prefetch)
+        working_apps = App.objects.get_compatible(version,
+                                                  prefetch=APP_PREFETCH_LIST)
         serializer = self.get_serializer(working_apps, many=True)
         data = self._filter_releases(serializer.data, version)
         return Response(data)
diff --git a/nextcloudappstore/core/caching.py b/nextcloudappstore/core/caching.py
--- a/nextcloudappstore/core/caching.py
+++ b/nextcloudappstore/core/caching.py
@@ -25,6 +25,13 @@ def apps_etag(request: Any, version: str) -> str:
     ])
 
 
+def apps_all_etag(request: Any) -> str:
+    return create_etag([
+        (App.objects.all(), 'last_release'),
+        (AppReleaseDeleteLog.objects.all(), 'last_modified'),
+    ])
+
+
 def app_etag(request: Any, id: str) -> str:
     return str(App.objects.get(id=id).last_modified)
 


Test patch: