diff --git a/CHANGES.rst b/CHANGES.rst
index 08f0a4e..539e306 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,11 @@ Changelog
1.2b2 (unreleased)
------------------
-- Avoid ComponentLookupError when plonectl adduser.
+- Add support for logging workflow transitions.
+ [hvelarde]
+
+- Avoid ComponentLookupError when plonectl adduser.
+ [jianaijun]
1.2b1 (2016-09-28)
diff --git a/src/collective/fingerpointing/interfaces.py b/src/collective/fingerpointing/interfaces.py
index d003806..c3b86bd 100644
--- a/src/collective/fingerpointing/interfaces.py
+++ b/src/collective/fingerpointing/interfaces.py
@@ -27,6 +27,12 @@ class IFingerPointingSettings(Interface):
default=True,
)
+ audit_workflow = schema.Bool(
+ title=_(u'Audit Workflow Transitions?'),
+ description=_(u'Log workflow transitions like object publishing.'),
+ default=True,
+ )
+
audit_registry = schema.Bool(
title=_(u'Audit Registry?'),
description=_(u'Log registry events like records being modified.'),
diff --git a/src/collective/fingerpointing/profiles/default/metadata.xml b/src/collective/fingerpointing/profiles/default/metadata.xml
index a44cc34..dab4dc0 100644
--- a/src/collective/fingerpointing/profiles/default/metadata.xml
+++ b/src/collective/fingerpointing/profiles/default/metadata.xml
@@ -1,4 +1,4 @@
- 3
+ 4
diff --git a/src/collective/fingerpointing/subscribers/__init__.py b/src/collective/fingerpointing/subscribers/__init__.py
index 00cf810..d2876a5 100644
--- a/src/collective/fingerpointing/subscribers/__init__.py
+++ b/src/collective/fingerpointing/subscribers/__init__.py
@@ -3,3 +3,4 @@
from .lifecycle_logger import lifecycle_logger # noqa
from .pas_logger import pas_logger # noqa
from .registry_logger import registry_logger # noqa
+from .workflow_logger import workflow_logger # noqa: F401
diff --git a/src/collective/fingerpointing/subscribers/configure.zcml b/src/collective/fingerpointing/subscribers/configure.zcml
index d31a2ee..4a8be21 100644
--- a/src/collective/fingerpointing/subscribers/configure.zcml
+++ b/src/collective/fingerpointing/subscribers/configure.zcml
@@ -97,4 +97,10 @@
handler=".iterate_logger"
/>
+
+
+
diff --git a/src/collective/fingerpointing/subscribers/workflow_logger.py b/src/collective/fingerpointing/subscribers/workflow_logger.py
new file mode 100644
index 0000000..bc6f6d1
--- /dev/null
+++ b/src/collective/fingerpointing/subscribers/workflow_logger.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+"""Event subscriber handler for IActionSucceededEvent."""
+from collective.fingerpointing.config import AUDIT_MESSAGE
+from collective.fingerpointing.interfaces import IFingerPointingSettings
+from collective.fingerpointing.logger import log_info
+from collective.fingerpointing.utils import get_request_information
+from plone import api
+from plone.api.exc import InvalidParameterError
+
+
+def workflow_logger(event):
+ """Log workflow transitions."""
+ try:
+ record = IFingerPointingSettings.__identifier__ + '.audit_workflow'
+ audit_workflow = api.portal.get_registry_record(record)
+ except InvalidParameterError:
+ return # package is not installed
+
+ if audit_workflow:
+ user, ip = get_request_information()
+ action = 'workflow transition'
+ extras = u'object={0} transition={1}'.format(event.object, event.action)
+ log_info(AUDIT_MESSAGE.format(user, ip, action, extras))
diff --git a/src/collective/fingerpointing/testing.py b/src/collective/fingerpointing/testing.py
index 0cb8e1b..2951538 100644
--- a/src/collective/fingerpointing/testing.py
+++ b/src/collective/fingerpointing/testing.py
@@ -43,17 +43,16 @@ def setUpZope(self, app, configurationContext):
def setUpPloneSite(self, portal):
self.applyProfile(portal, 'collective.fingerpointing:default')
+ portal.portal_workflow.setDefaultChain('simple_publication_workflow')
FIXTURE = Fixture()
INTEGRATION_TESTING = IntegrationTesting(
- bases=(FIXTURE,),
- name='collective.fingerpointing:Integration')
+ bases=(FIXTURE,), name='collective.fingerpointing:Integration')
FUNCTIONAL_TESTING = FunctionalTesting(
- bases=(FIXTURE,),
- name='collective.fingerpointing:Functional')
+ bases=(FIXTURE,), name='collective.fingerpointing:Functional')
ROBOT_TESTING = FunctionalTesting(
bases=(FIXTURE, AUTOLOGIN_LIBRARY_FIXTURE, z2.ZSERVER_FIXTURE),
diff --git a/src/collective/fingerpointing/tests/test_controlpanel.py b/src/collective/fingerpointing/tests/test_controlpanel.py
index 0e504c4..7713d31 100644
--- a/src/collective/fingerpointing/tests/test_controlpanel.py
+++ b/src/collective/fingerpointing/tests/test_controlpanel.py
@@ -66,6 +66,10 @@ def test_audit_lifecycle_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'audit_lifecycle'))
self.assertEqual(self.settings.audit_lifecycle, True)
+ def test_audit_workflow_record_in_registry(self):
+ self.assertTrue(hasattr(self.settings, 'audit_workflow'))
+ self.assertEqual(self.settings.audit_workflow, True)
+
def test_audit_registry_record_in_registry(self):
self.assertTrue(hasattr(self.settings, 'audit_registry'))
self.assertEqual(self.settings.audit_registry, True)
@@ -83,6 +87,7 @@ def test_records_removed_on_uninstall(self):
records = [
IFingerPointingSettings.__identifier__ + '.audit_pas',
IFingerPointingSettings.__identifier__ + '.audit_lifecycle',
+ IFingerPointingSettings.__identifier__ + '.audit_workflow',
IFingerPointingSettings.__identifier__ + '.audit_registry',
IFingerPointingSettings.__identifier__ + '.audit_iterate',
]
diff --git a/src/collective/fingerpointing/tests/test_upgrades.py b/src/collective/fingerpointing/tests/test_upgrades.py
index c46cf8a..71b87f0 100644
--- a/src/collective/fingerpointing/tests/test_upgrades.py
+++ b/src/collective/fingerpointing/tests/test_upgrades.py
@@ -120,3 +120,41 @@ def test_update_user_actions(self):
self._do_upgrade(step)
self.assertEqual(user_actions.keys()[-1], 'logout')
self.assertEqual(user_actions.keys()[-2], 'audit-log')
+
+
+class To4TestCase(BaseUpgradeTestCase):
+
+ from_ = '3'
+ to_ = '4'
+
+ def test_profile_version(self):
+ version = self.setup.getLastVersionForProfile(self.profile_id)[0]
+ self.assertEqual(version, self.from_)
+
+ def test_registered_steps(self):
+ steps = len(self.setup.listUpgrades(self.profile_id)[0])
+ self.assertEqual(steps, 1)
+
+ def test_update_user_actions(self):
+ # check if the upgrade step is registered
+ title = u'Add new field audit_workflow to configlet'
+ step = self._get_upgrade_step_by_title(title)
+ assert step is not None
+
+ from collective.fingerpointing.interfaces import IFingerPointingSettings
+ from plone.registry.interfaces import IRegistry
+ from zope.component import getUtility
+ registry = getUtility(IRegistry)
+
+ # simulate state on previous version
+ record = IFingerPointingSettings.__identifier__ + '.audit_workflow'
+ del registry.records[record]
+
+ with self.assertRaises(KeyError):
+ registry.forInterface(IFingerPointingSettings)
+
+ # execute upgrade step and verify changes were applied
+ self._do_upgrade(step)
+ settings = registry.forInterface(IFingerPointingSettings)
+ self.assertTrue(hasattr(settings, 'audit_workflow'))
+ self.assertEqual(settings.audit_workflow, True)
diff --git a/src/collective/fingerpointing/tests/test_workflow_subscriber.py b/src/collective/fingerpointing/tests/test_workflow_subscriber.py
new file mode 100644
index 0000000..120bb5b
--- /dev/null
+++ b/src/collective/fingerpointing/tests/test_workflow_subscriber.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+"""Tests for workflow subscriber."""
+from collective.fingerpointing.config import PROJECTNAME
+from collective.fingerpointing.interfaces import IFingerPointingSettings
+from collective.fingerpointing.testing import INTEGRATION_TESTING
+from logging import INFO
+from plone import api
+from plone.app.testing import setRoles
+from plone.app.testing import TEST_USER_ID
+from testfixtures import LogCapture
+
+import unittest
+
+
+class WorkflowSubscribersTestCase(unittest.TestCase):
+
+ """Tests content type life cycle subscribers."""
+
+ layer = INTEGRATION_TESTING
+
+ def setUp(self):
+ self.portal = self.layer['portal']
+ setRoles(self.portal, TEST_USER_ID, ['Manager'])
+
+ # disable lifecycle audit
+ record = IFingerPointingSettings.__identifier__ + '.audit_lifecycle'
+ api.portal.set_registry_record(record, False)
+
+ def test_workflow_transitions(self):
+ expected = (
+ ('collective.fingerpointing', 'INFO', u'user=test ip=127.0.0.1 action=workflow transition object= transition=submit'),
+ ('collective.fingerpointing', 'INFO', u'user=test ip=127.0.0.1 action=workflow transition object= transition=publish'),
+ ('collective.fingerpointing', 'INFO', u'user=test ip=127.0.0.1 action=workflow transition object= transition=retract'),
+ )
+
+ with LogCapture('collective.fingerpointing', level=INFO) as log:
+ obj = api.content.create(self.portal, 'News Item', 'foo')
+ api.content.transition(obj=obj, transition='submit')
+ api.content.transition(obj=obj, transition='publish')
+ api.content.transition(obj=obj, transition='retract')
+ log.check(*expected)
+
+ def test_susbcriber_ignored_when_package_not_installed(self):
+ # events should not raise errors if package is not installed
+ qi = self.portal['portal_quickinstaller']
+ qi.uninstallProducts(products=[PROJECTNAME])
+
+ obj = api.content.create(self.portal, 'News Item', 'foo')
+ api.content.transition(obj=obj, transition='submit')
+ api.content.transition(obj=obj, transition='publish')
+ api.content.transition(obj=obj, transition='retract')
diff --git a/src/collective/fingerpointing/upgrades/configure.zcml b/src/collective/fingerpointing/upgrades/configure.zcml
index 115301e..ed8f198 100644
--- a/src/collective/fingerpointing/upgrades/configure.zcml
+++ b/src/collective/fingerpointing/upgrades/configure.zcml
@@ -1,4 +1,5 @@
+
diff --git a/src/collective/fingerpointing/upgrades/v4/__init__.py b/src/collective/fingerpointing/upgrades/v4/__init__.py
new file mode 100644
index 0000000..40a96af
--- /dev/null
+++ b/src/collective/fingerpointing/upgrades/v4/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/src/collective/fingerpointing/upgrades/v4/configure.zcml b/src/collective/fingerpointing/upgrades/v4/configure.zcml
new file mode 100644
index 0000000..5f2828c
--- /dev/null
+++ b/src/collective/fingerpointing/upgrades/v4/configure.zcml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+