diff --git a/tests/workflow/test_carddata.py b/tests/workflow/test_carddata.py index 9cf70a4ad..1fe7f5648 100644 --- a/tests/workflow/test_carddata.py +++ b/tests/workflow/test_carddata.py @@ -1666,3 +1666,50 @@ def test_create_carddata_with_workflow_deleting_it(pub): formdata.store() formdata.perform_workflow() assert carddef.data_class().count() == 0 + + +@pytest.mark.parametrize('submitter_is_triggerer', [True, False]) +def test_anonymise_action_unlink_user(pub, submitter_is_triggerer): + CardDef.wipe() + FormDef.wipe() + pub.user_class.wipe() + + user = pub.user_class() + user.email = 'test@example.net' + user.name_identifiers = ['xyz'] + user.store() + + if submitter_is_triggerer: + pub.get_request()._user = () + pub.get_request().session = sessions.BasicSession(id=1) + pub.get_request().session.set_user(user.id) + + wf = Workflow(name='test-unlink-user') + wf.possible_status = Workflow.get_default_workflow().possible_status[:] + anonymise = wf.possible_status[1].add_action('anonymise', id='_anonymise', prepend=True) + anonymise.label = 'Unlink User' + anonymise.varname = 'mycard' + anonymise.unlink_user = True + wf.store() + + carddef = CardDef() + carddef.name = 'Person' + carddef.workflow_id = wf.id + carddef.store() + carddef.data_class().wipe() + + carddata = carddef.data_class()() + carddata.data = {'0': 'Foo', '1': 'Bar'} + carddata.user_id = user.id + carddata.just_created() + carddata.store() + + assert carddef.data_class().select()[0].user.id == user.id + + carddata.perform_workflow() + + assert carddef.data_class().select()[0].user is None + assert ( + pub.get_request().session.is_anonymous_submitter(carddef.data_class().select()[0]) + is submitter_is_triggerer + ) diff --git a/tests/workflow/test_formdata.py b/tests/workflow/test_formdata.py index 1a9cdd74b..45b2bc3b4 100644 --- a/tests/workflow/test_formdata.py +++ b/tests/workflow/test_formdata.py @@ -1,5 +1,5 @@ import pytest -from quixote import cleanup, get_response +from quixote import cleanup, get_publisher, get_response from wcs import sessions from wcs.carddef import CardDef @@ -407,3 +407,56 @@ def test_create_formdata_does_not_overwrite_initial_submission_context(pub): formdata.perform_workflow() assert target_formdef.data_class().count() == 2 assert formdata.submission_context == {'a': 'b'} + + +@pytest.mark.parametrize('submitter_is_triggerer', [True, False]) +def test_anonymise_action_unlink_user(pub, submitter_is_triggerer): + CardDef.wipe() + FormDef.wipe() + pub.user_class.wipe() + + user = pub.user_class() + user.email = 'test@example.net' + user.name_identifiers = ['xyz'] + user.store() + + if submitter_is_triggerer: + pub.get_request()._user = () + pub.get_request().session = sessions.BasicSession(id=1) + pub.get_request().session.set_user(user.id) + + wf = Workflow(name='test-unlink-user') + wf.possible_status = Workflow.get_default_workflow().possible_status[:] + anonymise = wf.possible_status[1].add_action('anonymise', id='_anonymise', prepend=True) + anonymise.label = 'Unlink User' + anonymise.varname = 'mycard' + anonymise.unlink_user = True + wf.store() + + formdef = FormDef() + formdef.name = 'Person' + formdef.workflow_id = wf.id + formdef.enable_tracking_codes = True + formdef.store() + formdef.data_class().wipe() + + formdata = formdef.data_class()() + formdata.data = {'0': 'Foo', '1': 'Bar'} + formdata.user_id = user.id + formdata.just_created() + formdata.store() + + code = get_publisher().tracking_code_class() + code.formdata = formdata + + assert formdef.data_class().select()[0].user.id == user.id + assert formdef.data_class().select()[0].tracking_code + + formdata.perform_workflow() + + assert formdef.data_class().select()[0].user is None + assert formdef.data_class().select()[0].tracking_code is None + assert ( + pub.get_request().session.is_anonymous_submitter(formdef.data_class().select()[0]) + is submitter_is_triggerer + ) diff --git a/wcs/formdata.py b/wcs/formdata.py index 5a6aeab58..5054e598c 100644 --- a/wcs/formdata.py +++ b/wcs/formdata.py @@ -1285,6 +1285,17 @@ class FormData(StorableObject): self._store_all_evolution = True self.store() + def unlink_user(self): + if self.user_id: + self.user_id = None + self.store() + + def remove_tracking_code(self): + if self.tracking_code is not None: + get_publisher().tracking_code_class.remove_object(self.tracking_code) + self.tracking_code = None + self.store() + def get_display_name(self): return _('%(name)s #%(id)s') % {'name': self.formdef.name, 'id': self.get_display_id()} diff --git a/wcs/wf/anonymise.py b/wcs/wf/anonymise.py index 65a8ad4d4..2fe09503c 100644 --- a/wcs/wf/anonymise.py +++ b/wcs/wf/anonymise.py @@ -14,7 +14,10 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see . +from quixote import get_request, get_session + from wcs.qommon import _ +from wcs.qommon.form import CheckboxWidget from wcs.workflows import WorkflowStatusItem, register_item_class @@ -22,9 +25,33 @@ class AnonymiseWorkflowStatusItem(WorkflowStatusItem): description = _('Anonymisation') key = 'anonymise' category = 'formdata-action' + unlink_user = False def perform(self, formdata): - formdata.anonymise() + if self.unlink_user is True: + if formdata.is_submitter(get_request().user): + get_session().mark_anonymous_formdata(formdata) + formdata.unlink_user() + formdata.remove_tracking_code() + else: + formdata.anonymise() + + def get_parameters(self): + return ('unlink_user',) + + def add_parameters_widgets(self, form, parameters, prefix='', formdef=None, **kwargs): + super().add_parameters_widgets(form, parameters, prefix, formdef, **kwargs) + if 'unlink_user' in parameters: + form.add( + CheckboxWidget, + '%sunlink_user' % prefix, + title=_('Only perform form/card user unlinking'), + hint=_( + 'If checked, this action will only unlink user from the form/card. ' + 'If existing, the tracking code will be deleted.' + ), + value=self.unlink_user, + ) register_item_class(AnonymiseWorkflowStatusItem)