backoffice: check category permissions for export/statistics views (#53667)

This commit is contained in:
Frédéric Péters 2021-05-14 15:11:43 +02:00
parent 7225537069
commit 5783fd8f0a
3 changed files with 92 additions and 8 deletions

View File

@ -1500,6 +1500,67 @@ def test_backoffice_statistics(pub):
assert 'End: 2013-01-01' in resp.text
def test_backoffice_form_category_permissions(pub):
user = create_user(pub)
create_environment(pub)
formdef = FormDef.get_by_urlname('form-title')
app = login(get_app(pub))
resp = app.get('/backoffice/management/form-title/')
assert 'Export a Spreadsheet' in resp.text
assert 'Statistics' in resp.text
cat1 = Category(name='cat1')
cat1.store()
formdef.category_id = cat1.id
formdef.store()
resp = app.get('/backoffice/management/form-title/')
assert 'Export a Spreadsheet' in resp.text
assert 'Statistics' in resp.text
role = pub.role_class(name='limited perms')
role.store()
cat1.export_roles = [role]
cat1.store()
resp = app.get('/backoffice/management/form-title/')
assert 'Export a Spreadsheet' not in resp.text
assert 'Statistics' in resp.text
cat1.statistics_roles = [role]
cat1.store()
resp = app.get('/backoffice/management/form-title/')
assert 'Export a Spreadsheet' not in resp.text
assert 'Statistics' not in resp.text
app.get('/backoffice/management/form-title/stats', status=403)
app.get('/backoffice/management/form-title/export-spreadsheet', status=403)
app.get('/backoffice/management/form-title/csv', status=403)
app.get('/backoffice/management/form-title/ods', status=403)
# check it's ok for admins
user.is_admin = True
user.store()
resp = app.get('/backoffice/management/form-title/')
assert 'Export a Spreadsheet' in resp.text
assert 'Statistics' in resp.text
app.get('/backoffice/management/form-title/stats', status=200)
app.get('/backoffice/management/form-title/export-spreadsheet', status=200)
app.get('/backoffice/management/form-title/csv', status=200)
app.get('/backoffice/management/form-title/ods', status=200)
# check it's ok for agents with roles
user.is_admin = False
user.roles.append(role.id)
user.store()
resp = app.get('/backoffice/management/form-title/')
assert 'Export a Spreadsheet' in resp.text
assert 'Statistics' in resp.text
app.get('/backoffice/management/form-title/stats', status=200)
app.get('/backoffice/management/form-title/export-spreadsheet', status=200)
app.get('/backoffice/management/form-title/csv', status=200)
app.get('/backoffice/management/form-title/ods', status=200)
def test_backoffice_multi_actions(pub):
create_superuser(pub)
create_environment(pub)

View File

@ -1183,16 +1183,20 @@ class FormPage(Directory):
def get_formdata_sidebar_actions(self, qs=''):
r = TemplateIO(html=True)
r += htmltext(
' <li><a rel="popup" data-base-href="export-spreadsheet" data-autoclose-dialog="true" '
'href="export-spreadsheet%s">%s</a></li>'
) % (
qs,
_('Export a Spreadsheet'),
)
if not self.formdef.category or self.formdef.category.has_permission('export', get_request().user):
r += htmltext(
' <li><a rel="popup" data-base-href="export-spreadsheet" data-autoclose-dialog="true" '
'href="export-spreadsheet%s">%s</a></li>'
) % (
qs,
_('Export a Spreadsheet'),
)
if self.formdef.geolocations:
r += htmltext(' <li><a data-base-href="map" href="map%s">%s</a></li>') % (qs, _('Plot on a Map'))
if 'stats' in self._q_exports:
if 'stats' in self._q_exports and (
not self.formdef.category
or self.formdef.category.has_permission('statistics', get_request().user)
):
r += htmltext(' <li class="stats"><a href="stats">%s</a></li>') % _('Statistics')
return r.getvalue()
@ -2140,6 +2144,8 @@ class FormPage(Directory):
def export_spreadsheet(self):
self.check_access()
if self.formdef.category and not self.formdef.category.has_permission('export', get_request().user):
raise errors.AccessForbiddenError()
form = Form()
form.add_hidden('query_string', get_request().get_query())
form.add(
@ -2175,6 +2181,8 @@ class FormPage(Directory):
def csv(self):
self.check_access()
if self.formdef.category and not self.formdef.category.has_permission('export', get_request().user):
raise errors.AccessForbiddenError()
fields = self.get_fields_from_query()
selected_filter = self.get_filter_from_query()
user = get_request().user
@ -2227,6 +2235,8 @@ class FormPage(Directory):
if get_request().has_anonymised_data_api_restriction():
# api/ will let this pass but we don't want that.
raise errors.AccessForbiddenError()
if self.formdef.category and not self.formdef.category.has_permission('export', get_request().user):
raise errors.AccessForbiddenError()
fields = self.get_fields_from_query()
selected_filter = self.get_filter_from_query()
user = get_user_from_api_query_string() or get_request().user
@ -2476,6 +2486,10 @@ class FormPage(Directory):
def stats(self):
self.check_access()
if self.formdef.category and not self.formdef.category.has_permission(
'statistics', get_request().user
):
raise errors.AccessForbiddenError()
get_logger().info('backoffice - form %s - stats' % self.formdef.name)
html_top('management', '%s - %s' % (_('Form'), self.formdef.name))
r = TemplateIO(html=True)

View File

@ -124,6 +124,15 @@ class Category(XmlStorableObject):
text = '<p>%s</p>' % text
return htmltext(text)
def has_permission(self, permission_name, user):
if user.is_admin:
return True
permission_roles = getattr(self, '%s_roles' % permission_name, None) or []
if not permission_roles:
return True
user_roles = set(user.get_roles()) if user else set()
return bool(user_roles.intersection([x.id for x in permission_roles]))
class CardDefCategory(Category):
_names = 'carddef_categories'