-
-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move security control panel to z3c.form. #216
Comments
Also replaced portal_properties lookups with plone.app.registry lookups and added a robot test.
I did some additional work on this, but it's not ready to merge yet. I'll try to find some time to work on it before NYE. |
What exactly is missing? Could you maybe create a todo list? I'd like to help if possible. |
@jcerjak I took your pull requests, fixed all failing tests and created new pull requests: #329 |
FYI: I added a question regarding the (last) failing csrf protection test: https://github.com/plone/Products.CMFPlone/pull/329/files#diff-d1fcf3ddc12f39ad335b7ddf19472bbfR182 |
@tisto , thanks! Here is my to-do list from some time ago, not sure if everything is still relevant:
|
@jcerjak I merged the pull requests yesterday. We can now work on the master branches. Would you mind going through your todo list and check if all those issues have been taken care of? I'd like to focus on the two last remaining control panels. |
@tisto, thanks, I'll work on it this week. |
@jcerjak Any updates? We would like to close this issue if possible. If there is still work to do maybe you can give us an heads up so people at the sprint can work on that. |
I've updated the list of things to fix, see: #216 (comment) I'll start with the last two items on that list, I'd appreciate feedback on things that block other items. |
I did some progress on this on the Alpine City Sprint, I hope to wrap it up today/tomorrow. |
Pull request opened: #362 |
Branch: refs/heads/master Date: 2015-01-25T12:29:31+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.robotframework@44dee80 Read "use_email_as_login" from registry instead of portal properties Files changed: M CHANGES.txt M src/plone/app/robotframework/users.py diff --git a/CHANGES.txt b/CHANGES.txt index 373e43d..8de3ba7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,7 +4,9 @@ Changelog 0.9.9 (unreleased) ------------------ -- Nothing changed yet. +- Read ``use_email_as_login`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] 0.9.8 (2014-11-11) diff --git a/src/plone/app/robotframework/users.py b/src/plone/app/robotframework/users.py index 22daf44..2603ea5 100644 --- a/src/plone/app/robotframework/users.py +++ b/src/plone/app/robotframework/users.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- from Products.CMFCore.utils import getToolByName -from zope.component.hooks import getSite +from Products.CMFPlone.interfaces import ISecuritySchema from plone.app.robotframework.remote import RemoteLibrary +from plone.registry.interfaces import IRegistry +from zope.component import getUtility +from zope.component.hooks import getSite class Users(RemoteLibrary): @@ -26,10 +29,13 @@ def create_user(self, *args, **kwargs): portal = getSite() registration = getToolByName(portal, 'portal_registration') - portal_properties = getToolByName(portal, 'portal_properties') - use_email_as_username =\ - portal_properties.site_properties.use_email_as_login + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + use_email_as_username = settings.use_email_as_login user_id = use_email_as_username and properties['email'] or username password = properties.pop('password', username) Repository: plone.app.robotframework Branch: refs/heads/master Date: 2015-02-01T15:49:46+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.robotframework@a565754 restore Plone 4 compatibility Files changed: M src/plone/app/robotframework/users.py diff --git a/src/plone/app/robotframework/users.py b/src/plone/app/robotframework/users.py index 2603ea5..c92f296 100644 --- a/src/plone/app/robotframework/users.py +++ b/src/plone/app/robotframework/users.py @@ -1,11 +1,16 @@ # -*- coding: utf-8 -*- from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.interfaces import ISecuritySchema from plone.app.robotframework.remote import RemoteLibrary from plone.registry.interfaces import IRegistry from zope.component import getUtility from zope.component.hooks import getSite +HAS_SECURITY_SETTINGS = True +try: + from Products.CMFPlone.interfaces import ISecuritySchema +except ImportError: + HAS_SECURITY_SETTINGS = False + class Users(RemoteLibrary): @@ -30,12 +35,17 @@ def create_user(self, *args, **kwargs): portal = getSite() registration = getToolByName(portal, 'portal_registration') - registry = getUtility(IRegistry) - settings = registry.forInterface( - ISecuritySchema, - prefix='plone', - ) - use_email_as_username = settings.use_email_as_login + if HAS_SECURITY_SETTINGS: # Plone 5 + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + use_email_as_username = settings.use_email_as_login + else: # Plone < 5 + portal_properties = getToolByName(portal, 'portal_properties') + use_email_as_username = \ + portal_properties.site_properties.use_email_as_login user_id = use_email_as_username and properties['email'] or username password = properties.pop('password', username) Repository: plone.app.robotframework Branch: refs/heads/master Date: 2015-02-04T22:27:46+02:00 Author: Asko Soukka (datakurre) <asko.soukka@iki.fi> Commit: plone/plone.app.robotframework@c5e344a Merge pull request #35 from plone/plip10359-security-controlpanel Plip 10359 - Security Control Panel migration Files changed: M CHANGES.txt M src/plone/app/robotframework/users.py diff --git a/CHANGES.txt b/CHANGES.txt index 373e43d..8de3ba7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,7 +4,9 @@ Changelog 0.9.9 (unreleased) ------------------ -- Nothing changed yet. +- Read ``use_email_as_login`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] 0.9.8 (2014-11-11) diff --git a/src/plone/app/robotframework/users.py b/src/plone/app/robotframework/users.py index 22daf44..c92f296 100644 --- a/src/plone/app/robotframework/users.py +++ b/src/plone/app/robotframework/users.py @@ -1,7 +1,15 @@ # -*- coding: utf-8 -*- from Products.CMFCore.utils import getToolByName -from zope.component.hooks import getSite from plone.app.robotframework.remote import RemoteLibrary +from plone.registry.interfaces import IRegistry +from zope.component import getUtility +from zope.component.hooks import getSite + +HAS_SECURITY_SETTINGS = True +try: + from Products.CMFPlone.interfaces import ISecuritySchema +except ImportError: + HAS_SECURITY_SETTINGS = False class Users(RemoteLibrary): @@ -26,10 +34,18 @@ def create_user(self, *args, **kwargs): portal = getSite() registration = getToolByName(portal, 'portal_registration') - portal_properties = getToolByName(portal, 'portal_properties') - use_email_as_username =\ - portal_properties.site_properties.use_email_as_login + if HAS_SECURITY_SETTINGS: # Plone 5 + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + use_email_as_username = settings.use_email_as_login + else: # Plone < 5 + portal_properties = getToolByName(portal, 'portal_properties') + use_email_as_username = \ + portal_properties.site_properties.use_email_as_login user_id = use_email_as_username and properties['email'] or username password = properties.pop('password', username)
Branch: refs/heads/master Date: 2015-02-15T17:31:58-08:00 Author: David Glick (davisagli) <david@glicksoftware.com> Commit: plone/plone.app.robotframework@1b809c7 find mockup-based modals too Files changed: M CHANGES.txt M src/plone/app/robotframework/keywords.robot diff --git a/CHANGES.txt b/CHANGES.txt index 8de3ba7..6cc6e84 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,10 @@ Changelog 0.9.9 (unreleased) ------------------ +- Also detect mockup-based modals in the "Click Overlay Link" and + "Click Overlay Button" keywords. + [davisagli] + - Read ``use_email_as_login`` setting from the registry instead of portal properties (see plone/Products.CMFPlone#216). [jcerjak] diff --git a/src/plone/app/robotframework/keywords.robot b/src/plone/app/robotframework/keywords.robot index 4e83420..efbd616 100644 --- a/src/plone/app/robotframework/keywords.robot +++ b/src/plone/app/robotframework/keywords.robot @@ -103,15 +103,15 @@ Log out Click Overlay Link [Arguments] ${element} Click Link ${element} - Wait until keyword succeeds 10 1 Page Should Contain Element css=.pb-ajax > div - Element Should Be Visible css=.pb-ajax > div + Wait until keyword succeeds 10 1 Page Should Contain Element css=.pb-ajax > div,.plone-modal + Element Should Be Visible css=.pb-ajax > div,.plone-modal Click Overlay Button [Arguments] ${element} Click Button ${element} - Wait until page contains element css=.pb-ajax > div - Page Should Contain Element css=.pb-ajax > div - Element Should Be Visible css=.pb-ajax > div + Wait until page contains element css=.pb-ajax > div,.plone-modal + Page Should Contain Element css=.pb-ajax > div,.plone-modal + Element Should Be Visible css=.pb-ajax > div,.plone-modal Should be above [Arguments] ${locator1} ${locator2}
Hey @jcerjak, I plan to work on this today. I just merged master into all repos. Though, I see quite a few test failures in CMFPlone now. Do you have time for a quick chat on IRC? |
Branch: refs/heads/master Date: 2015-01-25T20:15:31+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.search@15427c4 read "allow_anon_views_about" from registry instead of properties Files changed: M CHANGES.rst M plone/app/search/search.pt diff --git a/CHANGES.rst b/CHANGES.rst index 8a05d5c..a1ea647 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,9 @@ Changelog 1.2.3 (unreleased) ------------------ -- Nothing changed yet. +- Read ``allow_anon_views_about`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] 1.2.2 (2014-10-23) diff --git a/plone/app/search/search.pt b/plone/app/search/search.pt index 2549364..9ae4233 100644 --- a/plone/app/search/search.pt +++ b/plone/app/search/search.pt @@ -147,7 +147,7 @@ <div class="search-type-options"> <tal:div tal:define="typeLists python:context.createMultiColumnList(types_list, numCols=2, sort_on='self');" - + tal:repeat="sublist typeLists"> <tal:items repeat="type sublist"> <div> @@ -240,7 +240,7 @@ </dl> - + </div> @@ -275,8 +275,8 @@ toLocalizedTime nocall: context/@@plone/toLocalizedTime; site_properties context/portal_properties/site_properties; use_view_action site_properties/typesUseViewActionInListings|python:(); - allowAnonymousViewAbout site_properties/allowAnonymousViewAbout; - show_about python:not isAnon or allowAnonymousViewAbout;"> + allow_anon_views_about python:context.portal_registry['plone.allow_anon_views_about']; + show_about python:not isAnon or allow_anon_views_about;"> <ol class="searchResults"> <tal:results repeat="item batch"> <li> Repository: plone.app.search Branch: refs/heads/master Date: 2015-02-27T07:47:52+01:00 Author: Timo Stollenwerk () <contact@timostollenwerk.net> Commit: plone/plone.app.search@c233aec Merge branch 'master' into plip10359-security-controlpanel Files changed: M README.rst diff --git a/README.rst b/README.rst index 6868b6f..a42c0fb 100644 --- a/README.rst +++ b/README.rst @@ -8,4 +8,6 @@ plone.app.search also updates main search field (usually located at the top righ plone.app.search has the aim to give intuitively clear and understandable interface for searching in Plone. But there might be some new things that are not so obvious. Let's see how the search results works now. Notes -===== \ No newline at end of file +===== + +This package is merged into Products.CMFPlone in Plone 5. Repository: plone.app.search Branch: refs/heads/master Date: 2015-02-27T08:35:10+01:00 Author: Timo Stollenwerk (tisto) <tisto@plone.org> Commit: plone/plone.app.search@9c7459b Merge pull request #14 from plone/plip10359-security-controlpanel Plip 10359 - Security Control Panel migration Files changed: M CHANGES.rst M plone/app/search/search.pt diff --git a/CHANGES.rst b/CHANGES.rst index 8a05d5c..a1ea647 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,9 @@ Changelog 1.2.3 (unreleased) ------------------ -- Nothing changed yet. +- Read ``allow_anon_views_about`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] 1.2.2 (2014-10-23) diff --git a/plone/app/search/search.pt b/plone/app/search/search.pt index 2549364..9ae4233 100644 --- a/plone/app/search/search.pt +++ b/plone/app/search/search.pt @@ -147,7 +147,7 @@ <div class="search-type-options"> <tal:div tal:define="typeLists python:context.createMultiColumnList(types_list, numCols=2, sort_on='self');" - + tal:repeat="sublist typeLists"> <tal:items repeat="type sublist"> <div> @@ -240,7 +240,7 @@ </dl> - + </div> @@ -275,8 +275,8 @@ toLocalizedTime nocall: context/@@plone/toLocalizedTime; site_properties context/portal_properties/site_properties; use_view_action site_properties/typesUseViewActionInListings|python:(); - allowAnonymousViewAbout site_properties/allowAnonymousViewAbout; - show_about python:not isAnon or allowAnonymousViewAbout;"> + allow_anon_views_about python:context.portal_registry['plone.allow_anon_views_about']; + show_about python:not isAnon or allow_anon_views_about;"> <ol class="searchResults"> <tal:results repeat="item batch"> <li>
I created a Jenkins job, see console output for test failures: http://jenkins.plone.org/job/PLIP-10359/3/console |
Branch: refs/heads/master Date: 2015-01-25T20:33:16+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.portlets@3a154ee Read "use_email_as_login" from registry instead of properties Files changed: M CHANGES.rst M plone/app/portlets/portlets/login.pt diff --git a/CHANGES.rst b/CHANGES.rst index 3a4ad10..93bcdd1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,10 @@ Changelog 3.0.3 (unreleased) ------------------ +- Read ``use_email_as_login`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] + - Use plone_layout for getIcon. [pbauer] diff --git a/plone/app/portlets/portlets/login.pt b/plone/app/portlets/portlets/login.pt index d210276..606737f 100644 --- a/plone/app/portlets/portlets/login.pt +++ b/plone/app/portlets/portlets/login.pt @@ -30,7 +30,7 @@ </div> <div class="field" - tal:define="use_email_as_login context/portal_properties/site_properties/use_email_as_login|nothing;"> + tal:define="use_email_as_login python:context.portal_registry['plone.use_email_as_login'];"> <tal:loginname condition="not:use_email_as_login"> <label for="" Repository: plone.app.portlets Branch: refs/heads/master Date: 2015-02-27T07:48:27+01:00 Author: Timo Stollenwerk () <contact@timostollenwerk.net> Commit: plone/plone.app.portlets@ac46445 Merge branch 'master' into plip10359-security-controlpanel Conflicts: CHANGES.rst Files changed: M CHANGES.rst M plone/app/portlets/browser/templates/manage-contextual.pt M plone/app/portlets/browser/templates/topbar-manage-portlets.pt M plone/app/portlets/portlets/recent.pt diff --git a/CHANGES.rst b/CHANGES.rst index 93bcdd1..f206468 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,9 @@ Changelog properties (see plone/Products.CMFPlone#216). [jcerjak] +- Fix missing definitions of ``plone_view``. Fixes the recent portlet. + [thet] + - Use plone_layout for getIcon. [pbauer] diff --git a/plone/app/portlets/browser/templates/manage-contextual.pt b/plone/app/portlets/browser/templates/manage-contextual.pt index 1db5528..d01927c 100644 --- a/plone/app/portlets/browser/templates/manage-contextual.pt +++ b/plone/app/portlets/browser/templates/manage-contextual.pt @@ -13,7 +13,7 @@ </head> <body> -<metal:main fill-slot="main" tal:define="ploneview context/@@plone"> +<metal:main fill-slot="main" tal:define="plone_view context/@@plone"> <h1 class="documentFirstHeading" i18n:translate="title_manage_contextual_portlets"> @@ -40,7 +40,7 @@ </tal:block> <div class="portalMessage info" - tal:condition="ploneview/isDefaultPageInFolder|nothing"> + tal:condition="plone_view/isDefaultPageInFolder|nothing"> <strong i18n:translate=""> Info </strong> diff --git a/plone/app/portlets/browser/templates/topbar-manage-portlets.pt b/plone/app/portlets/browser/templates/topbar-manage-portlets.pt index f501d48..f8199e4 100644 --- a/plone/app/portlets/browser/templates/topbar-manage-portlets.pt +++ b/plone/app/portlets/browser/templates/topbar-manage-portlets.pt @@ -6,9 +6,9 @@ i18n:domain="plone"> <body> - <div metal:fill-slot="main"> + <div metal:fill-slot="main" tal:define="plone_view context/@@plone"> <div class="portalMessage info" - tal:condition="ploneview/isDefaultPageInFolder|nothing"> + tal:condition="plone_view/isDefaultPageInFolder|nothing"> <strong> Info </strong> diff --git a/plone/app/portlets/portlets/recent.pt b/plone/app/portlets/portlets/recent.pt index f5c0a26..a5ab758 100644 --- a/plone/app/portlets/portlets/recent.pt +++ b/plone/app/portlets/portlets/recent.pt @@ -15,6 +15,7 @@ tal:condition="view/recent_items"> <ul> <tal:items tal:define="plone_layout context/@@plone_layout; + plone_view context/@@plone; getIcon nocall:plone_layout/getIcon; normalizeString nocall:plone_view/normalizeString; toLocalizedTime nocall:plone_view/toLocalizedTime;" Repository: plone.app.portlets Branch: refs/heads/master Date: 2015-02-27T09:05:39+01:00 Author: Timo Stollenwerk (tisto) <tisto@plone.org> Commit: plone/plone.app.portlets@0842bd5 Merge pull request #46 from plone/plip10359-security-controlpanel Plip 10359 - Security Control Panel migration Files changed: M CHANGES.rst M plone/app/portlets/portlets/login.pt diff --git a/CHANGES.rst b/CHANGES.rst index 186b99b..f206468 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,10 @@ Changelog 3.0.3 (unreleased) ------------------ +- Read ``use_email_as_login`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] + - Fix missing definitions of ``plone_view``. Fixes the recent portlet. [thet] diff --git a/plone/app/portlets/portlets/login.pt b/plone/app/portlets/portlets/login.pt index d210276..606737f 100644 --- a/plone/app/portlets/portlets/login.pt +++ b/plone/app/portlets/portlets/login.pt @@ -30,7 +30,7 @@ </div> <div class="field" - tal:define="use_email_as_login context/portal_properties/site_properties/use_email_as_login|nothing;"> + tal:define="use_email_as_login python:context.portal_registry['plone.use_email_as_login'];"> <tal:loginname condition="not:use_email_as_login"> <label for=""
Branch: refs/heads/master Date: 2015-01-24T16:02:38+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/Products.PasswordResetTool@3b81f12 update browser.txt to reflect changes in CMFPlone validate_email was replaced by enable_user_pwd_choice Files changed: M Products/PasswordResetTool/tests/browser.txt diff --git a/Products/PasswordResetTool/tests/browser.txt b/Products/PasswordResetTool/tests/browser.txt index b9a573e..5876c79 100644 --- a/Products/PasswordResetTool/tests/browser.txt +++ b/Products/PasswordResetTool/tests/browser.txt @@ -25,9 +25,9 @@ distinct password policies regarding member registration. B. A password is generated for the users (and an e-mail with login credentials is sent automatically). -This policy can enabled or disabled in the ``validate_email`` property -on the Plone Site object. By default ``validate_email`` is enabled -and the second policy applies. +This policy can be enabled or disabled with the ``enable_user_pwd_choice`` +setting in the security control panel. By default ``enable_user_pwd_choice`` is +disabled and the second policy applies. Another aspect we have to take into account is the fact that Plone by default only allows Administrators to register (other) members, but allowing Repository: Products.PasswordResetTool Branch: refs/heads/master Date: 2015-01-25T17:09:01+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/Products.PasswordResetTool@5a9bacc Read use_email_as_login from registry instead of portal properties Files changed: M CHANGES.txt M Products/PasswordResetTool/PasswordResetTool.py M Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt diff --git a/CHANGES.txt b/CHANGES.txt index 4a3883f..3a66e3f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,10 @@ Changelog 2.1.2 (unreleased) ------------------ +- Read ``use_email_as_login`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] + - Amend browser.txt test to the new p.a.registry-based control panels (Plone 5 only). [timo] diff --git a/Products/PasswordResetTool/PasswordResetTool.py b/Products/PasswordResetTool/PasswordResetTool.py index dd03c3e..20d95aa 100644 --- a/Products/PasswordResetTool/PasswordResetTool.py +++ b/Products/PasswordResetTool/PasswordResetTool.py @@ -19,7 +19,9 @@ from App.special_dtml import DTMLFile from AccessControl import ClassSecurityInfo from AccessControl import ModuleSecurityInfo +from plone.registry.interfaces import IRegistry from Products.CMFCore.permissions import ManagePortal +from Products.CMFPlone.interfaces import ISecuritySchema try: from Products.CMFPlone.RegistrationTool import get_member_by_login_name except ImportError: @@ -33,6 +35,7 @@ import time import socket from DateTime import DateTime +from zope.component import getUtility from zope.interface import implements module_security = ModuleSecurityInfo('Products.PasswordResetTool.PasswordResetTool') @@ -346,8 +349,10 @@ def expirationDate(self): def getValidUser(self, userid): """Returns the member with 'userid' if available and None otherwise.""" if get_member_by_login_name: - props = getToolByName(self, 'portal_properties').site_properties - if props.getProperty('use_email_as_login', False): + registry = getUtility(IRegistry) + settings = registry.forInterface(ISecuritySchema, prefix='plone') + + if settings.use_email_as_login: return get_member_by_login_name( self, userid, raise_exceptions=False) membertool = getToolByName(self, 'portal_membership') diff --git a/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt b/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt index 53d325a..53be415 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt +++ b/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt @@ -32,7 +32,7 @@ <div class="field" tal:define="error errors/userid | nothing; site_properties context/portal_properties/site_properties; - use_email_as_login site_properties/use_email_as_login|nothing;" + use_email_as_login python:context.portal_registry['plone.use_email_as_login'];" tal:attributes="class python:test(error, 'field error', 'field')" tal:condition="here/portal_password_reset/checkUser | nothing"> Repository: Products.PasswordResetTool Branch: refs/heads/master Date: 2015-01-25T20:39:07+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/Products.PasswordResetTool@d1b381b fix "use_email_as_login" in other templates as well Files changed: M Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt M Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt diff --git a/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt b/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt index 03daaad..d23c1f1 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt +++ b/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt @@ -14,7 +14,7 @@ <metal:main fill-slot="main" tal:define="global props context/@@plone_tools/properties; - use_email_as_login props/site_properties/use_email_as_login|nothing;"> + use_email_as_login python:context.portal_registry['plone.use_email_as_login'];"> <h1 class="documentFirstHeading" i18n:translate="heading_lost_password">Lost Password</h1> diff --git a/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt b/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt index 755ed7e..417cf2f 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt +++ b/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt @@ -6,7 +6,7 @@ <metal:main fill-slot="main" tal:define="site_properties context/portal_properties/site_properties; - use_email_as_login site_properties/use_email_as_login|nothing;"> + use_email_as_login python:context.portal_registry['plone.use_email_as_login'];"> <h1 class="documentFirstHeading" i18n:translate="heading_pwreset_invalid">Error setting password</h1> Repository: Products.PasswordResetTool Branch: refs/heads/master Date: 2015-02-27T07:50:34+01:00 Author: Timo Stollenwerk () <contact@timostollenwerk.net> Commit: plone/Products.PasswordResetTool@a529ec2 Merge branch 'master' into plip10359-security-controlpanel Files changed: M CHANGES.txt M Products/PasswordResetTool/skins/PasswordReset/mail_password_template.pt M Products/PasswordResetTool/tests/browser.txt diff --git a/CHANGES.txt b/CHANGES.txt index 3a66e3f..95ac758 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,6 +11,8 @@ Changelog - Amend browser.txt test to the new p.a.registry-based control panels (Plone 5 only). [timo] +- Added userid information in reset mail (useful when the administrator resets a user password) + [sgeulette] 2.1.1 (2014-10-22) diff --git a/Products/PasswordResetTool/skins/PasswordReset/mail_password_template.pt b/Products/PasswordResetTool/skins/PasswordReset/mail_password_template.pt index 792967e..d5a57a1 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/mail_password_template.pt +++ b/Products/PasswordResetTool/skins/PasswordReset/mail_password_template.pt @@ -3,6 +3,7 @@ member python:options['member']; portal_state context/@@plone_portal_state; view context/@@passwordreset_view; + isAnon context/@@plone_portal_state/anonymous; reset python:options['reset']" >From: <span tal:replace="structure view/encoded_mail_sender" /> To: <span tal:replace="python:member.getProperty('email')" /> @@ -10,6 +11,15 @@ Subject: <span tal:replace="view/mail_password_subject" /> Precedence: bulk <div i18n:domain="passwordresettool" + i18n:translate="mailtemplate_reset_information" + tal:omit-tag="" + tal:condition="not:isAnon"> +The site administrator asks you to reset your password for '<span i18n:name="userid" + tal:omit-tag="" + tal:content="member/id" />' userid. Your old password doesn't work anymore. +</div> + +<div i18n:domain="passwordresettool" i18n:translate="mailtemplate_text_linkreset" tal:omit-tag="" tal:define="fullname python: test(member.fullname, @@ -32,7 +42,8 @@ The following link will take you to a page where you can reset your password for <div i18n:domain="passwordresettool" i18n:translate="mailtemplate_tracking_information" - tal:omit-tag=""> + tal:omit-tag="" + tal:condition="isAnon"> If you didn't expect to receive this email, please ignore it. Your password has not been changed. Request made from IP address <span tal:define="host request/HTTP_X_FORWARDED_FOR|request/REMOTE_ADDR" tal:content="host" diff --git a/Products/PasswordResetTool/tests/browser.txt b/Products/PasswordResetTool/tests/browser.txt index 5876c79..bc44317 100644 --- a/Products/PasswordResetTool/tests/browser.txt +++ b/Products/PasswordResetTool/tests/browser.txt @@ -72,6 +72,7 @@ What we do here: - Log in - Log out again - Forget our password (this is where PasswordResetTool comes in) + - Check if this is a soft reset (old password already works until changed) - Read the e-mail that contains the URL we visit to reset our password - Reset our password - Log in with our new password @@ -154,6 +155,24 @@ password`` in the login form: >>> form.getControl(name='userid').value = 'jsmith' >>> form.submit() +We check if the old password always works. + + >>> browser.open('http://nohost/plone/login') + >>> browser.getControl(name='__ac_name').value = 'jsmith' + >>> browser.getControl(name='__ac_password').value = 'secret' + >>> browser.getControl(name='submit').click() + +We should be logged in now: + + >>> "You are now logged in" in browser.contents + True + +Log out again: + + >>> browser.getLink('Log out').click() + >>> "You are now logged out" in browser.contents + True + As part of our test setup, we replaced the original MailHost with our own version. Our version doesn't mail messages, it just collects them in a list called ``messages``: @@ -170,13 +189,17 @@ then we extract the address that lets us reset our password: >>> msg = quopri.decodestring(msg) >>> "To: jsmith@example.com" in msg True + >>> "The site administrator asks you to reset your password for 'jsmith' userid" in msg + False >>> please_visit_text = "The following link will take you to a page where you can reset your password for Plone site site:" >>> please_visit_text in msg True >>> url_index = msg.index(please_visit_text) + len(please_visit_text) >>> address = msg[url_index:].strip().split()[0] - >>> address # doctest: +ELLIPSIS + >>> address # doctest: +ELLIPSIS 'http://nohost/plone/passwordreset/...' + >>> "If you didn't expect to receive this email" in msg + True Now that we have the address, we will reset our password: @@ -221,6 +244,9 @@ Log out again: - Register a member (with send email checked???) - Log out - Log in as the new member + - A manager resets a user password + - Check if this is a hard reset (old password is changed) + - Check the received mail First, we want to login as the portal owner: @@ -261,6 +287,56 @@ We want to logout and login as the new member: >>> browser.getLink('Log out').click() +Again, we want to login as the portal owner: + + >>> browser.open('http://nohost/plone/login') + >>> browser.getControl(name='__ac_name').value = SITE_OWNER_NAME + >>> browser.getControl(name='__ac_password').value = SITE_OWNER_PASSWORD + >>> browser.getControl(name='submit').click() + >>> "You are now logged in" in browser.contents + True + +We navigate to the Users Overview page and reset a password user: + + >>> browser.getLink('Site Setup').click() + >>> browser.getLink('Users and Groups').click() + >>> resets = browser.getControl(name='users.resetpassword:records') + >>> reset = resets.getControl(value='wsmith') + >>> reset.selected = True + >>> browser.getControl(name="form.button.Modify").click() + >>> "Changes applied." in browser.contents + True + >>> browser.getLink('Log out').click() + >>> "You are now logged out" in browser.contents + True + +We check if the old password is well changed. + + >>> browser.open('http://nohost/plone/login') + >>> browser.getControl(name='__ac_name').value = 'wsmith' + >>> browser.getControl(name='__ac_password').value = 'supersecret' + >>> browser.getControl(name='submit').click() + +We should not be logged in: + + >>> "Login failed" in browser.contents + True + +We should have received an e-mail at this point: + + >>> mailhost = layer['portal'].MailHost + >>> len(mailhost.messages) + 2 + >>> import quopri + >>> msg = quopri.decodestring(str(mailhost.messages[-1])) + >>> "The site administrator asks you to reset your password for 'wsmith' userid" in msg + True + >>> please_visit_text = "The following link will take you to a page where you can reset your password for Plone site site:" + >>> please_visit_text in msg + True + >>> "If you didn't expect to receive this email" in msg + False + 1B. User joins with e-mail validation enabled and forgets password ------------------------------------------------------------------ @@ -311,7 +387,7 @@ We should have received an e-mail at this point: >>> mailhost = layer['portal'].MailHost >>> len(mailhost.messages) - 2 + 3 >>> msg = str(mailhost.messages[-1]) Now that we have the message, we want to look at its contents, and @@ -397,7 +473,7 @@ We should have received an e-mail at this point: >>> mailhost = layer['portal'].MailHost >>> len(mailhost.messages) - 3 + 4 >>> msg = str(mailhost.messages[-1]) Now that we have the message, we want to look at its contents, and Repository: Products.PasswordResetTool Branch: refs/heads/master Date: 2015-02-27T10:00:03+01:00 Author: Timo Stollenwerk (tisto) <tisto@plone.org> Commit: plone/Products.PasswordResetTool@7019f76 Merge pull request #8 from plone/plip10359-security-controlpanel Plip10359 security controlpanel Files changed: M CHANGES.txt M Products/PasswordResetTool/PasswordResetTool.py M Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt M Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt M Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt M Products/PasswordResetTool/tests/browser.txt diff --git a/CHANGES.txt b/CHANGES.txt index 4f951e3..95ac758 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,10 @@ Changelog 2.1.2 (unreleased) ------------------ +- Read ``use_email_as_login`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] + - Amend browser.txt test to the new p.a.registry-based control panels (Plone 5 only). [timo] diff --git a/Products/PasswordResetTool/PasswordResetTool.py b/Products/PasswordResetTool/PasswordResetTool.py index dd03c3e..20d95aa 100644 --- a/Products/PasswordResetTool/PasswordResetTool.py +++ b/Products/PasswordResetTool/PasswordResetTool.py @@ -19,7 +19,9 @@ from App.special_dtml import DTMLFile from AccessControl import ClassSecurityInfo from AccessControl import ModuleSecurityInfo +from plone.registry.interfaces import IRegistry from Products.CMFCore.permissions import ManagePortal +from Products.CMFPlone.interfaces import ISecuritySchema try: from Products.CMFPlone.RegistrationTool import get_member_by_login_name except ImportError: @@ -33,6 +35,7 @@ import time import socket from DateTime import DateTime +from zope.component import getUtility from zope.interface import implements module_security = ModuleSecurityInfo('Products.PasswordResetTool.PasswordResetTool') @@ -346,8 +349,10 @@ def expirationDate(self): def getValidUser(self, userid): """Returns the member with 'userid' if available and None otherwise.""" if get_member_by_login_name: - props = getToolByName(self, 'portal_properties').site_properties - if props.getProperty('use_email_as_login', False): + registry = getUtility(IRegistry) + settings = registry.forInterface(ISecuritySchema, prefix='plone') + + if settings.use_email_as_login: return get_member_by_login_name( self, userid, raise_exceptions=False) membertool = getToolByName(self, 'portal_membership') diff --git a/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt b/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt index 03daaad..d23c1f1 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt +++ b/Products/PasswordResetTool/skins/PasswordReset/mail_password_form.pt @@ -14,7 +14,7 @@ <metal:main fill-slot="main" tal:define="global props context/@@plone_tools/properties; - use_email_as_login props/site_properties/use_email_as_login|nothing;"> + use_email_as_login python:context.portal_registry['plone.use_email_as_login'];"> <h1 class="documentFirstHeading" i18n:translate="heading_lost_password">Lost Password</h1> diff --git a/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt b/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt index 53d325a..53be415 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt +++ b/Products/PasswordResetTool/skins/PasswordReset/pwreset_form.cpt @@ -32,7 +32,7 @@ <div class="field" tal:define="error errors/userid | nothing; site_properties context/portal_properties/site_properties; - use_email_as_login site_properties/use_email_as_login|nothing;" + use_email_as_login python:context.portal_registry['plone.use_email_as_login'];" tal:attributes="class python:test(error, 'field error', 'field')" tal:condition="here/portal_password_reset/checkUser | nothing"> diff --git a/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt b/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt index 755ed7e..417cf2f 100644 --- a/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt +++ b/Products/PasswordResetTool/skins/PasswordReset/pwreset_invalid.pt @@ -6,7 +6,7 @@ <metal:main fill-slot="main" tal:define="site_properties context/portal_properties/site_properties; - use_email_as_login site_properties/use_email_as_login|nothing;"> + use_email_as_login python:context.portal_registry['plone.use_email_as_login'];"> <h1 class="documentFirstHeading" i18n:translate="heading_pwreset_invalid">Error setting password</h1> diff --git a/Products/PasswordResetTool/tests/browser.txt b/Products/PasswordResetTool/tests/browser.txt index d4dc5b1..bc44317 100644 --- a/Products/PasswordResetTool/tests/browser.txt +++ b/Products/PasswordResetTool/tests/browser.txt @@ -25,9 +25,9 @@ distinct password policies regarding member registration. B. A password is generated for the users (and an e-mail with login credentials is sent automatically). -This policy can enabled or disabled in the ``validate_email`` property -on the Plone Site object. By default ``validate_email`` is enabled -and the second policy applies. +This policy can be enabled or disabled with the ``enable_user_pwd_choice`` +setting in the security control panel. By default ``enable_user_pwd_choice`` is +disabled and the second policy applies. Another aspect we have to take into account is the fact that Plone by default only allows Administrators to register (other) members, but allowing
Branch: refs/heads/master Date: 2015-01-25T13:32:53+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.layout@ec8d8bb Read "allow_anon_views_about" from registry instead of properties Files changed: M CHANGES.rst M plone/app/layout/links/viewlets.py M plone/app/layout/viewlets/content.py M plone/app/layout/viewlets/tests/test_content.py diff --git a/CHANGES.rst b/CHANGES.rst index ee37d4c..2e0a425 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,10 @@ Changelog 2.5.4 (unreleased) ------------------ +- Read ``allow_anon_views_about`` settings from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] + - Added support for site logos stored in the portal registry via the site control panel for the logo viewlet with a fallback to the ``OFS.Image`` based ``logo.png`` file. Removed support of long-gone diff --git a/plone/app/layout/links/viewlets.py b/plone/app/layout/links/viewlets.py index 555616a..3ec1283 100644 --- a/plone/app/layout/links/viewlets.py +++ b/plone/app/layout/links/viewlets.py @@ -13,6 +13,7 @@ from zope.schema.interfaces import IVocabularyFactory from zope.component import getUtility from plone.registry.interfaces import IRegistry +from Products.CMFPlone.interfaces import ISecuritySchema from Products.CMFPlone.interfaces.syndication import IFeedSettings from Products.CMFPlone.interfaces.syndication import ISiteSyndicationSettings @@ -62,12 +63,13 @@ def update(self): name='plone_tools') def show(self): - properties = self.tools.properties() - site_properties = getattr(properties, 'site_properties') anonymous = self.portal_state.anonymous() - allowAnonymousViewAbout = site_properties.getProperty( - 'allowAnonymousViewAbout', True) - return not anonymous or allowAnonymousViewAbout + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + return not anonymous or settings.allow_anon_views_about def render(self): if self.show(): diff --git a/plone/app/layout/viewlets/content.py b/plone/app/layout/viewlets/content.py index 15adcbd..7ac2abf 100644 --- a/plone/app/layout/viewlets/content.py +++ b/plone/app/layout/viewlets/content.py @@ -6,14 +6,17 @@ from AccessControl import getSecurityManager from Acquisition import aq_inner from DateTime import DateTime +from plone.registry.interfaces import IRegistry from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.CMFCore.utils import _checkPermission from Products.CMFCore.utils import getToolByName from Products.CMFCore.WorkflowCore import WorkflowException from Products.CMFEditions.Permissions import AccessPreviousVersions from Products.CMFPlone import PloneMessageFactory as _ +from Products.CMFPlone.interfaces import ISecuritySchema from Products.CMFPlone.utils import base_hasattr from Products.CMFPlone.utils import log +from zope.component import getUtility from plone.app.layout.globals.interfaces import IViewView from plone.app.layout.viewlets import ViewletBase @@ -64,11 +67,12 @@ def update(self): self.has_pam = HAS_PAM def show(self): - properties = getToolByName(self.context, 'portal_properties') - site_properties = getattr(properties, 'site_properties') - allowAnonymousViewAbout = site_properties.getProperty( - 'allowAnonymousViewAbout', True) - return not self.anonymous or allowAnonymousViewAbout + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + return not self.anonymous or settings.allow_anon_views_about def show_history(self): has_access_preview_versions_permission = _checkPermission( diff --git a/plone/app/layout/viewlets/tests/test_content.py b/plone/app/layout/viewlets/tests/test_content.py index 2e32def..d474d08 100644 --- a/plone/app/layout/viewlets/tests/test_content.py +++ b/plone/app/layout/viewlets/tests/test_content.py @@ -8,6 +8,8 @@ from plone.app.layout.viewlets.content import ContentRelatedItems from plone.locking.tests import addMember from plone.locking.interfaces import ILockable +from plone.registry.interfaces import IRegistry +from Products.CMFPlone.interfaces import ISecuritySchema from DateTime import DateTime from Products.CMFCore.utils import getToolByName @@ -35,6 +37,44 @@ def afterSetUp(self): portal = getSite() addMember(portal, 'Alan', roles=('Member', 'Manager')) addMember(portal, 'Ano', roles=()) + self.folder.invokeFactory('Document', 'doc1', title='Document 1') + + registry = getUtility(IRegistry) + self.security_settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + + def _get_viewlet(self): + context = self.folder['doc1'] + request = self.app.REQUEST + viewlet = DocumentBylineViewlet(context, request, None, None) + viewlet.update() + return viewlet + + def test_show_anonymous_not_allowed(self): + self.security_settings.allow_anon_views_about = False + self.logout() + viewlet = self._get_viewlet() + self.assertFalse(viewlet.show()) + + def test_show_anonymous_allowed(self): + self.security_settings.allow_anon_views_about = True + self.logout() + viewlet = self._get_viewlet() + self.assertTrue(viewlet.show()) + + def test_show_logged_in_anonymous_not_allowed(self): + self.security_settings.allow_anon_views_about = False + self.login('Alan') + viewlet = self._get_viewlet() + self.assertTrue(viewlet.show()) + + def test_show_logged_in_anonymous_allowed(self): + self.security_settings.allow_anon_views_about = True + self.login('Alan') + viewlet = self._get_viewlet() + self.assertTrue(viewlet.show()) def test_anonymous_locked_icon(self): request = self.app.REQUEST Repository: plone.app.layout Branch: refs/heads/master Date: 2015-01-25T13:52:55+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.layout@49137b1 restructure DocumentBylineViewlet tests Files changed: M plone/app/layout/viewlets/tests/test_content.py diff --git a/plone/app/layout/viewlets/tests/test_content.py b/plone/app/layout/viewlets/tests/test_content.py index d474d08..c459ded 100644 --- a/plone/app/layout/viewlets/tests/test_content.py +++ b/plone/app/layout/viewlets/tests/test_content.py @@ -34,10 +34,8 @@ class TestDocumentBylineViewletView(ViewletsTestCase): Test the document by line viewlet """ def afterSetUp(self): - portal = getSite() - addMember(portal, 'Alan', roles=('Member', 'Manager')) - addMember(portal, 'Ano', roles=()) self.folder.invokeFactory('Document', 'doc1', title='Document 1') + self.context = self.folder['doc1'] registry = getUtility(IRegistry) self.security_settings = registry.forInterface( @@ -46,9 +44,8 @@ def afterSetUp(self): ) def _get_viewlet(self): - context = self.folder['doc1'] request = self.app.REQUEST - viewlet = DocumentBylineViewlet(context, request, None, None) + viewlet = DocumentBylineViewlet(self.context, request, None, None) viewlet.update() return viewlet @@ -66,57 +63,45 @@ def test_show_anonymous_allowed(self): def test_show_logged_in_anonymous_not_allowed(self): self.security_settings.allow_anon_views_about = False - self.login('Alan') viewlet = self._get_viewlet() self.assertTrue(viewlet.show()) def test_show_logged_in_anonymous_allowed(self): self.security_settings.allow_anon_views_about = True - self.login('Alan') viewlet = self._get_viewlet() self.assertTrue(viewlet.show()) - def test_anonymous_locked_icon(self): - request = self.app.REQUEST - self.setRoles(['Manager', 'Member']) - self.portal.invokeFactory('Document', 'd1') - context = getattr(self.portal, 'd1') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() - ILockable(context).lock() - self.login('Ano') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() + def test_anonymous_locked_icon_not_locked(self): + self.logout() + viewlet = self._get_viewlet() self.assertEqual(viewlet.locked_icon(), "") - def test_locked_icon(self): - request = self.app.REQUEST - self.setRoles(['Manager', 'Member']) - self.portal.invokeFactory('Document', 'd1') - context = getattr(self.portal, 'd1') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() + def test_anonymous_locked_icon_is_locked(self): + self.logout() + ILockable(self.context).lock() + viewlet = self._get_viewlet() self.assertEqual(viewlet.locked_icon(), "") - ILockable(context).lock() + + def test_logged_in_locked_icon_not_locked(self): + viewlet = self._get_viewlet() + self.assertEqual(viewlet.locked_icon(), "") + + def test_logged_in_locked_icon_is_locked(self): + viewlet = self._get_viewlet() + ILockable(self.context).lock() lockIconUrl = '<img src="http://nohost/plone/lock_icon.png" alt="" \ title="Locked" height="16" width="16" />' self.assertEqual(viewlet.locked_icon(), lockIconUrl) def test_pub_date(self): - request = self.app.REQUEST - self.login('Alan') - self.portal.invokeFactory('Document', 'd1') - context = getattr(self.portal, 'd1') - # configure our portal to enable publication date on pages globally on # the site - properties = getToolByName(context, 'portal_properties') + properties = getToolByName(self.portal, 'portal_properties') site_properties = getattr(properties, 'site_properties') site_properties.displayPublicationDateInByline = True - self.login('Ano') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() + self.logout() + viewlet = self._get_viewlet() # publication date should be None as there is not Effective date set # for our document yet @@ -124,7 +109,7 @@ def test_pub_date(self): # now set effective date for our document effective = DateTime() - context.setEffectiveDate(effective) + self.context.setEffectiveDate(effective) self.assertEqual(viewlet.pub_date(), DateTime(effective.ISO8601())) # now switch off publication date globally on the site and see if Repository: plone.app.layout Branch: refs/heads/master Date: 2015-01-25T16:56:29+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.layout@24d7cb6 remove unused imports, reorganize imports in test_content Files changed: M plone/app/layout/viewlets/tests/test_content.py diff --git a/plone/app/layout/viewlets/tests/test_content.py b/plone/app/layout/viewlets/tests/test_content.py index c459ded..d7f4476 100644 --- a/plone/app/layout/viewlets/tests/test_content.py +++ b/plone/app/layout/viewlets/tests/test_content.py @@ -1,18 +1,15 @@ -from z3c.relationfield import RelationValue -from zope.component import getUtility -from zope.component.hooks import getSite -from zope.interface import Interface -from zope.intid.interfaces import IIntIds +from DateTime import DateTime from plone.app.layout.viewlets.tests.base import ViewletsTestCase from plone.app.layout.viewlets.content import DocumentBylineViewlet from plone.app.layout.viewlets.content import ContentRelatedItems -from plone.locking.tests import addMember from plone.locking.interfaces import ILockable from plone.registry.interfaces import IRegistry -from Products.CMFPlone.interfaces import ISecuritySchema - -from DateTime import DateTime from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.interfaces import ISecuritySchema +from z3c.relationfield import RelationValue +from zope.component import getUtility +from zope.interface import Interface +from zope.intid.interfaces import IIntIds try: import pkg_resources Repository: plone.app.layout Branch: refs/heads/master Date: 2015-02-27T07:49:09+01:00 Author: Timo Stollenwerk () <contact@timostollenwerk.net> Commit: plone/plone.app.layout@8d8c3cc Merge branch 'master' into plip10359-security-controlpanel Conflicts: CHANGES.rst Files changed: A plone/app/layout/globals/tests/test_pattern_settings.py M CHANGES.rst M plone/app/layout/globals/patterns_settings.py M plone/app/layout/links/viewlets.py M plone/app/layout/viewlets/common.py M plone/app/layout/viewlets/searchbox.pt diff --git a/CHANGES.rst b/CHANGES.rst index 2e0a425..9c87a70 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,12 @@ Changelog properties (see plone/Products.CMFPlone#216). [jcerjak] +- use livesearch pattern + [vangheem] + +- use configuration registry pattern options + [vangheem] + - Added support for site logos stored in the portal registry via the site control panel for the logo viewlet with a fallback to the ``OFS.Image`` based ``logo.png`` file. Removed support of long-gone diff --git a/plone/app/layout/globals/patterns_settings.py b/plone/app/layout/globals/patterns_settings.py index f72115d..669bbd1 100644 --- a/plone/app/layout/globals/patterns_settings.py +++ b/plone/app/layout/globals/patterns_settings.py @@ -2,12 +2,12 @@ from zope.interface import implements from zope.component import getAdapters -from zope.component.hooks import getSite from zope.publisher.browser import BrowserView from .interfaces import IPatternsSettingsRenderer from Products.CMFPlone.interfaces import IPatternsSettings - -import json +from plone.registry.interfaces import IRegistry +from zope.component import getUtility +from zope.component import getMultiAdapter class PatternsSettings(BrowserView): @@ -17,20 +17,28 @@ class PatternsSettings(BrowserView): implements(IPatternsSettingsRenderer) def __call__(self): - modal_options = { - 'actionOptions': { - 'displayInModal': False, - } - } - base_url = getSite().absolute_url() + portal_state = getMultiAdapter( + (self.context, self.request), name=u'plone_portal_state') + # do not use getSite because it's possible it could be different + # than the actual portal url + base_url = portal_state.portal_url() result = { - 'data-pat-modal': json.dumps(modal_options), 'data-base-url': self.context.absolute_url(), 'data-portal-url': base_url, 'data-i18ncatalogurl': base_url + '/plonejsi18n' } + + # first, check for any adapters that need pattern data defined adapters = getAdapters((self.context, self.request, None), IPatternsSettings) [result.update(x[1]()) for x in adapters] - return result + # Resources Registered UI patterns can override adapters + registry = getUtility(IRegistry) + try: + pattern_options = registry['plone.patternoptions'] + except (AttributeError, KeyError): + pattern_options = {} + for key, value in pattern_options.items(): + result['data-pat-' + key] = value + return result diff --git a/plone/app/layout/globals/tests/test_pattern_settings.py b/plone/app/layout/globals/tests/test_pattern_settings.py new file mode 100644 index 0000000..a17cc1a --- /dev/null +++ b/plone/app/layout/globals/tests/test_pattern_settings.py @@ -0,0 +1,33 @@ +from plone.app.layout.globals.tests.base import GlobalsTestCase +from plone.app.layout.globals.patterns_settings import PatternsSettings +from plone.registry.interfaces import IRegistry +from zope.component import getUtility + + +class TestPatternSettings(GlobalsTestCase): + """Ensure that the basic redirector setup is successful. + """ + + def testShouldReturnCorrectType(self): + settings = PatternsSettings(self.folder, self.app.REQUEST) + result = settings() + self.assertEquals(type(result), dict) + for key, value in result.items(): + self.assertTrue(isinstance(key, basestring)) + self.assertTrue(isinstance(value, basestring)) + + def testUrls(self): + settings = PatternsSettings(self.folder, self.app.REQUEST) + result = settings() + self.assertEquals(result['data-base-url'], self.folder.absolute_url()) + self.assertEquals(result['data-portal-url'], self.portal.absolute_url()) + + def testPatternOptions(self): + registry = getUtility(IRegistry) + registry['plone.patternoptions'] = { + 'foo': u'{"foo": "bar"}' + } + + settings = PatternsSettings(self.folder, self.app.REQUEST) + result = settings() + self.assertEquals(result['data-pat-foo'], u'{"foo": "bar"}') \ No newline at end of file diff --git a/plone/app/layout/links/viewlets.py b/plone/app/layout/links/viewlets.py index 3ec1283..48d1534 100644 --- a/plone/app/layout/links/viewlets.py +++ b/plone/app/layout/links/viewlets.py @@ -112,12 +112,13 @@ def update(self): settings = registry.forInterface(ISiteSyndicationSettings) except KeyError: return - for uid in settings.site_rss_items: - obj = uuidToObject(uid) - if obj is not None: - self.rsslinks.extend(self.getRssLinks(obj)) - self.rsslinks.extend(self.getRssLinks( - self.portal_state.portal())) + if settings.site_rss_items: + for uid in settings.site_rss_items: + obj = uuidToObject(uid) + if obj is not None: + self.rsslinks.extend(self.getRssLinks(obj)) + self.rsslinks.extend(self.getRssLinks( + self.portal_state.portal())) else: if util.context_enabled(): self.rsslinks.extend(self.getRssLinks(self.context)) diff --git a/plone/app/layout/viewlets/common.py b/plone/app/layout/viewlets/common.py index 0f65305..4a05b72 100644 --- a/plone/app/layout/viewlets/common.py +++ b/plone/app/layout/viewlets/common.py @@ -17,6 +17,7 @@ from Products.CMFCore.utils import getToolByName from Products.CMFPlone.interfaces import ISiteSchema +from Products.CMFPlone.interfaces import ISearchSchema from Products.CMFPlone.utils import safe_unicode from Products.CMFPlone.interfaces import IPloneSiteRoot from Products.Five.browser import BrowserView @@ -175,13 +176,9 @@ def update(self): context_state = getMultiAdapter((self.context, self.request), name=u'plone_context_state') - props = getToolByName(self.context, 'portal_properties') - livesearch = props.site_properties.getProperty( - 'enable_livesearch', False) - if livesearch: - self.search_input_id = "searchGadget" - else: - self.search_input_id = "nolivesearchGadget" # don't use "" here! + registry = getUtility(IRegistry) + search_settings = registry.forInterface(ISearchSchema, prefix='plone') + self.livesearch = search_settings.enable_livesearch folder = context_state.folder() self.folder_path = '/'.join(folder.getPhysicalPath()) diff --git a/plone/app/layout/viewlets/searchbox.pt b/plone/app/layout/viewlets/searchbox.pt index 879a6d7..bde537c 100644 --- a/plone/app/layout/viewlets/searchbox.pt +++ b/plone/app/layout/viewlets/searchbox.pt @@ -1,30 +1,30 @@ <div id="portal-searchbox" i18n:domain="plone" - tal:define="navigation_root_url view/navigation_root_url; - search_input_id view/search_input_id;"> + tal:define="navigation_root_url view/navigation_root_url;"> <form id="searchGadget_form" action="@@search" role="search" tal:attributes="action string:${navigation_root_url}/@@search; - id string:${search_input_id}_form;"> + data-pat-livesearch string:ajaxUrl:${navigation_root_url}/@@ajax-search; + class python: view.livesearch and 'pat-livesearch' or ''"> <div class="LSBox"> <label class="hiddenStructure" - tal:attributes="for search_input_id" + for="searchGadget" i18n:translate="text_search">Search Site</label> <input name="SearchableText" type="text" size="18" value="" + id="searchGadget" title="Search Site" placeholder="Search Site" accesskey="4" i18n:attributes="title title_search_site; placeholder title_search_site" - tal:attributes="value request/form/SearchableText|nothing; - id search_input_id" + tal:attributes="value request/form/SearchableText|nothing;" class="searchField" /> <input class="searchButton" @@ -46,8 +46,6 @@ only in current section </label> </div> - - <div class="LSResult" id="LSResult"><div class="LSShadow" id="LSShadow"></div></div> </div> </form> Repository: plone.app.layout Branch: refs/heads/master Date: 2015-02-27T10:10:33+01:00 Author: Timo Stollenwerk (tisto) <tisto@plone.org> Commit: plone/plone.app.layout@1cdded0 Merge pull request #39 from plone/plip10359-security-controlpanel Plip10359 security controlpanel Files changed: M CHANGES.rst M plone/app/layout/links/viewlets.py M plone/app/layout/viewlets/content.py M plone/app/layout/viewlets/tests/test_content.py diff --git a/CHANGES.rst b/CHANGES.rst index 7051605..9c87a70 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,10 @@ Changelog 2.5.4 (unreleased) ------------------ +- Read ``allow_anon_views_about`` settings from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] + - use livesearch pattern [vangheem] diff --git a/plone/app/layout/links/viewlets.py b/plone/app/layout/links/viewlets.py index 238c61d..48d1534 100644 --- a/plone/app/layout/links/viewlets.py +++ b/plone/app/layout/links/viewlets.py @@ -13,6 +13,7 @@ from zope.schema.interfaces import IVocabularyFactory from zope.component import getUtility from plone.registry.interfaces import IRegistry +from Products.CMFPlone.interfaces import ISecuritySchema from Products.CMFPlone.interfaces.syndication import IFeedSettings from Products.CMFPlone.interfaces.syndication import ISiteSyndicationSettings @@ -62,12 +63,13 @@ def update(self): name='plone_tools') def show(self): - properties = self.tools.properties() - site_properties = getattr(properties, 'site_properties') anonymous = self.portal_state.anonymous() - allowAnonymousViewAbout = site_properties.getProperty( - 'allowAnonymousViewAbout', True) - return not anonymous or allowAnonymousViewAbout + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + return not anonymous or settings.allow_anon_views_about def render(self): if self.show(): diff --git a/plone/app/layout/viewlets/content.py b/plone/app/layout/viewlets/content.py index 15adcbd..7ac2abf 100644 --- a/plone/app/layout/viewlets/content.py +++ b/plone/app/layout/viewlets/content.py @@ -6,14 +6,17 @@ from AccessControl import getSecurityManager from Acquisition import aq_inner from DateTime import DateTime +from plone.registry.interfaces import IRegistry from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.CMFCore.utils import _checkPermission from Products.CMFCore.utils import getToolByName from Products.CMFCore.WorkflowCore import WorkflowException from Products.CMFEditions.Permissions import AccessPreviousVersions from Products.CMFPlone import PloneMessageFactory as _ +from Products.CMFPlone.interfaces import ISecuritySchema from Products.CMFPlone.utils import base_hasattr from Products.CMFPlone.utils import log +from zope.component import getUtility from plone.app.layout.globals.interfaces import IViewView from plone.app.layout.viewlets import ViewletBase @@ -64,11 +67,12 @@ def update(self): self.has_pam = HAS_PAM def show(self): - properties = getToolByName(self.context, 'portal_properties') - site_properties = getattr(properties, 'site_properties') - allowAnonymousViewAbout = site_properties.getProperty( - 'allowAnonymousViewAbout', True) - return not self.anonymous or allowAnonymousViewAbout + registry = getUtility(IRegistry) + settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) + return not self.anonymous or settings.allow_anon_views_about def show_history(self): has_access_preview_versions_permission = _checkPermission( diff --git a/plone/app/layout/viewlets/tests/test_content.py b/plone/app/layout/viewlets/tests/test_content.py index 2e32def..d7f4476 100644 --- a/plone/app/layout/viewlets/tests/test_content.py +++ b/plone/app/layout/viewlets/tests/test_content.py @@ -1,16 +1,15 @@ -from z3c.relationfield import RelationValue -from zope.component import getUtility -from zope.component.hooks import getSite -from zope.interface import Interface -from zope.intid.interfaces import IIntIds +from DateTime import DateTime from plone.app.layout.viewlets.tests.base import ViewletsTestCase from plone.app.layout.viewlets.content import DocumentBylineViewlet from plone.app.layout.viewlets.content import ContentRelatedItems -from plone.locking.tests import addMember from plone.locking.interfaces import ILockable - -from DateTime import DateTime +from plone.registry.interfaces import IRegistry from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.interfaces import ISecuritySchema +from z3c.relationfield import RelationValue +from zope.component import getUtility +from zope.interface import Interface +from zope.intid.interfaces import IIntIds try: import pkg_resources @@ -32,51 +31,74 @@ class TestDocumentBylineViewletView(ViewletsTestCase): Test the document by line viewlet """ def afterSetUp(self): - portal = getSite() - addMember(portal, 'Alan', roles=('Member', 'Manager')) - addMember(portal, 'Ano', roles=()) + self.folder.invokeFactory('Document', 'doc1', title='Document 1') + self.context = self.folder['doc1'] + + registry = getUtility(IRegistry) + self.security_settings = registry.forInterface( + ISecuritySchema, + prefix='plone', + ) - def test_anonymous_locked_icon(self): + def _get_viewlet(self): request = self.app.REQUEST - self.setRoles(['Manager', 'Member']) - self.portal.invokeFactory('Document', 'd1') - context = getattr(self.portal, 'd1') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() - ILockable(context).lock() - self.login('Ano') - viewlet = DocumentBylineViewlet(context, request, None, None) + viewlet = DocumentBylineViewlet(self.context, request, None, None) viewlet.update() + return viewlet + + def test_show_anonymous_not_allowed(self): + self.security_settings.allow_anon_views_about = False + self.logout() + viewlet = self._get_viewlet() + self.assertFalse(viewlet.show()) + + def test_show_anonymous_allowed(self): + self.security_settings.allow_anon_views_about = True + self.logout() + viewlet = self._get_viewlet() + self.assertTrue(viewlet.show()) + + def test_show_logged_in_anonymous_not_allowed(self): + self.security_settings.allow_anon_views_about = False + viewlet = self._get_viewlet() + self.assertTrue(viewlet.show()) + + def test_show_logged_in_anonymous_allowed(self): + self.security_settings.allow_anon_views_about = True + viewlet = self._get_viewlet() + self.assertTrue(viewlet.show()) + + def test_anonymous_locked_icon_not_locked(self): + self.logout() + viewlet = self._get_viewlet() self.assertEqual(viewlet.locked_icon(), "") - def test_locked_icon(self): - request = self.app.REQUEST - self.setRoles(['Manager', 'Member']) - self.portal.invokeFactory('Document', 'd1') - context = getattr(self.portal, 'd1') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() + def test_anonymous_locked_icon_is_locked(self): + self.logout() + ILockable(self.context).lock() + viewlet = self._get_viewlet() self.assertEqual(viewlet.locked_icon(), "") - ILockable(context).lock() + + def test_logged_in_locked_icon_not_locked(self): + viewlet = self._get_viewlet() + self.assertEqual(viewlet.locked_icon(), "") + + def test_logged_in_locked_icon_is_locked(self): + viewlet = self._get_viewlet() + ILockable(self.context).lock() lockIconUrl = '<img src="http://nohost/plone/lock_icon.png" alt="" \ title="Locked" height="16" width="16" />' self.assertEqual(viewlet.locked_icon(), lockIconUrl) def test_pub_date(self): - request = self.app.REQUEST - self.login('Alan') - self.portal.invokeFactory('Document', 'd1') - context = getattr(self.portal, 'd1') - # configure our portal to enable publication date on pages globally on # the site - properties = getToolByName(context, 'portal_properties') + properties = getToolByName(self.portal, 'portal_properties') site_properties = getattr(properties, 'site_properties') site_properties.displayPublicationDateInByline = True - self.login('Ano') - viewlet = DocumentBylineViewlet(context, request, None, None) - viewlet.update() + self.logout() + viewlet = self._get_viewlet() # publication date should be None as there is not Effective date set # for our document yet @@ -84,7 +106,7 @@ def test_pub_date(self): # now set effective date for our document effective = DateTime() - context.setEffectiveDate(effective) + self.context.setEffectiveDate(effective) self.assertEqual(viewlet.pub_date(), DateTime(effective.ISO8601())) # now switch off publication date globally on the site and see if
@jcerjak is it possible that all tests pass now? http://jenkins.plone.org/view/PLIPs/job/PLIP-10359/8/console After I set up the Jenkins job on the new machine all tests seem to pass. Will check on my local machine... |
@tisto, if it sounds too good to be true, it probably is :) I did:
and I get a bunch of errors. Am I missing something? |
There must be something wrong with the Jenkins job. I get errors when I run the tests locally. BTW: running "bin/test" without any params will not work in buildout.coredev. You always have to run "bin/alltests" and "bin/alltests-at". |
Ok, this is a configuration problem. I will investigate it further... |
Ok, thanks! |
Branch: refs/heads/master Date: 2015-01-26T19:50:04+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.collection@67e3724 Read "allow_anon_views_about" from registry instead of properties Files changed: M CHANGES.rst M plone/app/collection/browser/templates/standard_view.pt diff --git a/CHANGES.rst b/CHANGES.rst index 169f9c9..9adfd4e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,9 @@ Changelog 1.1.3 (unreleased) ------------------ -- Nothing changed yet. +- Read ``allow_anon_views_about`` setting from the registry instead of portal + properties (see plone/Products.CMFPlone#216). + [jcerjak] 1.1.2 (2014-10-23) diff --git a/plone/app/collection/browser/templates/standard_view.pt b/plone/app/collection/browser/templates/standard_view.pt index 052ebf8..408e4d2 100644 --- a/plone/app/collection/browser/templates/standard_view.pt +++ b/plone/app/collection/browser/templates/standard_view.pt @@ -33,7 +33,7 @@ isAnon context/@@plone_portal_state/anonymous; normalizeString nocall: context/plone_utils/normalizeString; toLocalizedTime nocall: context/@@plone/toLocalizedTime; - show_about python:not isAnon or site_properties.allowAnonymousViewAbout; + show_about python:not isAnon or context.portal_registry['plone.allow_anon_views_about']; navigation_root_url context/@@plone_portal_state/navigation_root_url; pas_member context/@@pas_member;"> <tal:listing condition="batch"> Repository: plone.app.collection Branch: refs/heads/master Date: 2015-02-27T07:50:17+01:00 Author: Timo Stollenwerk () <contact@timostollenwerk.net> Commit: plone/plone.app.collection@321bd07 Merge branch 'master' into plip10359-security-controlpanel Conflicts: CHANGES.rst Files changed: A plone/app/collection/marshaller.py M CHANGES.rst M plone/app/collection/collection.py M plone/app/collection/configure.zcml M plone/app/collection/tests/test_collection.py M setup.py diff --git a/CHANGES.rst b/CHANGES.rst index 9adfd4e..d42b982 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,9 @@ Changelog properties (see plone/Products.CMFPlone#216). [jcerjak] +- Support for import and export of collections using FTP, DAV and GenericSetup + [matthewwilkes] + 1.1.2 (2014-10-23) ------------------ diff --git a/plone/app/collection/collection.py b/plone/app/collection/collection.py index eac3bce..5504a4e 100644 --- a/plone/app/collection/collection.py +++ b/plone/app/collection/collection.py @@ -2,7 +2,7 @@ from OFS.ObjectManager import ObjectManager from plone.app.collection.field import QueryField from plone.app.contentlisting.interfaces import IContentListing -from plone.app.widgets.at import QueryStringWidget +from Products.Archetypes.Widget import QueryStringWidget from Products.ATContentTypes.content import document, schemata from Products.Archetypes import atapi from Products.Archetypes.atapi import (BooleanField, @@ -20,7 +20,7 @@ from plone.app.collection import PloneMessageFactory as _ from plone.app.collection.config import ATCT_TOOLNAME, PROJECTNAME from plone.app.collection.interfaces import ICollection - +from plone.app.collection.marshaller import CollectionRFC822Marshaller CollectionSchema = document.ATDocumentSchema.copy() + atapi.Schema(( @@ -86,6 +86,9 @@ ), )) +# Use the extended marshaller that understands queries +CollectionSchema.registerLayer("marshall", CollectionRFC822Marshaller()) + CollectionSchema.moveField('query', after='description') if 'presentation' in CollectionSchema: CollectionSchema['presentation'].widget.visible = False diff --git a/plone/app/collection/configure.zcml b/plone/app/collection/configure.zcml index 33ce9dc..d2bda5d 100644 --- a/plone/app/collection/configure.zcml +++ b/plone/app/collection/configure.zcml @@ -14,7 +14,7 @@ name="default" title="plone.app.collection" directory="profiles/default" - description="Adds support for new style collections to Plone" + description="Archetypes-based collections" provides="Products.GenericSetup.interfaces.EXTENSION" /> diff --git a/plone/app/collection/marshaller.py b/plone/app/collection/marshaller.py new file mode 100644 index 0000000..acab0ad --- /dev/null +++ b/plone/app/collection/marshaller.py @@ -0,0 +1,68 @@ +from types import ListType, TupleType + +from zope.contenttype import guess_content_type + +from AccessControl import ClassSecurityInfo +from App.class_init import InitializeClass +from Products.Archetypes.interfaces.base import IBaseUnit +from Products.Archetypes.utils import mapply +from Products.Archetypes.Marshall import RFC822Marshaller, parseRFC822, formatRFC822Headers + + +class CollectionRFC822Marshaller(RFC822Marshaller): + + security = ClassSecurityInfo() + security.declareObjectPrivate() + security.setDefaultAccess('deny') + + def demarshall(self, instance, data, **kwargs): + # We don't want to pass file forward. + if 'file' in kwargs: + if not data: + # TODO Yuck! Shouldn't read the whole file, never. + # OTOH, if you care about large files, you should be + # using the PrimaryFieldMarshaller or something + # similar. + data = kwargs['file'].read() + del kwargs['file'] + headers, body = parseRFC822(data) + + query = {} + for k, v in headers.items(): + if not k.startswith("query"): + continue + else: + index = int(k[5]) + sub_key = k.split("_")[1] + query_part = query.get(index, {}) + query_part[sub_key] = v + query[index] = query_part + del headers[k] + query = [facet[1] for facet in sorted(query.items())] + + header = formatRFC822Headers(headers.items()) + data = '%s\n\n%s' % (header, body) + + try: + return RFC822Marshaller.demarshall(self, instance, data, **kwargs) + finally: + instance.query = query + + def marshall(self, instance, **kwargs): + content_type, length, data = RFC822Marshaller.marshall(self, instance, **kwargs) + headers, body = parseRFC822(data) + + headers = headers.items() + for i, query in enumerate(instance.query): + for key, value in query.items(): + if isinstance(value, list): + value = "\n".join(value) + header_key = 'query%d_%s' % (i, key) + headers.append((header_key, value)) + + header = formatRFC822Headers(headers) + data = '%s\n\n%s' % (header, body) + length = len(data) + return (content_type, length, data) + +InitializeClass(CollectionRFC822Marshaller) \ No newline at end of file diff --git a/plone/app/collection/tests/test_collection.py b/plone/app/collection/tests/test_collection.py index f1611e7..9599d3e 100644 --- a/plone/app/collection/tests/test_collection.py +++ b/plone/app/collection/tests/test_collection.py @@ -7,6 +7,7 @@ from plone.app.testing import setRoles from plone.testing.z2 import Browser from transaction import commit +from Products.Archetypes.Marshall import parseRFC822 import unittest2 as unittest @@ -235,3 +236,94 @@ def test_selectedViewFields(self): def test_syndication_enabled_by_default(self): syn = getToolByName(self.portal, 'portal_syndication') self.assertTrue(syn.isSyndicationAllowed(self.collection)) + + +class TestMarshalling(unittest.TestCase): + + layer = PLONEAPPCOLLECTION_INTEGRATION_TESTING + + def test_simple_query_included_in_marshall_results(self): + portal = self.layer['portal'] + login(portal, 'admin') + query = [{ + 'i': 'portal_type', + 'o': 'plone.app.querystring.operation.string.is', + 'v': 'News Item', + }] + portal.invokeFactory("Collection", + "collection", + query=query, + title="New Collection") + collection = portal['collection'] + rfc822 = collection.manage_FTPget() + data = parseRFC822(rfc822) + self.assertIn('query0_i', data[0]) + self.assertIn('query0_o', data[0]) + self.assertIn('query0_v', data[0]) + + self.assertEqual(data[0]['query0_i'], query[0]['i']) + self.assertEqual(data[0]['query0_o'], query[0]['o']) + self.assertEqual(data[0]['query0_v'], query[0]['v']) + + def test_multiple_query_items_included_in_marshall_results(self): + portal = self.layer['portal'] + login(portal, 'admin') + query = [{ + 'i': 'portal_type', + 'o': 'plone.app.querystring.operation.string.is', + 'v': 'News Item', + },{ 'i': 'Title', + 'o': 'plone.app.querystring.operation.string.is', + 'v': 'Test News Item', + }] + + portal.invokeFactory("Collection", + "collection", + query=query, + title="New Collection") + collection = portal['collection'] + rfc822 = collection.manage_FTPget() + data = parseRFC822(rfc822) + + self.assertIn('query0_i', data[0]) + self.assertIn('query0_o', data[0]) + self.assertIn('query0_v', data[0]) + self.assertIn('query1_i', data[0]) + self.assertIn('query1_o', data[0]) + self.assertIn('query1_v', data[0]) + + self.assertEqual(data[0]['query0_i'], query[0]['i']) + self.assertEqual(data[0]['query0_o'], query[0]['o']) + self.assertEqual(data[0]['query0_v'], query[0]['v']) + self.assertEqual(data[0]['query1_i'], query[1]['i']) + self.assertEqual(data[0]['query1_o'], query[1]['o']) + self.assertEqual(data[0]['query1_v'], query[1]['v']) + + def test_query_gets_set_on_PUT(self): + portal = self.layer['portal'] + login(portal, 'admin') + query = [{ + 'i': 'portal_type', + 'o': 'plone.app.querystring.operation.string.is', + 'v': 'News Item', + }] + + expected_query = [{ + 'i': 'portal_type', + 'o': 'plone.app.querystring.operation.string.is', + 'v': 'LOREM IPSUM DOLOR', + }] + + portal.invokeFactory("Collection", + "collection", + query=query, + title="New Collection") + collection = portal['collection'] + rfc822 = collection.manage_FTPget() + # Modify the response to put in a sentinal, to check it's been updated + rfc822 = rfc822.replace(query[0]['v'], expected_query[0]['v']) + + portal.REQUEST.set("BODY", rfc822) + collection.PUT(portal.REQUEST, None) + self.assertEqual(collection.query, expected_query) + diff --git a/setup.py b/setup.py index c4d4d8d..9a982fb 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ 'plone.app.widgets', 'plone.portlet.collection', 'plone.portlets', - 'Products.Archetypes', + 'Products.Archetypes>=1.10.4.dev0', 'Products.CMFCore', 'Products.CMFPlone', 'Products.CMFQuickInstallerTool', Repository: plone.app.collection Branch: refs/heads/master Date: 2015-02-27T14:39:17+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.collection@2da6fa1 restore plone 4 compatibility for 'show about' setting Files changed: M CHANGES.rst M plone/app/collection/browser/templates/standard_view.pt M plone/app/collection/tests/test_collection.py diff --git a/CHANGES.rst b/CHANGES.rst index d42b982..10ee51a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,8 +4,8 @@ Changelog 1.1.3 (unreleased) ------------------ -- Read ``allow_anon_views_about`` setting from the registry instead of portal - properties (see plone/Products.CMFPlone#216). +- Read ``allow_anon_views_about`` setting from the registry, with fallback to + portal properties (see plone/Products.CMFPlone#216) [jcerjak] - Support for import and export of collections using FTP, DAV and GenericSetup diff --git a/plone/app/collection/browser/templates/standard_view.pt b/plone/app/collection/browser/templates/standard_view.pt index 408e4d2..2d036bc 100644 --- a/plone/app/collection/browser/templates/standard_view.pt +++ b/plone/app/collection/browser/templates/standard_view.pt @@ -29,11 +29,14 @@ <tal:results define="b_start python:request.get('b_start', 0); batch python:context.results(b_start=b_start); site_properties context/portal_properties/site_properties; + portal_registry context/portal_registry|nothing; use_view_action site_properties/typesUseViewActionInListings|python:(); isAnon context/@@plone_portal_state/anonymous; normalizeString nocall: context/plone_utils/normalizeString; toLocalizedTime nocall: context/@@plone/toLocalizedTime; - show_about python:not isAnon or context.portal_registry['plone.allow_anon_views_about']; + show_about_bbb site_properties/allowAnonymousViewAbout|nothing; + show_about_registry python:portal_registry and portal_registry.get('plone.allow_anon_views_about'); + show_about python:not isAnon or show_about_registry or show_about_bbb; navigation_root_url context/@@plone_portal_state/navigation_root_url; pas_member context/@@pas_member;"> <tal:listing condition="batch"> diff --git a/plone/app/collection/tests/test_collection.py b/plone/app/collection/tests/test_collection.py index 9599d3e..b2640ff 100644 --- a/plone/app/collection/tests/test_collection.py +++ b/plone/app/collection/tests/test_collection.py @@ -42,6 +42,14 @@ def setUp(self): pass self.collection = self.portal['col'] + def _set_up_collection(self): + self.portal.invokeFactory( + 'Document', + 'doc1', + title='Collection Test Page' + ) + self.collection.setQuery(query) + def test_addCollection(self): self.portal.invokeFactory("Collection", "col1", @@ -114,6 +122,160 @@ def test_viewingCollection(self): browser.open(self.collection.absolute_url()) self.assertTrue("Collection Test Page" in browser.contents) + def test_show_about_no_registry_has_property_noshow(self): + """Test the case where we fetch show about information from portal + properties (Plone < 5) and show about is False. + """ + # disable show about in site properties + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', False, 'boolean') + except: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=False) + self.portal.portal_registry = None + + self._set_up_collection() + + # logout and check if author information is hidden + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertFalse("author" in result) + self.assertFalse("test-user" in result) + + def test_show_about_no_registry_has_property_show(self): + """Test the case where we fetch show about information from portal + properties (Plone < 5) and show about is True. + """ + # enable show about in site properties + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', True, 'boolean') + except: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=True) + self.portal.portal_registry = None + + self._set_up_collection() + + # logout and check if author information is shown + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + + def test_show_about_has_property_and_registry_noshow(self): + """Test the case where we fetch show about information from portal + properties, but registry is also present (Plone < 5, with + plone.app.registry installed) and show about is False. + """ + # disable show about in site properties, create an empty registry + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', False, 'boolean') + except: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=False) + self.portal.portal_registry = {} # mock the registry + + self._set_up_collection() + + # logout and check if author information is hidden + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertFalse("author" in result) + self.assertFalse("test-user" in result) + + def test_show_about_has_property_and_registry_show(self): + """Test the case where we fetch show about information from portal + properties, but registry is also present (Plone < 5, with + plone.app.registry installed) and show about is True. + """ + # enable show about in site properties, create an empty registry + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', True, 'boolean') + except: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=True) + self.portal.portal_registry = {} # mock the registry + + self._set_up_collection() + + # logout and check if author information is shown + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + + def test_show_about_has_registry_no_property_noshow(self): + """Test the case where we fetch show about information from the + registry (Plone >= 5) and show about is False. + """ + # disable show about in the registry, delete 'allowAnonymousViewAbout' + # property + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_delProperties( + ['allowAnonymousViewAbout']) + except: + pass + self.portal.portal_registry = {'plone.allow_anon_views_about': False} + + self._set_up_collection() + + # logout and check if author information is hidden + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertFalse("author" in result) + self.assertFalse("test-user" in result) + + def test_show_about_has_registry_no_property_show(self): + """Test the case where we fetch show about information from the + registry (Plone >= 5) and show about is True. + """ + # enable show about in the registry, delete 'allowAnonymousViewAbout' + # property + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_delProperties( + ['allowAnonymousViewAbout']) + except: + pass + self.portal.portal_registry = {'plone.allow_anon_views_about': True} + + self._set_up_collection() + + # logout and check if author information is shown + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + + def test_show_about_logged_in(self): + """Test the case where we show about information if a user is logged in + even though show about is set to False + """ + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', False, 'boolean') + except: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=False) + self.portal.portal_registry = {'plone.allow_anon_views_about': False} + + self._set_up_collection() + + # check if author information is shown + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + def test_collection_templates(self): data = getData('image.png') # add an image that will be listed by the collection @@ -260,11 +422,11 @@ def test_simple_query_included_in_marshall_results(self): self.assertIn('query0_i', data[0]) self.assertIn('query0_o', data[0]) self.assertIn('query0_v', data[0]) - + self.assertEqual(data[0]['query0_i'], query[0]['i']) self.assertEqual(data[0]['query0_o'], query[0]['o']) self.assertEqual(data[0]['query0_v'], query[0]['v']) - + def test_multiple_query_items_included_in_marshall_results(self): portal = self.layer['portal'] login(portal, 'admin') @@ -276,7 +438,7 @@ def test_multiple_query_items_included_in_marshall_results(self): 'o': 'plone.app.querystring.operation.string.is', 'v': 'Test News Item', }] - + portal.invokeFactory("Collection", "collection", query=query, @@ -284,21 +446,21 @@ def test_multiple_query_items_included_in_marshall_results(self): collection = portal['collection'] rfc822 = collection.manage_FTPget() data = parseRFC822(rfc822) - + self.assertIn('query0_i', data[0]) self.assertIn('query0_o', data[0]) self.assertIn('query0_v', data[0]) self.assertIn('query1_i', data[0]) self.assertIn('query1_o', data[0]) self.assertIn('query1_v', data[0]) - + self.assertEqual(data[0]['query0_i'], query[0]['i']) self.assertEqual(data[0]['query0_o'], query[0]['o']) self.assertEqual(data[0]['query0_v'], query[0]['v']) self.assertEqual(data[0]['query1_i'], query[1]['i']) self.assertEqual(data[0]['query1_o'], query[1]['o']) self.assertEqual(data[0]['query1_v'], query[1]['v']) - + def test_query_gets_set_on_PUT(self): portal = self.layer['portal'] login(portal, 'admin') @@ -307,13 +469,13 @@ def test_query_gets_set_on_PUT(self): 'o': 'plone.app.querystring.operation.string.is', 'v': 'News Item', }] - + expected_query = [{ 'i': 'portal_type', 'o': 'plone.app.querystring.operation.string.is', 'v': 'LOREM IPSUM DOLOR', }] - + portal.invokeFactory("Collection", "collection", query=query, @@ -322,8 +484,7 @@ def test_query_gets_set_on_PUT(self): rfc822 = collection.manage_FTPget() # Modify the response to put in a sentinal, to check it's been updated rfc822 = rfc822.replace(query[0]['v'], expected_query[0]['v']) - + portal.REQUEST.set("BODY", rfc822) collection.PUT(portal.REQUEST, None) self.assertEqual(collection.query, expected_query) - Repository: plone.app.collection Branch: refs/heads/master Date: 2015-02-27T18:30:41+01:00 Author: Jure Cerjak (jcerjak) <jcerjak@termitnjak.si> Commit: plone/plone.app.collection@8dc58e5 don't do bare excepts Files changed: M plone/app/collection/tests/test_collection.py diff --git a/plone/app/collection/tests/test_collection.py b/plone/app/collection/tests/test_collection.py index b2640ff..0804004 100644 --- a/plone/app/collection/tests/test_collection.py +++ b/plone/app/collection/tests/test_collection.py @@ -1,3 +1,4 @@ +from Products.Archetypes.Marshall import parseRFC822 from Products.CMFCore.utils import getToolByName from plone.app.collection.testing import PLONEAPPCOLLECTION_INTEGRATION_TESTING from plone.app.testing import TEST_USER_ID @@ -7,7 +8,7 @@ from plone.app.testing import setRoles from plone.testing.z2 import Browser from transaction import commit -from Products.Archetypes.Marshall import parseRFC822 +from zExceptions import BadRequest import unittest2 as unittest @@ -131,7 +132,7 @@ def test_show_about_no_registry_has_property_noshow(self): try: properties.site_properties.manage_addProperty( 'allowAnonymousViewAbout', False, 'boolean') - except: + except BadRequest: properties.site_properties.manage_changeProperties( allowAnonymousViewAbout=False) self.portal.portal_registry = None @@ -153,7 +154,7 @@ def test_show_about_no_registry_has_property_show(self): try: properties.site_properties.manage_addProperty( 'allowAnonymousViewAbout', True, 'boolean') - except: + except BadRequest: properties.site_properties.manage_changeProperties( allowAnonymousViewAbout=True) self.portal.portal_registry = None @@ -176,7 +177,7 @@ def test_show_about_has_property_and_registry_noshow(self): try: properties.site_properties.manage_addProperty( 'allowAnonymousViewAbout', False, 'boolean') - except: + except BadRequest: properties.site_properties.manage_changeProperties( allowAnonymousViewAbout=False) self.portal.portal_registry = {} # mock the registry @@ -199,7 +200,7 @@ def test_show_about_has_property_and_registry_show(self): try: properties.site_properties.manage_addProperty( 'allowAnonymousViewAbout', True, 'boolean') - except: + except BadRequest: properties.site_properties.manage_changeProperties( allowAnonymousViewAbout=True) self.portal.portal_registry = {} # mock the registry @@ -222,7 +223,7 @@ def test_show_about_has_registry_no_property_noshow(self): try: properties.site_properties.manage_delProperties( ['allowAnonymousViewAbout']) - except: + except BadRequest: pass self.portal.portal_registry = {'plone.allow_anon_views_about': False} @@ -244,7 +245,7 @@ def test_show_about_has_registry_no_property_show(self): try: properties.site_properties.manage_delProperties( ['allowAnonymousViewAbout']) - except: + except BadRequest: pass self.portal.portal_registry = {'plone.allow_anon_views_about': True} @@ -264,7 +265,7 @@ def test_show_about_logged_in(self): try: properties.site_properties.manage_addProperty( 'allowAnonymousViewAbout', False, 'boolean') - except: + except BadRequest: properties.site_properties.manage_changeProperties( allowAnonymousViewAbout=False) self.portal.portal_registry = {'plone.allow_anon_views_about': False} Repository: plone.app.collection Branch: refs/heads/master Date: 2015-03-02T18:07:09+01:00 Author: Timo Stollenwerk (tisto) <tisto@plone.org> Commit: plone/plone.app.collection@f50678f Merge pull request #22 from plone/plip10359-security-controlpanel Plip 10359 - Security Control Panel migration Files changed: M CHANGES.rst M plone/app/collection/browser/templates/standard_view.pt M plone/app/collection/tests/test_collection.py diff --git a/CHANGES.rst b/CHANGES.rst index 734edfa..10ee51a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,10 @@ Changelog 1.1.3 (unreleased) ------------------ +- Read ``allow_anon_views_about`` setting from the registry, with fallback to + portal properties (see plone/Products.CMFPlone#216) + [jcerjak] + - Support for import and export of collections using FTP, DAV and GenericSetup [matthewwilkes] diff --git a/plone/app/collection/browser/templates/standard_view.pt b/plone/app/collection/browser/templates/standard_view.pt index 052ebf8..2d036bc 100644 --- a/plone/app/collection/browser/templates/standard_view.pt +++ b/plone/app/collection/browser/templates/standard_view.pt @@ -29,11 +29,14 @@ <tal:results define="b_start python:request.get('b_start', 0); batch python:context.results(b_start=b_start); site_properties context/portal_properties/site_properties; + portal_registry context/portal_registry|nothing; use_view_action site_properties/typesUseViewActionInListings|python:(); isAnon context/@@plone_portal_state/anonymous; normalizeString nocall: context/plone_utils/normalizeString; toLocalizedTime nocall: context/@@plone/toLocalizedTime; - show_about python:not isAnon or site_properties.allowAnonymousViewAbout; + show_about_bbb site_properties/allowAnonymousViewAbout|nothing; + show_about_registry python:portal_registry and portal_registry.get('plone.allow_anon_views_about'); + show_about python:not isAnon or show_about_registry or show_about_bbb; navigation_root_url context/@@plone_portal_state/navigation_root_url; pas_member context/@@pas_member;"> <tal:listing condition="batch"> diff --git a/plone/app/collection/tests/test_collection.py b/plone/app/collection/tests/test_collection.py index 9599d3e..0804004 100644 --- a/plone/app/collection/tests/test_collection.py +++ b/plone/app/collection/tests/test_collection.py @@ -1,3 +1,4 @@ +from Products.Archetypes.Marshall import parseRFC822 from Products.CMFCore.utils import getToolByName from plone.app.collection.testing import PLONEAPPCOLLECTION_INTEGRATION_TESTING from plone.app.testing import TEST_USER_ID @@ -7,7 +8,7 @@ from plone.app.testing import setRoles from plone.testing.z2 import Browser from transaction import commit -from Products.Archetypes.Marshall import parseRFC822 +from zExceptions import BadRequest import unittest2 as unittest @@ -42,6 +43,14 @@ def setUp(self): pass self.collection = self.portal['col'] + def _set_up_collection(self): + self.portal.invokeFactory( + 'Document', + 'doc1', + title='Collection Test Page' + ) + self.collection.setQuery(query) + def test_addCollection(self): self.portal.invokeFactory("Collection", "col1", @@ -114,6 +123,160 @@ def test_viewingCollection(self): browser.open(self.collection.absolute_url()) self.assertTrue("Collection Test Page" in browser.contents) + def test_show_about_no_registry_has_property_noshow(self): + """Test the case where we fetch show about information from portal + properties (Plone < 5) and show about is False. + """ + # disable show about in site properties + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', False, 'boolean') + except BadRequest: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=False) + self.portal.portal_registry = None + + self._set_up_collection() + + # logout and check if author information is hidden + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertFalse("author" in result) + self.assertFalse("test-user" in result) + + def test_show_about_no_registry_has_property_show(self): + """Test the case where we fetch show about information from portal + properties (Plone < 5) and show about is True. + """ + # enable show about in site properties + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', True, 'boolean') + except BadRequest: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=True) + self.portal.portal_registry = None + + self._set_up_collection() + + # logout and check if author information is shown + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + + def test_show_about_has_property_and_registry_noshow(self): + """Test the case where we fetch show about information from portal + properties, but registry is also present (Plone < 5, with + plone.app.registry installed) and show about is False. + """ + # disable show about in site properties, create an empty registry + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', False, 'boolean') + except BadRequest: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=False) + self.portal.portal_registry = {} # mock the registry + + self._set_up_collection() + + # logout and check if author information is hidden + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertFalse("author" in result) + self.assertFalse("test-user" in result) + + def test_show_about_has_property_and_registry_show(self): + """Test the case where we fetch show about information from portal + properties, but registry is also present (Plone < 5, with + plone.app.registry installed) and show about is True. + """ + # enable show about in site properties, create an empty registry + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', True, 'boolean') + except BadRequest: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=True) + self.portal.portal_registry = {} # mock the registry + + self._set_up_collection() + + # logout and check if author information is shown + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + + def test_show_about_has_registry_no_property_noshow(self): + """Test the case where we fetch show about information from the + registry (Plone >= 5) and show about is False. + """ + # disable show about in the registry, delete 'allowAnonymousViewAbout' + # property + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_delProperties( + ['allowAnonymousViewAbout']) + except BadRequest: + pass + self.portal.portal_registry = {'plone.allow_anon_views_about': False} + + self._set_up_collection() + + # logout and check if author information is hidden + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertFalse("author" in result) + self.assertFalse("test-user" in result) + + def test_show_about_has_registry_no_property_show(self): + """Test the case where we fetch show about information from the + registry (Plone >= 5) and show about is True. + """ + # enable show about in the registry, delete 'allowAnonymousViewAbout' + # property + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_delProperties( + ['allowAnonymousViewAbout']) + except BadRequest: + pass + self.portal.portal_registry = {'plone.allow_anon_views_about': True} + + self._set_up_collection() + + # logout and check if author information is shown + logout() + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + + def test_show_about_logged_in(self): + """Test the case where we show about information if a user is logged in + even though show about is set to False + """ + properties = getToolByName(self.portal, 'portal_properties') + try: + properties.site_properties.manage_addProperty( + 'allowAnonymousViewAbout', False, 'boolean') + except BadRequest: + properties.site_properties.manage_changeProperties( + allowAnonymousViewAbout=False) + self.portal.portal_registry = {'plone.allow_anon_views_about': False} + + self._set_up_collection() + + # check if author information is shown + result = self.collection.restrictedTraverse('standard_view')() + self.assertTrue("author" in result) + self.assertTrue("test-user" in result) + def test_collection_templates(self): data = getData('image.png') # add an image that will be listed by the collection @@ -260,11 +423,11 @@ def test_simple_query_included_in_marshall_results(self): self.assertIn('query0_i', data[0]) self.assertIn('query0_o', data[0]) self.assertIn('query0_v', data[0]) - + self.assertEqual(data[0]['query0_i'], query[0]['i']) self.assertEqual(data[0]['query0_o'], query[0]['o']) self.assertEqual(data[0]['query0_v'], query[0]['v']) - + def test_multiple_query_items_included_in_marshall_results(self): portal = self.layer['portal'] login(portal, 'admin') @@ -276,7 +439,7 @@ def test_multiple_query_items_included_in_marshall_results(self): 'o': 'plone.app.querystring.operation.string.is', 'v': 'Test News Item', }] - + portal.invokeFactory("Collection", "collection", query=query, @@ -284,21 +447,21 @@ def test_multiple_query_items_included_in_marshall_results(self): collection = portal['collection'] rfc822 = collection.manage_FTPget() data = parseRFC822(rfc822) - + self.assertIn('query0_i', data[0]) self.assertIn('query0_o', data[0]) self.assertIn('query0_v', data[0]) self.assertIn('query1_i', data[0]) self.assertIn('query1_o', data[0]) self.assertIn('query1_v', data[0]) - + self.assertEqual(data[0]['query0_i'], query[0]['i']) self.assertEqual(data[0]['query0_o'], query[0]['o']) self.assertEqual(data[0]['query0_v'], query[0]['v']) self.assertEqual(data[0]['query1_i'], query[1]['i']) self.assertEqual(data[0]['query1_o'], query[1]['o']) self.assertEqual(data[0]['query1_v'], query[1]['v']) - + def test_query_gets_set_on_PUT(self): portal = self.layer['portal'] login(portal, 'admin') @@ -307,13 +470,13 @@ def test_query_gets_set_on_PUT(self): 'o': 'plone.app.querystring.operation.string.is', 'v': 'News Item', }] - + expected_query = [{ 'i': 'portal_type', 'o': 'plone.app.querystring.operation.string.is', 'v': 'LOREM IPSUM DOLOR', }] - + portal.invokeFactory("Collection", "collection", query=query, @@ -322,8 +485,7 @@ def test_query_gets_set_on_PUT(self): rfc822 = collection.manage_FTPget() # Modify the response to put in a sentinal, to check it's been updated rfc822 = rfc822.replace(query[0]['v'], expected_query[0]['v']) - + portal.REQUEST.set("BODY", rfc822) collection.PUT(portal.REQUEST, None) self.assertEqual(collection.query, expected_query) -
All pull requests merged. |
This has been already done in the z3c.form branch of plone.app.contenttypes:
https://github.com/plone/plone.app.controlpanel/blob/plip10359-z3cform/plone/app/controlpanel/browser/security.py
The text was updated successfully, but these errors were encountered: