misc: keep track of user that changed a workflow in snapshot (#87843)
gitea/wcs/pipeline/head This commit looks good
Details
gitea/wcs/pipeline/head This commit looks good
Details
This commit is contained in:
parent
36e1f16a31
commit
23e66ec078
|
@ -765,7 +765,7 @@ def test_form_workflow_link(pub):
|
||||||
|
|
||||||
def test_form_workflow_remapping(pub):
|
def test_form_workflow_remapping(pub):
|
||||||
AfterJob.wipe()
|
AfterJob.wipe()
|
||||||
create_superuser(pub)
|
user = create_superuser(pub)
|
||||||
create_role(pub)
|
create_role(pub)
|
||||||
|
|
||||||
FormDef.wipe()
|
FormDef.wipe()
|
||||||
|
@ -872,6 +872,8 @@ def test_form_workflow_remapping(pub):
|
||||||
resp = resp.follow() # -> to job processing page
|
resp = resp.follow() # -> to job processing page
|
||||||
resp = resp.click('Back')
|
resp = resp.click('Back')
|
||||||
assert resp.pyquery('[href="workflow"] .offset').text() == 'Workflow Three'
|
assert resp.pyquery('[href="workflow"] .offset').text() == 'Workflow Three'
|
||||||
|
assert pub.snapshot_class.select_object_history(formdef)[0].comment == 'Workflow change'
|
||||||
|
assert pub.snapshot_class.select_object_history(formdef)[0].user_id == str(user.id)
|
||||||
|
|
||||||
# run a SQL SELECT and we known all columns are defined.
|
# run a SQL SELECT and we known all columns are defined.
|
||||||
FormDef.get(formdef.id).data_class().select()
|
FormDef.get(formdef.id).data_class().select()
|
||||||
|
|
|
@ -1140,7 +1140,12 @@ class FormDefPage(Directory, TempfileDirectoryMixin):
|
||||||
# there are existing formdata, status will have to be mapped
|
# there are existing formdata, status will have to be mapped
|
||||||
return redirect('workflow-status-remapping?new=%s' % workflow_id)
|
return redirect('workflow-status-remapping?new=%s' % workflow_id)
|
||||||
|
|
||||||
job = WorkflowChangeJob(formdef=self.formdef, new_workflow_id=workflow_id, status_mapping={})
|
job = WorkflowChangeJob(
|
||||||
|
formdef=self.formdef,
|
||||||
|
new_workflow_id=workflow_id,
|
||||||
|
status_mapping={},
|
||||||
|
user_id=get_session().user,
|
||||||
|
)
|
||||||
job.store()
|
job.store()
|
||||||
get_response().add_after_job(job)
|
get_response().add_after_job(job)
|
||||||
return redirect(job.get_processing_url())
|
return redirect(job.get_processing_url())
|
||||||
|
@ -1230,7 +1235,10 @@ class FormDefPage(Directory, TempfileDirectoryMixin):
|
||||||
return self.workflow_status_remapping()
|
return self.workflow_status_remapping()
|
||||||
|
|
||||||
job = WorkflowChangeJob(
|
job = WorkflowChangeJob(
|
||||||
formdef=self.formdef, new_workflow_id=new_workflow.id, status_mapping=status_mapping
|
formdef=self.formdef,
|
||||||
|
new_workflow_id=new_workflow.id,
|
||||||
|
status_mapping=status_mapping,
|
||||||
|
user_id=get_session().user,
|
||||||
)
|
)
|
||||||
job.store()
|
job.store()
|
||||||
get_response().add_after_job(job)
|
get_response().add_after_job(job)
|
||||||
|
@ -2042,19 +2050,20 @@ class FormsDirectory(AccessControlled, Directory):
|
||||||
|
|
||||||
|
|
||||||
class WorkflowChangeJob(AfterJob):
|
class WorkflowChangeJob(AfterJob):
|
||||||
def __init__(self, formdef, new_workflow_id, status_mapping):
|
def __init__(self, formdef, new_workflow_id, status_mapping, user_id):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
label=_('Updating data for new workflow'),
|
label=_('Updating data for new workflow'),
|
||||||
formdef_class=formdef.__class__,
|
formdef_class=formdef.__class__,
|
||||||
formdef_id=formdef.id,
|
formdef_id=formdef.id,
|
||||||
new_workflow_id=new_workflow_id,
|
new_workflow_id=new_workflow_id,
|
||||||
status_mapping=status_mapping,
|
status_mapping=status_mapping,
|
||||||
|
user_id=user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
formdef = self.kwargs['formdef_class'].get(self.kwargs['formdef_id'])
|
formdef = self.kwargs['formdef_class'].get(self.kwargs['formdef_id'])
|
||||||
workflow = Workflow.get(self.kwargs['new_workflow_id'])
|
workflow = Workflow.get(self.kwargs['new_workflow_id'])
|
||||||
formdef.change_workflow(workflow, self.kwargs['status_mapping'])
|
formdef.change_workflow(workflow, self.kwargs['status_mapping'], user_id=self.kwargs.get('user_id'))
|
||||||
|
|
||||||
def done_action_url(self):
|
def done_action_url(self):
|
||||||
formdef = self.kwargs['formdef_class'].get(self.kwargs['formdef_id'])
|
formdef = self.kwargs['formdef_class'].get(self.kwargs['formdef_id'])
|
||||||
|
|
|
@ -1967,7 +1967,7 @@ class FormDef(StorableObject):
|
||||||
# chunk contains the fields.
|
# chunk contains the fields.
|
||||||
return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2)
|
return pickle.dumps(object, protocol=2) + pickle.dumps(object.fields, protocol=2)
|
||||||
|
|
||||||
def change_workflow(self, new_workflow, status_mapping=None):
|
def change_workflow(self, new_workflow, status_mapping=None, user_id=None):
|
||||||
old_workflow = self.get_workflow()
|
old_workflow = self.get_workflow()
|
||||||
|
|
||||||
formdata_count = self.data_class().count()
|
formdata_count = self.data_class().count()
|
||||||
|
@ -2003,7 +2003,7 @@ class FormDef(StorableObject):
|
||||||
if function_key not in new_workflow.roles:
|
if function_key not in new_workflow.roles:
|
||||||
del self.workflow_roles[function_key]
|
del self.workflow_roles[function_key]
|
||||||
removed_functions.add(function_key)
|
removed_functions.add(function_key)
|
||||||
self.store(comment=_('Workflow change'))
|
self.store(comment=_('Workflow change'), snapshot_store_user=user_id)
|
||||||
if formdata_count:
|
if formdata_count:
|
||||||
# instruct formdef to update its security rules
|
# instruct formdef to update its security rules
|
||||||
self.data_class().rebuild_security()
|
self.data_class().rebuild_security()
|
||||||
|
|
|
@ -150,13 +150,21 @@ class Snapshot:
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def snap(cls, instance, comment=None, label=None, store_user=True, application=None):
|
def snap(cls, instance, comment=None, label=None, store_user=None, application=None):
|
||||||
obj = cls()
|
obj = cls()
|
||||||
obj.object_type = instance.xml_root_node
|
obj.object_type = instance.xml_root_node
|
||||||
obj.object_id = instance.id
|
obj.object_id = instance.id
|
||||||
obj.timestamp = now()
|
obj.timestamp = now()
|
||||||
if get_session() and store_user:
|
# store_user:
|
||||||
obj.user_id = get_session().user
|
# None/True: get user from active session
|
||||||
|
# False: do not store user
|
||||||
|
# any value: consider it as user id
|
||||||
|
# (store_user is explicitely checked to be a boolean, to avoid the "1" integer being treated as True)
|
||||||
|
if store_user is None or (isinstance(store_user, bool) and store_user is True):
|
||||||
|
if get_session():
|
||||||
|
obj.user_id = get_session().user
|
||||||
|
elif store_user:
|
||||||
|
obj.user_id = store_user
|
||||||
|
|
||||||
tree = instance.export_to_xml(include_id=True)
|
tree = instance.export_to_xml(include_id=True)
|
||||||
# remove position for categories
|
# remove position for categories
|
||||||
|
|
Loading…
Reference in New Issue