From 3d3db505999b65e45297b623342804654664af33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 30 Oct 2020 11:05:21 +0100
Subject: [PATCH] api: list carddef datasource custom views (#48099)

---
 tests/test_api.py | 86 +++++++++++++++++++++++++++++++++++++++++++++++
 wcs/api.py        | 12 +++----
 2 files changed, 91 insertions(+), 7 deletions(-)

diff --git a/tests/test_api.py b/tests/test_api.py
index aa98a579..6482f377 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -2157,6 +2157,90 @@ def test_api_ods_formdata(pub, local_user):
     assert len(ods_sheet.findall('.//{%s}table-row' % ods.NS['table'])) == 311
 
 
+def test_api_custom_view_access(pub, local_user):
+    Role.wipe()
+    role = Role(name='test')
+    role.store()
+    local_user.roles = [role.id]
+    local_user.store()
+
+    FormDef.wipe()
+    formdef = FormDef()
+    formdef.name = 'test'
+    formdef.workflow_roles = {'_receiver': role.id}
+    formdef.fields = [fields.StringField(id='0', label='foobar', varname='foobar')]
+    formdef.geolocations = {'base': 'Location'}
+    formdef.store()
+
+    carddef = CardDef()
+    carddef.name = 'test'
+    carddef.fields = [fields.StringField(id='0', label='foobar', varname='foo')]
+    carddef.workflow_roles = {'_viewer': role.id}
+    carddef.digest_template = 'bla {{ form_var_foo }} xxx'
+    carddef.geolocations = {'base': 'Location'}
+    carddef.store()
+
+    pub.custom_view_class.wipe()
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'shared formdef custom view'
+    custom_view.formdef = formdef
+    custom_view.columns = {'list': [{'id': '0'}]}
+    custom_view.filters = {}
+    custom_view.visibility = 'any'
+    custom_view.store()
+
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'private formdef custom view'
+    custom_view.formdef = formdef
+    custom_view.columns = {'list': [{'id': '0'}]}
+    custom_view.filters = {}
+    custom_view.visibility = 'owner'
+    custom_view.user = local_user
+    custom_view.store()
+
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'shared carddef custom view'
+    custom_view.formdef = carddef
+    custom_view.columns = {'list': [{'id': '0'}]}
+    custom_view.filters = {}
+    custom_view.visibility = 'any'
+    custom_view.store()
+
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'private carddef custom view'
+    custom_view.formdef = carddef
+    custom_view.columns = {'list': [{'id': '0'}]}
+    custom_view.filters = {}
+    custom_view.visibility = 'owner'
+    custom_view.user = local_user
+    custom_view.store()
+
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'datasource carddef custom view'
+    custom_view.formdef = carddef
+    custom_view.columns = {'list': [{'id': '0'}]}
+    custom_view.filters = {}
+    custom_view.visibility = 'datasource'
+    custom_view.store()
+
+    get_app(pub).get(sign_uri('/api/forms/test/list/shared-formdef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/forms/test/ods/shared-formdef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/forms/test/geojson/shared-formdef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/forms/test/list/private-formdef-custom-view', user=local_user), status=404)
+    get_app(pub).get(sign_uri('/api/forms/test/ods/private-formdef-custom-view', user=local_user), status=404)
+    get_app(pub).get(sign_uri('/api/forms/test/geojson/private-formdef-custom-view', user=local_user), status=404)
+
+    get_app(pub).get(sign_uri('/api/cards/test/list/shared-carddef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/cards/test/ods/shared-carddef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/cards/test/geojson/shared-carddef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/cards/test/list/private-carddef-custom-view', user=local_user), status=404)
+    get_app(pub).get(sign_uri('/api/cards/test/ods/private-carddef-custom-view', user=local_user), status=404)
+    get_app(pub).get(sign_uri('/api/cards/test/geojson/private-carddef-custom-view', user=local_user), status=404)
+    get_app(pub).get(sign_uri('/api/cards/test/list/datasource-carddef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/cards/test/ods/datasource-carddef-custom-view', user=local_user), status=200)
+    get_app(pub).get(sign_uri('/api/cards/test/geojson/datasource-carddef-custom-view', user=local_user), status=200)
+
+
 def test_api_list_formdata_custom_view(pub, local_user):
     Role.wipe()
     role = Role(name='test')
@@ -3228,6 +3312,7 @@ def test_cards(pub, local_user):
     local_user.roles = [role.id]
     local_user.store()
 
+    CardDef.wipe()
     carddef = CardDef()
     carddef.name = 'test'
     carddef.fields = [fields.StringField(id='0', label='foobar', varname='foo')]
@@ -3235,6 +3320,7 @@ def test_cards(pub, local_user):
     carddef.digest_template = 'bla {{ form_var_foo }} xxx'
     carddef.store()
 
+    carddef.data_class().wipe()
     formdata = carddef.data_class()()
     formdata.data = {'0': 'blah'}
     formdata.just_created()
diff --git a/wcs/api.py b/wcs/api.py
index 04575929..5236a8d9 100644
--- a/wcs/api.py
+++ b/wcs/api.py
@@ -17,7 +17,6 @@
 import json
 import re
 import time
-import sys
 
 from quixote import get_request, get_publisher, get_response, get_session
 from quixote.directory import Directory
@@ -28,10 +27,9 @@ from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse
 
 from .qommon import _
 from .qommon import misc
-from .qommon.errors import (AccessForbiddenError, HttpResponse401Error,
-    QueryError, TraversalError, UnknownNameIdAccessForbiddenError, RequestError)
-from .qommon.form import ComputedExpressionWidget, ConditionWidget
-from .qommon.storage import Equal
+from .qommon.errors import AccessForbiddenError, TraversalError, UnknownNameIdAccessForbiddenError
+from .qommon.form import ComputedExpressionWidget
+from .qommon.storage import Equal, NotEqual
 
 from wcs.categories import Category
 from wcs.conditions import Condition, ValidationError
@@ -215,12 +213,12 @@ class ApiFormPage(BackofficeFormPage):
                     path = [mode]  # default view, with trailing slash
                 else:
                     # custom view
-                    for view in self.get_custom_views([Equal('visibility', 'any'), Equal('slug', path[1])]):
+                    for view in self.get_custom_views([NotEqual('visibility', 'owner'), Equal('slug', path[1])]):
                         self._view = view
                         path = [mode]
 
         if len(path) >= 2 and path[1] == 'ics':
-            for view in self.get_custom_views([Equal('visibility', 'any'), Equal('slug', path[0])]):
+            for view in self.get_custom_views([NotEqual('visibility', 'owner'), Equal('slug', path[0])]):
                 self._view = view
                 path = path[1:]
 
-- 
2.28.0

