Skip to content
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

More python 3 issues #34

Merged
merged 13 commits into from
Sep 14, 2018
17 changes: 16 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,26 @@ Breaking changes:

New features:

- Make imports work with python 3. Fix startup.
- Make it work in Python 3:
Make imports work.
Fix startup.
Fix setting the auth-cookie.
Fix assignment of MemberData-functions during startup.
User properties are text.
Fix scaling user profile.
Migrate all tests away from PloneTestCasei.
Fix other tests.
[pbauer]

Bug fixes:

- InitializeClass was moved to AccessControl.class_init
[jensens]

- setDefaultRoles is deprecated.
addPermission from AccessControl.Permission is used.
[jensens]

- Removed ``Extensions/Install.py`` which had only backwards compatibility imports.
[maurits]

Expand Down
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
'setuptools',
'six',
'zope.deprecation',
'Zope2 >=2.13.22',
'Zope',
]

setup(
Expand All @@ -35,6 +35,8 @@
"License :: OSI Approved :: Zope Public License",
"Programming Language :: Python",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
],
keywords='Zope CMF Plone PAS authentication',
author='Kapil Thangavelu, Wichert Akkerman',
Expand Down
12 changes: 6 additions & 6 deletions src/Products/PlonePAS/permissions.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
from Products.CMFCore.permissions import setDefaultRoles
from AccessControl.Permission import addPermission

AddGroups = 'Add Groups'
setDefaultRoles(AddGroups, ('Manager',))
addPermission(AddGroups, default_roles=('Manager',))

ManageGroups = 'Manage Groups'
setDefaultRoles(ManageGroups, ('Manager',))
addPermission(ManageGroups, default_roles=('Manager',))

ViewGroups = 'View Groups'
setDefaultRoles(ViewGroups, ('Manager', 'Owner', 'Member'))
addPermission(ViewGroups, default_roles=('Manager', 'Owner', 'Member'))

DeleteGroups = 'Delete Groups'
setDefaultRoles(DeleteGroups, ('Manager', ))
addPermission(DeleteGroups, default_roles=('Manager', ))

SetGroupOwnership = 'Set Group Ownership'
setDefaultRoles(SetGroupOwnership, ('Manager', 'Owner'))
addPermission(SetGroupOwnership, default_roles=('Manager', 'Owner'))
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/autogroup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.PlonePAS.interfaces.group import IGroupIntrospection
from Products.PluggableAuthService.PropertiedUser import PropertiedUser
Expand Down
8 changes: 6 additions & 2 deletions src/Products/PlonePAS/plugins/cookie_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from AccessControl.SecurityManagement import getSecurityManager
from Acquisition import aq_base
from Acquisition import aq_parent
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from base64 import encodestring
from Products.PluggableAuthService.interfaces.authservice import \
Expand Down Expand Up @@ -70,7 +70,11 @@ def updateCredentials(self, request, response, login, new_password):

setAuthCookie = getattr(self, 'setAuthCookie', None)
if setAuthCookie:
cookie_val = encodestring('%s:%s' % (login, new_password))
cookie_str = b':'.join([
login.encode('utf-8'),
new_password.encode('utf-8'),
])
cookie_val = encodestring(cookie_str)
cookie_val = cookie_val.rstrip()
setAuthCookie(response, self.cookie_name, quote(cookie_val))
else:
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/crumbler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"""
from AccessControl.SecurityInfo import ClassSecurityInfo
from Acquisition import aq_base
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from OFS.Folder import Folder
from Products.CMFCore.CookieCrumbler import manage_addCC
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

"""
from AccessControl import ClassSecurityInfo
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from BTrees.OOBTree import OOBTree
from BTrees.OOBTree import OOSet
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/local_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from AccessControl import ClassSecurityInfo
from Acquisition import aq_inner
from Acquisition import aq_parent
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin
from Products.PluggableAuthService.plugins.LocalRolePlugin \
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/passwordpolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Mutable Property Provider
"""
from AccessControl import ClassSecurityInfo
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.PluggableAuthService.interfaces.plugins import IValidationPlugin
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Mutable Property Provider
"""
from AccessControl import ClassSecurityInfo
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from BTrees.OOBTree import OOBTree
from Products.CMFCore.utils import getToolByName
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from Acquisition import aq_get
from Acquisition import aq_inner
from Acquisition import aq_parent
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from Products.PlonePAS.interfaces.capabilities import IAssignRoleCapability
from Products.PlonePAS.utils import getGroupsForPrincipal
Expand Down
6 changes: 3 additions & 3 deletions src/Products/PlonePAS/plugins/ufactory.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from AccessControl import ClassSecurityInfo
from AccessControl.PermissionRole import _what_not_even_god_should_do
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin
from Products.PlonePAS.interfaces.propertysheets import IMutablePropertySheet
Expand Down Expand Up @@ -215,7 +215,7 @@ def setProperties(self, properties=None, **kw):
continue

