backoffice: only display datasource custom views to admins (#77191) #299

Merged
fpeters merged 1 commits from wip/77191-custom-views-data-sources-admin into main 2023-05-12 09:39:44 +02:00
7 changed files with 78 additions and 11 deletions

View File

@ -6,6 +6,7 @@ from quixote import get_publisher
from wcs import fields
from wcs.carddef import CardDef
from wcs.categories import CardDefCategory
from wcs.formdef import FormDef
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.ident.password_accounts import PasswordAccount
@ -1239,3 +1240,64 @@ def test_item_options_in_dynamic_view(pub):
'a3',
'{}',
]
@pytest.mark.parametrize('user_perms', ['admin', 'category_admin', 'category_not_admin', 'agent'])
def test_backoffice_hidden_data_source_custom_view(pub, user_perms):
pub.user_class.wipe()
CardDefCategory.wipe()
cat = CardDefCategory(name='Foo')
cat.store()
if user_perms == 'admin':
user = create_superuser(pub)
elif user_perms == 'category_admin':
user = create_user(pub)
cat.management_roles = [pub.role_class.get(user.roles[0])]
cat.store()
else:
user = create_user(pub)
pub.custom_view_class.wipe()
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
fields.StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.backoffice_submission_roles = user.roles
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.digest_templates = {
'default': 'plop',
'custom-view:custom-test-view': 'FOO {{ form_var_foo }}',
'custom-view:datasource-view': '{{ form_var_foo }}',
}
if user_perms in ('category_admin', 'category_not_admin'):
carddef.category = cat
carddef.store()
custom_view = pub.custom_view_class()
custom_view.title = 'custom test view'
custom_view.formdef = carddef
custom_view.visibility = 'any'
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {}
custom_view.store()
custom_view = pub.custom_view_class()
custom_view.title = 'datasource view'
custom_view.formdef = carddef
custom_view.visibility = 'datasource'
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {}
custom_view.store()
app = login(get_app(pub))
resp = app.get('/backoffice/data/foo/')
visible_views = {x.attrib['href'] for x in resp.pyquery('#sidebar-custom-views a')}
if user_perms in ('admin', 'category_admin'):
assert visible_views == {'datasource-view/', 'custom-test-view/'}
else:
assert visible_views == {'custom-test-view/'}

View File

@ -1856,7 +1856,7 @@ class FormsDirectory(AccessControlled, Directory):
def _q_lookup(self, component):
directory = self.formdef_page_class(component)
if not directory.formdef.has_user_access(get_request().user):
if not directory.formdef.has_admin_access(get_request().user):
raise AccessForbiddenError()
return directory

View File

@ -2129,7 +2129,7 @@ class WorkflowsDirectory(Directory):
directory = WorkflowPage(component)
if directory.workflow.id in ('_default', '_carddef_default'):
return directory
if not directory.workflow.has_user_access(get_request().user):
if not directory.workflow.has_admin_access(get_request().user):
raise errors.AccessForbiddenError()
return directory

View File

@ -320,7 +320,7 @@ class ApiCardPage(ApiFormPageMixin, BackofficeCardPage):
return super().check_access(api_name=api_name)
def schema(self):
if is_url_signed() or self.formdef.has_user_access(get_user_from_api_query_string()):
if is_url_signed() or self.formdef.has_admin_access(get_user_from_api_query_string()):
get_response().set_content_type('application/json')
return self.formdef.export_to_json(with_user_fields=True)
raise AccessForbiddenError()
@ -563,7 +563,7 @@ class ApiFormdefDirectory(Directory):
self.formdef = formdef
def schema(self):
if is_url_signed() or self.formdef.has_user_access(get_user_from_api_query_string()):
if is_url_signed() or self.formdef.has_admin_access(get_user_from_api_query_string()):
get_response().set_content_type('application/json')
return self.formdef.export_to_json()
raise AccessForbiddenError()

View File

@ -879,12 +879,12 @@ class FormPage(FormdefDirectoryBase):
):
r += htmltext(' <li class="stats"><a href="stats">%s</a></li>') % _('Statistics')
if self.formdef.has_user_access(get_request().user):
if self.formdef.has_admin_access(get_request().user):
r += htmltext(' <li><a href="%s">%s</a></li>') % (
self.formdef.get_admin_url(),
self.formdef_view_label,
)
if self.formdef.workflow.has_user_access(get_request().user):
if self.formdef.workflow.has_admin_access(get_request().user):
r += htmltext(' <li><a href="%s">%s</a></li>') % (
self.formdef.workflow.get_admin_url(),
_('View Workflow'),
@ -896,7 +896,10 @@ class FormPage(FormdefDirectoryBase):
r += htmltext('<ul id="sidebar-actions">')
r += self.get_formdata_sidebar_actions(qs=qs)
r += htmltext('</ul>')
views = list(self.get_custom_views())
criterias = []
if not self.formdef.has_admin_access(get_request().user):
criterias = [NotEqual('visibility', 'datasource')]
views = list(self.get_custom_views(criterias))
if views:
r += htmltext('<h3>%s</h3>') % _('Custom Views')
r += htmltext('<ul id="sidebar-custom-views">')
@ -3677,8 +3680,8 @@ class FormBackOfficeStatusPage(FormStatusPage):
return v
access_to_admin_forms = get_publisher().get_backoffice_root().is_global_accessible('forms')
access_to_formdef = self.formdef.has_user_access(get_request().user)
access_to_workflow = self.formdef.workflow.has_user_access(get_request().user)
access_to_formdef = self.formdef.has_admin_access(get_request().user)
access_to_workflow = self.formdef.workflow.has_admin_access(get_request().user)
for k in sorted(substvars.get_flat_keys()):
if not k.startswith('form_'):

View File

@ -364,7 +364,9 @@ class FormDef(StorableObject):
break
return '%s%s' % (direction, order_by)
def has_user_access(self, user):
def has_admin_access(self, user):
# return True if user 1/ is global administrator for this type of object, or
# 2/ has one of the management roles defined in its category.
if get_publisher().get_backoffice_root().is_global_accessible(self.backoffice_section):
return True
if not user:

View File

@ -1341,7 +1341,7 @@ class Workflow(StorableObject):
criterias = [st.Contains('slug', slugs)]
return list(MailTemplate.select(criterias, order_by='name'))
def has_user_access(self, user):
def has_admin_access(self, user):
if get_publisher().get_backoffice_root().is_global_accessible('workflows'):
return True
if not user: