diff --git a/last_commit.txt b/last_commit.txt index 74226138cd..637fb6a2e5 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,50 +1,38 @@ -Repository: plone.app.multilingual +Repository: plone.locking -Branch: refs/heads/5.6.x -Date: 2021-10-08T02:19:42+02:00 -Author: mamico (mamico) -Commit: https://github.com/plone/plone.app.multilingual/commit/a143e2c953f6eeb0fe01f1e0b8db09d6e016f101 +Branch: refs/heads/master +Date: 2021-10-08T16:51:24+02:00 +Author: Érico Andrei (ericof) +Commit: https://github.com/plone/plone.locking/commit/780f9b69316bf90891fd4ab8fc850f9d98969744 -Disable CSRF protection during the setting of TG attribute. #375 backport +Register a fallback @@plone_lock_info view to allow objects without plone.locking behavior to be edited. Files changed: -M src/plone/app/multilingual/manager.py -M src/plone/app/multilingual/subscriber.py +A news/3331.fix +A plone/locking/tests/test_views.py +M plone/locking/browser/locking.py +M plone/locking/configure.zcml -b"diff --git a/src/plone/app/multilingual/manager.py b/src/plone/app/multilingual/manager.py\nindex 8981e66b..0a3a2f21 100644\n--- a/src/plone/app/multilingual/manager.py\n+++ b/src/plone/app/multilingual/manager.py\n@@ -12,12 +12,15 @@\n from plone.app.multilingual.interfaces import NOTG\n from plone.app.multilingual.itg import addAttributeTG\n from plone.app.uuid.utils import uuidToObject\n+from plone.protect.interfaces import IDisableCSRFProtection\n from plone.uuid.handlers import addAttributeUUID\n from plone.uuid.interfaces import IUUID\n from Products.CMFCore.utils import getToolByName\n from Products.CMFPlone.interfaces import ILanguage\n from zope.component.hooks import getSite\n from zope.event import notify\n+from zope.globalrequest import getRequest\n+from zope.interface import alsoProvides\n from zope.interface import implementer\n \n \n@@ -43,7 +46,7 @@ def get_id(self, context):\n # We must ensure that this case can't happen, any object translatable\n # will have an UUID (in any case we can be at the portal factory!)\n except KeyError:\n- context._v_safe_write = True\n+ alsoProvides(getRequest(), IDisableCSRFProtection)\n addAttributeUUID(context, None)\n context.reindexObject(idxs=['UID'])\n context_id = IUUID(context)\n@@ -57,8 +60,9 @@ def get_tg(self, context):\n try:\n context_id = ITG(context)\n # We must ensure that this case can't happen, any object translatable\n- # will have an UUID (in any case we can be at the portal factory!)\n+ # will have an TG (in any case we can be at the portal factory!)\n except TypeError:\n+ alsoProvides(getRequest(), IDisableCSRFProtection)\n addAttributeTG(context, None)\n context.reindexObject(idxs=['TranslationGroup'])\n context_id = ITG(context)\ndiff --git a/src/plone/app/multilingual/subscriber.py b/src/plone/app/multilingual/subscriber.py\nindex 6069fb7b..42816ad6 100644\n--- a/src/plone/app/multilingual/subscriber.py\n+++ b/src/plone/app/multilingual/subscriber.py\n@@ -5,9 +5,11 @@\n from plone.app.multilingual.interfaces import ILanguageIndependentFolder\n from plone.app.multilingual.interfaces import IMutableTG\n from plone.app.multilingual.interfaces import IPloneAppMultilingualInstalled\n+from plone.app.multilingual.interfaces import ITG\n from plone.app.multilingual.interfaces import ITranslatable\n from plone.app.multilingual.interfaces import ITranslationManager\n from plone.app.multilingual.interfaces import LANGUAGE_INDEPENDENT\n+from plone.app.multilingual.itg import addAttributeTG\n from plone.dexterity.interfaces import IDexterityContent\n from plone.uuid.interfaces import IUUID\n from Products.CMFCore.interfaces import IFolderish\n@@ -116,6 +118,9 @@ def set_recursive_language(ob, language):\n \n elif ILanguage(ob).get_language() != language:\n ILanguage(ob).set_language(language)\n+ if ITG(ob, None) is None:\n+ addAttributeTG(ob, None)\n+ ob.reindexObject(idxs=['TranslationGroup'])\n ITranslationManager(ob).update()\n reindex_object(ob)\n \n" +b'diff --git a/news/3331.fix b/news/3331.fix\nnew file mode 100644\nindex 0000000..9efab5b\n--- /dev/null\n+++ b/news/3331.fix\n@@ -0,0 +1,2 @@\n+Register a fallback @@plone_lock_info view to allow objects without plone.locking behavior to be edited.\n+[ericof]\n\\ No newline at end of file\ndiff --git a/plone/locking/browser/locking.py b/plone/locking/browser/locking.py\nindex 7f4145e..6453bdc 100644\n--- a/plone/locking/browser/locking.py\n+++ b/plone/locking/browser/locking.py\n@@ -161,3 +161,23 @@ def _getNiceTimeDifference(self, baseTime):\n else:\n dateString = _(u"$d days and $h hours", mapping={\'d\': days, \'h\': hours})\n return dateString\n+\n+\n+class LockingInformationFallback(BrowserView):\n+ """Fallback view for Lock information.\n+\n+ This view exists to return sensible defaults if a content type does\n+ not have the plone.locking behavior active.\n+ """\n+\n+ def is_locked(self):\n+ return False\n+\n+ def is_locked_for_current_user(self):\n+ return False\n+\n+ def lock_is_stealable(self):\n+ return False\n+\n+ def lock_info(self):\n+ return None\ndiff --git a/plone/locking/configure.zcml b/plone/locking/configure.zcml\nindex c4890e2..9c8ed2c 100644\n--- a/plone/locking/configure.zcml\n+++ b/plone/locking/configure.zcml\n@@ -22,4 +22,12 @@\n allowed_attributes="is_locked is_locked_for_current_user lock_is_stealable lock_info"\n />\n \n+ \n+\n \ndiff --git a/plone/locking/tests/test_views.py b/plone/locking/tests/test_views.py\nnew file mode 100644\nindex 0000000..412c3b0\n--- /dev/null\n+++ b/plone/locking/tests/test_views.py\n@@ -0,0 +1,44 @@\n+# -*- coding: utf-8 -*-\n+from plone.app.testing import setRoles\n+from plone.app.testing import TEST_USER_ID\n+from plone.locking.browser.locking import LockingInformation\n+from plone.locking.browser.locking import LockingInformationFallback\n+from plone.locking.testing import PLONE_LOCKING_INTEGRATION_TESTING\n+from plone.dexterity.interfaces import IDexterityFTI\n+from zope.component import queryUtility\n+\n+import unittest\n+\n+\n+class TestLockInfoViewWithoutLocking(unittest.TestCase):\n+\n+ layer = PLONE_LOCKING_INTEGRATION_TESTING\n+\n+ view = "@@plone_lock_info"\n+\n+ def setUp(self):\n+ self.app = self.layer["app"]\n+ self.portal = self.layer["portal"]\n+\n+ setRoles(self.portal, TEST_USER_ID, ["Manager", "Site Administrator"])\n+\n+ self.portal.invokeFactory("News Item", id="news1", title="News Item 1")\n+ self.news = self.portal["news1"]\n+\n+ # Remove plone.locking from Document content type\n+ fti = queryUtility(IDexterityFTI, name="Document")\n+ behavior_list = [a for a in fti.behaviors if a != "plone.locking"]\n+ fti.behaviors = tuple(behavior_list)\n+\n+ self.portal.invokeFactory("Document", id="doc1", title="Document 1")\n+ self.doc = self.portal["doc1"]\n+\n+ def test_browser_view_available_for_content_with_locking_behavior(self):\n+ content = self.news\n+ view = content.restrictedTraverse(self.view)\n+ self.assertIsInstance(view, LockingInformation)\n+\n+ def test_browser_view_available_for_content_without_locking_behavior(self):\n+ content = self.doc\n+ view = content.restrictedTraverse(self.view)\n+ self.assertIsInstance(view, LockingInformationFallback)\n' -Repository: plone.app.multilingual +Repository: plone.locking -Branch: refs/heads/5.6.x -Date: 2021-10-08T02:22:37+02:00 -Author: mamico (mamico) -Commit: https://github.com/plone/plone.app.multilingual/commit/0aff30fe47fb95da3a0f2a56c35051494db33f25 - -changelog - -Files changed: -A news/393.bugfix - -b'diff --git a/news/393.bugfix b/news/393.bugfix\nnew file mode 100644\nindex 00000000..ebfb25ba\n--- /dev/null\n+++ b/news/393.bugfix\n@@ -0,0 +1 @@\n+Disable CSRF protection during the setting of TG attribute. #375 backport [mamico]\n' - -Repository: plone.app.multilingual - - -Branch: refs/heads/5.6.x -Date: 2021-10-08T08:53:07+02:00 +Branch: refs/heads/master +Date: 2021-10-08T23:33:43+02:00 Author: Maurits van Rees (mauritsvanrees) -Commit: https://github.com/plone/plone.app.multilingual/commit/ebd2a9903119745de905f6ff47f0dad8ff57fd13 +Commit: https://github.com/plone/plone.locking/commit/16f132198012601b9b433f346c0a81b19a26be5e -Merge pull request #393 from plone/mamico/safewrite-5.6 +Merge pull request #18 from plone/issue-3331-removing-lock-behavior -Disable CSRF protection during the setting of TG attribute. #375 backport +Add fallback plone_lock_info view Files changed: -A news/393.bugfix -M src/plone/app/multilingual/manager.py -M src/plone/app/multilingual/subscriber.py +A news/3331.fix +A plone/locking/tests/test_views.py +M plone/locking/browser/locking.py +M plone/locking/configure.zcml -b"diff --git a/news/393.bugfix b/news/393.bugfix\nnew file mode 100644\nindex 00000000..ebfb25ba\n--- /dev/null\n+++ b/news/393.bugfix\n@@ -0,0 +1 @@\n+Disable CSRF protection during the setting of TG attribute. #375 backport [mamico]\ndiff --git a/src/plone/app/multilingual/manager.py b/src/plone/app/multilingual/manager.py\nindex 8981e66b..0a3a2f21 100644\n--- a/src/plone/app/multilingual/manager.py\n+++ b/src/plone/app/multilingual/manager.py\n@@ -12,12 +12,15 @@\n from plone.app.multilingual.interfaces import NOTG\n from plone.app.multilingual.itg import addAttributeTG\n from plone.app.uuid.utils import uuidToObject\n+from plone.protect.interfaces import IDisableCSRFProtection\n from plone.uuid.handlers import addAttributeUUID\n from plone.uuid.interfaces import IUUID\n from Products.CMFCore.utils import getToolByName\n from Products.CMFPlone.interfaces import ILanguage\n from zope.component.hooks import getSite\n from zope.event import notify\n+from zope.globalrequest import getRequest\n+from zope.interface import alsoProvides\n from zope.interface import implementer\n \n \n@@ -43,7 +46,7 @@ def get_id(self, context):\n # We must ensure that this case can't happen, any object translatable\n # will have an UUID (in any case we can be at the portal factory!)\n except KeyError:\n- context._v_safe_write = True\n+ alsoProvides(getRequest(), IDisableCSRFProtection)\n addAttributeUUID(context, None)\n context.reindexObject(idxs=['UID'])\n context_id = IUUID(context)\n@@ -57,8 +60,9 @@ def get_tg(self, context):\n try:\n context_id = ITG(context)\n # We must ensure that this case can't happen, any object translatable\n- # will have an UUID (in any case we can be at the portal factory!)\n+ # will have an TG (in any case we can be at the portal factory!)\n except TypeError:\n+ alsoProvides(getRequest(), IDisableCSRFProtection)\n addAttributeTG(context, None)\n context.reindexObject(idxs=['TranslationGroup'])\n context_id = ITG(context)\ndiff --git a/src/plone/app/multilingual/subscriber.py b/src/plone/app/multilingual/subscriber.py\nindex 6069fb7b..42816ad6 100644\n--- a/src/plone/app/multilingual/subscriber.py\n+++ b/src/plone/app/multilingual/subscriber.py\n@@ -5,9 +5,11 @@\n from plone.app.multilingual.interfaces import ILanguageIndependentFolder\n from plone.app.multilingual.interfaces import IMutableTG\n from plone.app.multilingual.interfaces import IPloneAppMultilingualInstalled\n+from plone.app.multilingual.interfaces import ITG\n from plone.app.multilingual.interfaces import ITranslatable\n from plone.app.multilingual.interfaces import ITranslationManager\n from plone.app.multilingual.interfaces import LANGUAGE_INDEPENDENT\n+from plone.app.multilingual.itg import addAttributeTG\n from plone.dexterity.interfaces import IDexterityContent\n from plone.uuid.interfaces import IUUID\n from Products.CMFCore.interfaces import IFolderish\n@@ -116,6 +118,9 @@ def set_recursive_language(ob, language):\n \n elif ILanguage(ob).get_language() != language:\n ILanguage(ob).set_language(language)\n+ if ITG(ob, None) is None:\n+ addAttributeTG(ob, None)\n+ ob.reindexObject(idxs=['TranslationGroup'])\n ITranslationManager(ob).update()\n reindex_object(ob)\n \n" +b'diff --git a/news/3331.fix b/news/3331.fix\nnew file mode 100644\nindex 0000000..9efab5b\n--- /dev/null\n+++ b/news/3331.fix\n@@ -0,0 +1,2 @@\n+Register a fallback @@plone_lock_info view to allow objects without plone.locking behavior to be edited.\n+[ericof]\n\\ No newline at end of file\ndiff --git a/plone/locking/browser/locking.py b/plone/locking/browser/locking.py\nindex 7f4145e..6453bdc 100644\n--- a/plone/locking/browser/locking.py\n+++ b/plone/locking/browser/locking.py\n@@ -161,3 +161,23 @@ def _getNiceTimeDifference(self, baseTime):\n else:\n dateString = _(u"$d days and $h hours", mapping={\'d\': days, \'h\': hours})\n return dateString\n+\n+\n+class LockingInformationFallback(BrowserView):\n+ """Fallback view for Lock information.\n+\n+ This view exists to return sensible defaults if a content type does\n+ not have the plone.locking behavior active.\n+ """\n+\n+ def is_locked(self):\n+ return False\n+\n+ def is_locked_for_current_user(self):\n+ return False\n+\n+ def lock_is_stealable(self):\n+ return False\n+\n+ def lock_info(self):\n+ return None\ndiff --git a/plone/locking/configure.zcml b/plone/locking/configure.zcml\nindex c4890e2..9c8ed2c 100644\n--- a/plone/locking/configure.zcml\n+++ b/plone/locking/configure.zcml\n@@ -22,4 +22,12 @@\n allowed_attributes="is_locked is_locked_for_current_user lock_is_stealable lock_info"\n />\n \n+ \n+\n \ndiff --git a/plone/locking/tests/test_views.py b/plone/locking/tests/test_views.py\nnew file mode 100644\nindex 0000000..412c3b0\n--- /dev/null\n+++ b/plone/locking/tests/test_views.py\n@@ -0,0 +1,44 @@\n+# -*- coding: utf-8 -*-\n+from plone.app.testing import setRoles\n+from plone.app.testing import TEST_USER_ID\n+from plone.locking.browser.locking import LockingInformation\n+from plone.locking.browser.locking import LockingInformationFallback\n+from plone.locking.testing import PLONE_LOCKING_INTEGRATION_TESTING\n+from plone.dexterity.interfaces import IDexterityFTI\n+from zope.component import queryUtility\n+\n+import unittest\n+\n+\n+class TestLockInfoViewWithoutLocking(unittest.TestCase):\n+\n+ layer = PLONE_LOCKING_INTEGRATION_TESTING\n+\n+ view = "@@plone_lock_info"\n+\n+ def setUp(self):\n+ self.app = self.layer["app"]\n+ self.portal = self.layer["portal"]\n+\n+ setRoles(self.portal, TEST_USER_ID, ["Manager", "Site Administrator"])\n+\n+ self.portal.invokeFactory("News Item", id="news1", title="News Item 1")\n+ self.news = self.portal["news1"]\n+\n+ # Remove plone.locking from Document content type\n+ fti = queryUtility(IDexterityFTI, name="Document")\n+ behavior_list = [a for a in fti.behaviors if a != "plone.locking"]\n+ fti.behaviors = tuple(behavior_list)\n+\n+ self.portal.invokeFactory("Document", id="doc1", title="Document 1")\n+ self.doc = self.portal["doc1"]\n+\n+ def test_browser_view_available_for_content_with_locking_behavior(self):\n+ content = self.news\n+ view = content.restrictedTraverse(self.view)\n+ self.assertIsInstance(view, LockingInformation)\n+\n+ def test_browser_view_available_for_content_without_locking_behavior(self):\n+ content = self.doc\n+ view = content.restrictedTraverse(self.view)\n+ self.assertIsInstance(view, LockingInformationFallback)\n'