update = {}
for (key, value) in properties.items():
for (key, value) in list(properties.items()):
if sheet.hasProperty(key):
update[key] = value
del properties[key]
Expand All @@ -227,7 +227,7 @@ def getProperty(self, id, default=_marker):
for sheet in self.getOrderedPropertySheets():
if sheet.hasProperty(id):
value = sheet.getProperty(id)
if isinstance(value, six.text_type):
if six.PY2 and isinstance(value, six.text_type):
# XXX Temporarily work around the fact that
# property sheets blindly store and return
# unicode. This is sub-optimal and should be
Expand Down
2 changes: 1 addition & 1 deletion src/Products/PlonePAS/plugins/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from AccessControl import AuthEncoding
from AccessControl import ClassSecurityInfo
from AccessControl.Permissions import manage_users as ManageUsers
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
from App.special_dtml import DTMLFile
from Products.PlonePAS.interfaces.capabilities import IDeleteCapability
from Products.PlonePAS.interfaces.capabilities import IPasswordSetCapability
Expand Down
52 changes: 52 additions & 0 deletions src/Products/PlonePAS/testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.app.testing import applyProfile
from plone.app.testing import FunctionalTesting
from plone.app.testing import IntegrationTesting
from plone.app.testing import PloneSandboxLayer
from plone.testing import z2

import Products.PlonePAS


class ProductsPlonepasLayer(PloneSandboxLayer):

defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,)

def setUpZope(self, app, configurationContext):
# Load any other ZCML that is required for your tests.
# The z3c.autoinclude feature is disabled in the Plone fixture base
# layer.
self.loadZCML(package=Products.PlonePAS)
z2.installProduct(app, 'Products.PlonePAS')

def setUpPloneSite(self, portal):
applyProfile(portal, 'Products.PlonePAS:PlonePAS')
# setRoles(portal, TEST_USER_ID, ['Manager'])
from Products.CMFPlone.utils import _createObjectByType
_createObjectByType('Folder', portal, id='Members')
mtool = portal.portal_membership
if not mtool.getMemberareaCreationFlag():
mtool.setMemberareaCreationFlag()
mtool.createMemberArea(TEST_USER_ID)
if mtool.getMemberareaCreationFlag():
mtool.setMemberareaCreationFlag()

_createObjectByType('Folder', portal, id='folder')


PRODUCTS_PLONEPAS_FIXTURE = ProductsPlonepasLayer()


PRODUCTS_PLONEPAS_INTEGRATION_TESTING = IntegrationTesting(
bases=(PRODUCTS_PLONEPAS_FIXTURE,),
name='ProductsPlonepasLayer:IntegrationTesting',
)


PRODUCTS_PLONEPAS_FUNCTIONAL_TESTING = FunctionalTesting(
bases=(PRODUCTS_PLONEPAS_FIXTURE,),
name='ProductsPlonepasLayer:FunctionalTesting',
)
3 changes: 0 additions & 3 deletions src/Products/PlonePAS/tests/base.py

This file was deleted.

22 changes: 11 additions & 11 deletions src/Products/PlonePAS/tests/cookie_auth.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ User in Plone Site
Plone Site has PAS installed

>>> portal = layer['portal']
>>> print portal.acl_users.meta_type
>>> print(portal.acl_users.meta_type)
Pluggable Auth Service

User exists in the user folder inside the Plone Site.

>>> uf = portal.acl_users
>>> print uf.meta_type
>>> print(uf.meta_type)
Pluggable Auth Service

>>> user_name, user_password, user_role = ('foo', 'bar', 'Manager')
Expand All @@ -32,7 +32,7 @@ Login to Plone Site using Basic Auth works.
>>> browser = Browser(layer['app'])
>>> browser.addHeader('Authorization', 'Basic %s:%s' % (TEST_USER_NAME, TEST_USER_PASSWORD,))
>>> browser.open('%s/manage' % portal.absolute_url())
>>> print browser.headers
>>> print(browser.headers)
Status: 200 ...

