Commit f4338e7e authored by Jérome Perrin's avatar Jérome Perrin

ERP5Type: don't publish workflow methods

Wrapping a method in a workflow method should not change the
publishable state the method.
If the original method is not publishable, wrapping it in a workflow
method should not make it publishable.  If the original method is
publishable, then the wrapped method should still be publishable.

This was always intended to work like this, as we can see in the code
comment in `WorkflowMethod.__init__` but was not properly tested and got
broken at some point.

It's important to restore the behavior, because workflow methods such as
`validate` should not be published, users must only be able to use the
user interface transitions freely, workflow methods transitions are
only available if developer expose them in a script - and perform the
necessary consistency and security checks in that script.
parent 038b7a14
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
############################################################################## ##############################################################################
import unittest import unittest
import httplib
import transaction import transaction
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
...@@ -613,6 +614,18 @@ context.setTitle('Bar') ...@@ -613,6 +614,18 @@ context.setTitle('Bar')
# two calls: one to _setProperty, and one to _setDescription # two calls: one to _setProperty, and one to _setDescription
self.assertEqual(len(call_list), 6) self.assertEqual(len(call_list), 6)
def test_interaction_workflow_methods_are_published(self):
"""Wrapping a publishable method in an interaction workflow does not prevent its publication.
"""
self.assertIsNotNone(self.organisation.getTitle.__doc__)
self.createInteractionWorkflow()
self.interaction.setProperties('default', method_id='getTitle')
self.assertIsNotNone(self.organisation.getTitle.__doc__)
self.organisation.setTitle(self.id())
ret = self.publish('%s/getTitle' % self.organisation.getPath(), basic='ERP5TypeTestCase:')
self.assertEqual(httplib.OK, ret.getStatus())
self.assertEqual(self.id(), ret.getBody())
def test_security(self): def test_security(self):
# wrapping a method in an interaction workflow adds a default security to # wrapping a method in an interaction workflow adds a default security to
......
...@@ -166,7 +166,8 @@ class WorkflowMethod(Method): ...@@ -166,7 +166,8 @@ class WorkflowMethod(Method):
# This is intentional to prevent methods such as submit, share to # This is intentional to prevent methods such as submit, share to
# be called from a URL. If someone can show that this way # be called from a URL. If someone can show that this way
# is wrong (ex. for remote operation of a site), let us know. # is wrong (ex. for remote operation of a site), let us know.
if not method.__name__.startswith('_'): self.__doc__ = method.__doc__
if method.__name__.startswith('_') or method.__doc__ is None:
self.__name__ = method.__name__ self.__name__ = method.__name__
for func_id in ['func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']: for func_id in ['func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']:
setattr(self, func_id, getattr(method, func_id, None)) setattr(self, func_id, getattr(method, func_id, None))
......
...@@ -33,7 +33,7 @@ except ImportError: # BBB: ZODB < 4 ...@@ -33,7 +33,7 @@ except ImportError: # BBB: ZODB < 4
import unittest import unittest
import sys import sys
import mock import mock
import httplib
import transaction import transaction
from random import randint from random import randint
from unittest import expectedFailure from unittest import expectedFailure
...@@ -3024,6 +3024,14 @@ return True''') ...@@ -3024,6 +3024,14 @@ return True''')
person.validate() person.validate()
self.assertRaises(WorkflowException, person.validate) self.assertRaises(WorkflowException, person.validate)
def test_workflow_transitions_are_not_published(self):
person = self.getPersonModule().newContent(portal_type='Person')
# workflow methods are not published by zope because they don't have a __doc__ attribute
self.assertIsNone(person.validate.__doc__)
ret = self.publish('%s/validate' % person.getPath(), basic='ERP5TypeTestCase:')
self.assertEqual(httplib.NOT_FOUND, ret.getStatus())
self.assertEqual('draft', person.getValidationState())
def test_PropertyConstantGetter(self): def test_PropertyConstantGetter(self):
""" """
Check the boolean constant getter. Make sure Check the boolean constant getter. Make sure
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment