From 4d06af425ec2468c3d5d227a3f31082a997f5727 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 26 Feb 2016 10:49:56 +0100 Subject: [PATCH 1/2] add anonymise parameter to JSON exports of formdata (#9146) - FormData.get_json_export_dict(), .get_json_dict(), .export_to_json(), FormDefUI.get_listing_items(), .export_to_json() get a new anonymise parameter. - in FormPage.json() and FormStatusPage().json if an anonymise parameter is present in the query string the anonymized mode is activated. --- wcs/backoffice/management.py | 10 ++++++---- wcs/formdata.py | 42 +++++++++++++++++++++++------------------- wcs/forms/backoffice.py | 6 +++--- wcs/forms/common.py | 17 ++++++++++++----- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py index 31f86e0..1bc8d6b 100644 --- a/wcs/backoffice/management.py +++ b/wcs/backoffice/management.py @@ -1331,19 +1331,21 @@ class FormPage(Directory): return exporter.output.getvalue() def json(self): + anonymise = 'anonymise' in get_request().form self.check_access() get_response().set_content_type('application/json') from wcs.api import get_user_from_api_query_string - user = get_user_from_api_query_string() or get_request().user + user = get_user_from_api_query_string() or get_request().user if not anonymise else None selected_filter = self.get_filter_from_query(default='all') criterias = self.get_criterias_from_query() order_by = get_request().form.get('order_by', None) - query = get_request().form.get('q') + query = get_request().form.get('q') if not anonymise else None items, total_count = FormDefUI(self.formdef).get_listing_items( selected_filter, user=user, query=query, criterias=criterias, - order_by=order_by) + order_by=order_by, anonymise=anonymise) if get_request().form.get('full') == 'on': - output = [filled.get_json_export_dict(include_files=False) for filled in items] + output = [filled.get_json_export_dict(include_files=False, anonymise=anonymise) + for filled in items] else: output = [{'id': filled.id, 'url': filled.get_url(), diff --git a/wcs/formdata.py b/wcs/formdata.py index 96a8de2..d6ee5da 100644 --- a/wcs/formdata.py +++ b/wcs/formdata.py @@ -97,9 +97,11 @@ def flatten_dict(d): del d[k] -def get_json_dict(fields, data, include_files=True): +def get_json_dict(fields, data, include_files=True, anonymise=False): new_data = {} for field in fields: + if anonymise and field.anonymise: + continue if not field.varname: # exports only named fields continue if not include_files and isinstance(field, FileField): @@ -624,7 +626,7 @@ class FormData(StorableObject): evo.parts = None self.store() - def get_json_export_dict(self, include_files=True): + def get_json_export_dict(self, include_files=True, anonymise=False): data = {} data['id'] = '%s/%s' % (self.formdef.url_name, self.id) data['display_id'] = self.get_display_id() @@ -635,29 +637,31 @@ class FormData(StorableObject): data['last_update_time'] = self.last_update_time data['url'] = self.get_url() - try: - user = get_publisher().user_class.get(self.user_id) - except KeyError: - user = None - # this is custom code so it is possible to mark forms as anonyms, this - # is done through the VoteAnonymity field, this is very specific but - # isn't generalised yet into an useful extension mechanism, as it's not - # clear at the moment what could be useful. - for f in self.formdef.fields: - if f.key == 'vote-anonymity': + if not anonymise: + try: + user = get_publisher().user_class.get(self.user_id) + except KeyError: user = None - break - if user: - data['user'] = {'id': user.id, 'name': user.display_name} + # this is custom code so it is possible to mark forms as anonyms, this + # is done through the VoteAnonymity field, this is very specific but + # isn't generalised yet into an useful extension mechanism, as it's not + # clear at the moment what could be useful. + for f in self.formdef.fields: + if f.key == 'vote-anonymity': + user = None + break + if user: + data['user'] = {'id': user.id, 'name': user.display_name} data['fields'] = get_json_dict(self.formdef.fields, self.data, - include_files=include_files) + include_files=include_files, anonymise=anonymise) data['workflow'] = {} wf_status = self.get_visible_status() if wf_status: data['workflow']['status'] = {'id': wf_status.id, 'name': wf_status.name} - if self.workflow_data: + # Workflow data have unknown purpose, do not store then in anonymised export + if self.workflow_data and not anonymise: data['workflow']['data'] = self.workflow_data # add a roles dictionary, with workflow functions and two special @@ -689,8 +693,8 @@ class FormData(StorableObject): return data - def export_to_json(self, include_files=True): - data = self.get_json_export_dict(include_files=include_files) + def export_to_json(self, include_files=True, anonymise=False): + data = self.get_json_export_dict(include_files=include_files, anonymise=anonymise) return json.dumps(data, cls=qommon.misc.JSONEncoder, encoding=get_publisher().site_charset) diff --git a/wcs/forms/backoffice.py b/wcs/forms/backoffice.py index c95e877..3cc7f5c 100644 --- a/wcs/forms/backoffice.py +++ b/wcs/forms/backoffice.py @@ -131,7 +131,7 @@ class FormDefUI(object): return r.getvalue() def get_listing_items(self, selected_filter='all', offset=None, - limit=None, query=None, order_by=None, user=None, criterias=None): + limit=None, query=None, order_by=None, user=None, criterias=None, anonymise=False): formdata_class = self.formdef.data_class() if selected_filter == 'all': item_ids = formdata_class.keys() @@ -160,7 +160,7 @@ class FormDefUI(object): select_ids = [x.id for x in formdata_class.select(clause=criterias)] item_ids = list(set(item_ids).intersection(select_ids)) - if item_ids: + if item_ids and not anonymise: # as we are in the backoffice, we don't have to care about the # situation where the user is the submitter, and we limit ourselves # to consider treating roles. @@ -173,7 +173,7 @@ class FormDefUI(object): 'concerned_roles', str(role))) item_ids = list(set(item_ids).intersection(concerned_ids)) - if order_by: + if order_by and not anonymise: ordered_ids = formdata_class.get_sorted_ids(order_by) new_item_ids = [] for item_id in ordered_ids: diff --git a/wcs/forms/common.py b/wcs/forms/common.py index c9d4add..46d7634 100644 --- a/wcs/forms/common.py +++ b/wcs/forms/common.py @@ -114,8 +114,14 @@ class FormStatusPage(Directory): session = get_session() mine = False if api_call: - from wcs.api import get_user_from_api_query_string - user = get_user_from_api_query_string() or get_request().user + from wcs.api import get_user_from_api_query_string, is_url_signed + if 'anonymise' in get_request().form: + if is_url_signed() or (get_request().user and get_request().user.is_admin): + return None + else: + raise errors.AccessUnauthorizedError() + else: + user = get_user_from_api_query_string() or get_request().user else: user = get_request().user if user and not user.anonymous: @@ -130,7 +136,8 @@ class FormStatusPage(Directory): def json(self): self.check_auth(api_call=True) - return self.export_to_json() + anonymise = 'anonymise' in get_request().form + return self.export_to_json(anonymise=anonymise) def workflow_messages(self): if self.formdef.workflow: @@ -230,9 +237,9 @@ class FormStatusPage(Directory): r += self.form_status_buttons() return r.getvalue() - def export_to_json(self): + def export_to_json(self, anonymise=False): get_response().set_content_type('application/json') - return self.filled.export_to_json() + return self.filled.export_to_json(anonymise=anonymise) def form_status_buttons(self): if not get_response().iframe_mode: -- 2.1.4