Make sure cookie plugin is installed and activated.
Expand All @@ -53,13 +53,13 @@ Make sure cookie plugin is installed and activated.
... pass

>>> for active, iface in actives:
... print iface,
... print(iface)
... for id, plugin in active:
... if id == 'credentials_cookie_auth':
... print True
<...IExtraction...> True
<...IChallenge...> True
<...ICredentialsUpdate...> <...ICredentialsReset...>
... print(True)
<...IExtraction...>...True
<...IChallenge...>...True
<...ICredentialsUpdate...>...<...ICredentialsReset...>

User in parent folder
---------------------
Expand All @@ -68,7 +68,7 @@ User Exists on the folder containing the Plone Site, which should be a
Pluggable Auth Service too.

>>> uf = layer['app'].acl_users
>>> print uf.meta_type
>>> print(uf.meta_type)
Pluggable Auth Service

>>> user_name, user_password, user_role = ('baz', 'bar', 'Manager')
Expand All @@ -85,14 +85,14 @@ Login directly to containing folder using Basic Auth works.
>>> browser = Browser(layer['app'])
>>> browser.addHeader('Authorization', 'Basic %s:%s' % (user_name, user_password,))
>>> browser.open('%s/manage' % layer['app'].absolute_url())
>>> print browser.headers
>>> print(browser.headers)
Status: 200 ...

Login to Plone Site using Basic Auth works.

>>> browser = Browser(layer['app'])
>>> browser.addHeader('Authorization', 'Basic %s:%s' % (user_name, user_password,))
>>> browser.open('%s/manage' % portal.absolute_url())
>>> print browser.headers
>>> print(browser.headers)
Status: 200 ...

6 changes: 3 additions & 3 deletions src/Products/PlonePAS/tests/dummy.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from OFS.SimpleItem import SimpleItem
from six import StringIO
from six import BytesIO
from ZPublisher.HTTPRequest import FileUpload

TEXT = 'file data'
TEXT = b'file data'


class FieldStorage(object):
Expand Down Expand Up @@ -33,7 +33,7 @@ def __init__(self, filename=None, data=None, headers=None):
self.data = data
if headers is not None:
self.headers = headers
self.file = StringIO(self.data)
self.file = BytesIO(self.data)

def seek(self, *args):
pass
Expand Down
30 changes: 16 additions & 14 deletions src/Products/PlonePAS/tests/test_basic_ops.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
# -*- coding: utf-8 -*-
from Products.PlonePAS.tests import base
from Products.PluggableAuthService.PluggableAuthService import \
_SWALLOWABLE_PLUGIN_EXCEPTIONS
from Products.PluggableAuthService.interfaces.authservice import \
IPluggableAuthService
from Products.PluggableAuthService.interfaces.events import \
IPrincipalDeletedEvent
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING
from Products.PluggableAuthService.interfaces.authservice import IPluggableAuthService
from Products.PluggableAuthService.interfaces.events import IPrincipalDeletedEvent
from Products.PluggableAuthService.interfaces.plugins import IRolesPlugin
from Products.PluggableAuthService.PluggableAuthService import _SWALLOWABLE_PLUGIN_EXCEPTIONS
from zope.component import adapter
from zope.component import getGlobalSiteManager

import unittest

class BasicOpsTestCase(base.TestCase):

def afterSetUp(self):
self.loginAsPortalOwner()
class BasicOpsTestCase(unittest.TestCase):

layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.acl_users = self.portal.acl_users

def compareRoles(self, target, user, roles):
Expand All @@ -32,11 +36,9 @@ def compareRoles(self, target, user, roles):
user_roles = list(u.getRoles())
else:
user_roles = list(u.getRolesInContext(target))
actual_roles = filter(lambda x: x not in non_roles, user_roles)
actual_roles.sort()
actual_roles = list(filter(lambda x: x not in non_roles, user_roles))
wished_roles = list(roles)
wished_roles.sort()
if actual_roles == wished_roles:
if sorted(actual_roles) == sorted(wished_roles):
return 1
raise RuntimeError("User %s: Whished roles: %s BUT current "
"roles: %s" % (user, wished_roles, actual_roles))
Expand Down
Loading