diff --git a/CHANGES.rst b/CHANGES.rst index 3e3653f6..f7f37333 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -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] diff --git a/setup.py b/setup.py index 009c32f6..5114586f 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ 'setuptools', 'six', 'zope.deprecation', - 'Zope2 >=2.13.22', + 'Zope', ] setup( @@ -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', diff --git a/src/Products/PlonePAS/permissions.py b/src/Products/PlonePAS/permissions.py index 126932a3..0ab494d1 100644 --- a/src/Products/PlonePAS/permissions.py +++ b/src/Products/PlonePAS/permissions.py @@ -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')) diff --git a/src/Products/PlonePAS/plugins/autogroup.py b/src/Products/PlonePAS/plugins/autogroup.py index 8ec0ee3f..5783ef63 100644 --- a/src/Products/PlonePAS/plugins/autogroup.py +++ b/src/Products/PlonePAS/plugins/autogroup.py @@ -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 diff --git a/src/Products/PlonePAS/plugins/cookie_handler.py b/src/Products/PlonePAS/plugins/cookie_handler.py index a301a1ed..e3103c31 100644 --- a/src/Products/PlonePAS/plugins/cookie_handler.py +++ b/src/Products/PlonePAS/plugins/cookie_handler.py @@ -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 \ @@ -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: diff --git a/src/Products/PlonePAS/plugins/crumbler.py b/src/Products/PlonePAS/plugins/crumbler.py index 0061e1a3..1c940fc9 100644 --- a/src/Products/PlonePAS/plugins/crumbler.py +++ b/src/Products/PlonePAS/plugins/crumbler.py @@ -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 diff --git a/src/Products/PlonePAS/plugins/group.py b/src/Products/PlonePAS/plugins/group.py index 2bc36bf6..bbbd21ed 100644 --- a/src/Products/PlonePAS/plugins/group.py +++ b/src/Products/PlonePAS/plugins/group.py @@ -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 diff --git a/src/Products/PlonePAS/plugins/local_role.py b/src/Products/PlonePAS/plugins/local_role.py index f09ef382..93e76b5d 100644 --- a/src/Products/PlonePAS/plugins/local_role.py +++ b/src/Products/PlonePAS/plugins/local_role.py @@ -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 \ diff --git a/src/Products/PlonePAS/plugins/passwordpolicy.py b/src/Products/PlonePAS/plugins/passwordpolicy.py index 0b3c29a8..f0e36f89 100644 --- a/src/Products/PlonePAS/plugins/passwordpolicy.py +++ b/src/Products/PlonePAS/plugins/passwordpolicy.py @@ -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 diff --git a/src/Products/PlonePAS/plugins/property.py b/src/Products/PlonePAS/plugins/property.py index 799bd379..430a9dfa 100644 --- a/src/Products/PlonePAS/plugins/property.py +++ b/src/Products/PlonePAS/plugins/property.py @@ -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 diff --git a/src/Products/PlonePAS/plugins/role.py b/src/Products/PlonePAS/plugins/role.py index 8a0b4442..9c836ae0 100644 --- a/src/Products/PlonePAS/plugins/role.py +++ b/src/Products/PlonePAS/plugins/role.py @@ -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 diff --git a/src/Products/PlonePAS/plugins/ufactory.py b/src/Products/PlonePAS/plugins/ufactory.py index 6663650b..9be8b467 100644 --- a/src/Products/PlonePAS/plugins/ufactory.py +++ b/src/Products/PlonePAS/plugins/ufactory.py @@ -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 @@ -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] @@ -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 diff --git a/src/Products/PlonePAS/plugins/user.py b/src/Products/PlonePAS/plugins/user.py index 79ee8f0f..5a4d8ace 100644 --- a/src/Products/PlonePAS/plugins/user.py +++ b/src/Products/PlonePAS/plugins/user.py @@ -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 diff --git a/src/Products/PlonePAS/testing.py b/src/Products/PlonePAS/testing.py new file mode 100644 index 00000000..39bcf180 --- /dev/null +++ b/src/Products/PlonePAS/testing.py @@ -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', +) diff --git a/src/Products/PlonePAS/tests/base.py b/src/Products/PlonePAS/tests/base.py deleted file mode 100644 index 20038455..00000000 --- a/src/Products/PlonePAS/tests/base.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- -from plone.app.testing.bbb import PloneTestCase as TestCase # noqa -from plone.app.testing.bbb import PloneTestCase as FunctionalTestCase # noqa diff --git a/src/Products/PlonePAS/tests/cookie_auth.rst b/src/Products/PlonePAS/tests/cookie_auth.rst index e5b0e795..7405a560 100644 --- a/src/Products/PlonePAS/tests/cookie_auth.rst +++ b/src/Products/PlonePAS/tests/cookie_auth.rst @@ -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') @@ -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. @@ -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 --------------------- @@ -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') @@ -85,7 +85,7 @@ 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. @@ -93,6 +93,6 @@ 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 ... diff --git a/src/Products/PlonePAS/tests/dummy.py b/src/Products/PlonePAS/tests/dummy.py index 5c7a8c36..3dfede87 100644 --- a/src/Products/PlonePAS/tests/dummy.py +++ b/src/Products/PlonePAS/tests/dummy.py @@ -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): @@ -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 diff --git a/src/Products/PlonePAS/tests/test_basic_ops.py b/src/Products/PlonePAS/tests/test_basic_ops.py index 55188058..220d8960 100644 --- a/src/Products/PlonePAS/tests/test_basic_ops.py +++ b/src/Products/PlonePAS/tests/test_basic_ops.py @@ -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): @@ -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)) diff --git a/src/Products/PlonePAS/tests/test_doctests.py b/src/Products/PlonePAS/tests/test_doctests.py index 9e2c509c..73647bfd 100644 --- a/src/Products/PlonePAS/tests/test_doctests.py +++ b/src/Products/PlonePAS/tests/test_doctests.py @@ -1,10 +1,20 @@ # -*- coding: utf-8 -*- -from plone.app.testing.bbb import PTC_FUNCTIONAL_TESTING +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_FUNCTIONAL_TESTING from plone.testing import layered + import doctest +import re +import six import unittest +class Py23DocChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if six.PY2: + got = re.sub("IOError", "OSError", got) + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + def test_suite(): suite = unittest.TestSuite() suite.addTest( @@ -12,15 +22,17 @@ def test_suite(): doctest.DocFileSuite( 'cookie_auth.rst', package='Products.PlonePAS.tests', - optionflags=doctest.ELLIPSIS + optionflags=doctest.ELLIPSIS, + checker=Py23DocChecker(), ), - layer=PTC_FUNCTIONAL_TESTING + layer=PRODUCTS_PLONEPAS_FUNCTIONAL_TESTING ) ) suite.addTest( doctest.DocTestSuite( 'Products.PlonePAS.utils', - optionflags=doctest.ELLIPSIS + optionflags=doctest.ELLIPSIS, + checker=Py23DocChecker(), ) ) return suite diff --git a/src/Products/PlonePAS/tests/test_groupdatatool.py b/src/Products/PlonePAS/tests/test_groupdatatool.py index 343c6e7a..d69da2d9 100644 --- a/src/Products/PlonePAS/tests/test_groupdatatool.py +++ b/src/Products/PlonePAS/tests/test_groupdatatool.py @@ -2,9 +2,12 @@ from AccessControl import Permissions from AccessControl import Unauthorized from Acquisition import aq_parent -from Products.PlonePAS.tests import base from plone.app.testing import TEST_USER_ID from plone.app.testing import TEST_USER_NAME +from plone.app.testing import logout +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING + +import unittest def sortTuple(t): @@ -13,9 +16,12 @@ def sortTuple(t): return tuple(l) -class TestGroupDataTool(base.TestCase): +class TestGroupDataTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.acl_users = self.portal.acl_users self.groups = self.portal.portal_groups self.groupdata = self.portal.portal_groupdata @@ -35,9 +41,12 @@ def testWrapGroup(self): 'GroupManager') -class TestGroupData(base.TestCase): +class TestGroupData(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.memberdata = self.portal.portal_memberdata self.acl_users = self.portal.acl_users @@ -73,13 +82,13 @@ def testGroupMembersAreWrapped(self): self.assertEqual(aq_parent(ms[0]).__class__.__name__, 'PluggableAuthService') def testAddMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) g = self.groups.getGroupById('foo') g.addMember(TEST_USER_ID) self.assertEqual(g.getGroupMembers()[0].getId(), TEST_USER_ID) def testRemoveMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) g = self.groups.getGroupById('foo') g.addMember(TEST_USER_ID) g.removeMember(TEST_USER_ID) @@ -121,6 +130,7 @@ def testGetRoles(self): ('Authenticated', 'Member')) def testGetRolesInContext(self): + self.folder = self.portal['folder'] g = self.groups.getGroupById('foo') self.acl_users.userSetGroups(TEST_USER_ID, groupnames=['foo']) user = self.acl_users.getUser(TEST_USER_NAME) @@ -145,19 +155,22 @@ def testHasRole(self): self.assertTrue(g.has_role('Member')) -class TestMethodProtection(base.TestCase): +class TestMethodProtection(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.groups = self.portal.portal_groups self.groups.addGroup('foo') self.groupdata = self.groups.getGroupById('foo') def testAnonAddMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.addMember, TEST_USER_ID) def testAnonRemoveMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.removeMember, TEST_USER_ID) @@ -169,10 +182,10 @@ def testMemberRemoveMember(self): TEST_USER_ID) def testManagerAddMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) def testManagerRemoveMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) self.groupdata.removeMember(TEST_USER_ID) diff --git a/src/Products/PlonePAS/tests/test_groupstool.py b/src/Products/PlonePAS/tests/test_groupstool.py index fce58aa7..da81fd0a 100644 --- a/src/Products/PlonePAS/tests/test_groupstool.py +++ b/src/Products/PlonePAS/tests/test_groupstool.py @@ -3,16 +3,20 @@ from AccessControl import Unauthorized from Acquisition import aq_base from Acquisition import aq_parent +from plone.app.testing import setRoles +from plone.app.testing import logout +from plone.app.testing import TEST_USER_ID +from plone.app.testing import TEST_USER_ID from Products.CMFCore.utils import getToolByName from Products.PlonePAS.plugins.group import PloneGroup -from Products.PlonePAS.tests import base +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING from Products.PlonePAS.tools.groupdata import GroupData -from Products.PluggableAuthService.interfaces.events import \ - IGroupDeletedEvent -from plone.app.testing import TEST_USER_ID +from Products.PluggableAuthService.interfaces.events import IGroupDeletedEvent from zope.component import adapter from zope.component import getGlobalSiteManager +import unittest + def sortTuple(t): l = list(t) @@ -20,15 +24,18 @@ def sortTuple(t): return tuple(l) -class GroupsToolTest(base.TestCase): +class TestGroupsTool(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.gt = getToolByName(self.portal, 'portal_groups') self.gd = getToolByName(self.portal, 'portal_groupdata') self.group_id = 'group1' # Create a new Group - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.gt.addGroup( self.group_id, ['Reviewer'], @@ -89,20 +96,23 @@ def test_edit_group(self): self.assertTrue('Reviewers' in group.getGroups()) -class TestMethodProtection(base.TestCase): +class TestMethodProtection(unittest.TestCase): # GroupData has wrong security declarations - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.groups = self.portal.portal_groups self.groups.addGroup('foo') self.groupdata = self.groups.getGroupById('foo') def testAnonAddMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.addMember, TEST_USER_ID) def testAnonRemoveMember(self): - self.logout() + logout() self.assertRaises(Unauthorized, self.groupdata.removeMember, TEST_USER_ID) @@ -114,21 +124,25 @@ def testMemberRemoveMember(self): TEST_USER_ID) def testManagerAddMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) def testManagerRemoveMember(self): - self.setPermissions([Permissions.manage_users]) + self.portal.manage_role('Member', [Permissions.manage_users]) self.groupdata.addMember(TEST_USER_ID) self.groupdata.removeMember(TEST_USER_ID) -class TestGroupsTool(base.TestCase): +class TestGroupsTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.acl_users = self.portal.acl_users self.groups = self.portal.portal_groups + self.folder = self.portal['folder'] if 'auto_group' in self.acl_users: self.acl_users.manage_delObjects(['auto_group']) @@ -262,7 +276,7 @@ def testGetGroupInfo(self): def testGetGroupInfoAsAnonymous(self): self.groups.addGroup('foo', title='Foo', description='Bar') - self.logout() + logout() info = self.groups.restrictedTraverse('getGroupInfo')('foo') self.assertEqual(info.get('title'), 'Foo') self.assertEqual(info.get('description'), 'Bar') diff --git a/src/Products/PlonePAS/tests/test_memberdatatool.py b/src/Products/PlonePAS/tests/test_memberdatatool.py index 440322aa..c4321242 100644 --- a/src/Products/PlonePAS/tests/test_memberdatatool.py +++ b/src/Products/PlonePAS/tests/test_memberdatatool.py @@ -2,13 +2,18 @@ from DateTime import DateTime from OFS.Image import Image from plone.app.testing import TEST_USER_ID as default_user -from Products.PlonePAS.tests import base from Products.PlonePAS.tests import dummy +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING +import unittest -class TestMemberDataTool(base.TestCase): - def afterSetUp(self): +class TestMemberDataTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.memberdata = self.portal.portal_memberdata self.membership = self.portal.portal_membership self.membership.memberareaCreationFlag = 0 diff --git a/src/Products/PlonePAS/tests/test_membershiptool.py b/src/Products/PlonePAS/tests/test_membershiptool.py index 5f1ab79f..42d989c8 100644 --- a/src/Products/PlonePAS/tests/test_membershiptool.py +++ b/src/Products/PlonePAS/tests/test_membershiptool.py @@ -11,25 +11,34 @@ from plone.app.testing import TEST_USER_ID from plone.app.testing import TEST_USER_NAME from plone.app.testing import TEST_USER_PASSWORD +from plone.app.testing import login +from plone.app.testing import logout +from plone.app.testing import setRoles from Products.CMFCore.utils import getToolByName from Products.PlonePAS.browser.member import PASMemberView from Products.PlonePAS.interfaces.membership import IMembershipTool from Products.PlonePAS.plugins.ufactory import PloneUser -from Products.PlonePAS.tests import base +from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING from Products.PlonePAS.tests import dummy from Products.PlonePAS.tools.memberdata import MemberData from Products.PlonePAS.tools.membership import MembershipTool from Products.PlonePAS.utils import getGroupsForPrincipal -import six -from six import StringIO +from six import BytesIO from zExceptions import BadRequest +from plone.app.testing import TEST_USER_ID + import os +import six +import unittest -class MembershipToolTest(base.TestCase): +class MembershipToolTest(unittest.TestCase): - def afterSetUp(self): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] self.mt = getToolByName(self.portal, 'portal_membership') self.md = getToolByName(self.portal, 'portal_memberdata') @@ -120,12 +129,16 @@ def test_id_clean(self): cleaned = cleanId(u'abc') self.assertEqual(cleaned, 'abc') self.assertTrue(isinstance(cleaned, str)) - self.assertFalse(isinstance(cleaned, six.text_type)) + if six.PY2: + self.assertFalse(isinstance(cleaned, six.text_type)) + +class MemberAreaTest(unittest.TestCase): -class MemberAreaTest(base.TestCase): + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.mt = getToolByName(self.portal, 'portal_membership') self.md = getToolByName(self.portal, 'portal_memberdata') # Enable member-area creation @@ -133,7 +146,7 @@ def afterSetUp(self): # Those are all valid chars in Zope. self.mid = "Member #1 - Houston, TX. ($100)" self.pas = self.portal.acl_users - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) def test_funky_member_ids_1(self): mid = self.mid @@ -167,11 +180,15 @@ def test_memberareaCreationFlag_respected(self): self.assertFalse('bar' in self.portal.Members) -class TestMembershipTool(base.TestCase): +class TestMembershipTool(unittest.TestCase): + + layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING - def afterSetUp(self): + def setUp(self): + self.portal = self.layer['portal'] self.membership = self.portal.portal_membership self.groups = self.portal.portal_groups + self.folder = self.portal['folder'] def test_interface(self): from zope.interface.verify import verifyClass @@ -232,7 +249,7 @@ def testChangeOwnMemberPortraitWithEmailUsers(self): {'email': 'member2@host.com', 'title': 'Member #2'} ) - self.login(member_id) + login(self.portal, member_id) image = self.makeRealImage() safe_member_id = self.membership._getSafeMemberId(member_id) @@ -247,6 +264,7 @@ def testChangeOwnMemberPortraitWithEmailUsers(self): def testCannotChangeOtherMemberPortrait(self): # A normal member should not be able to change the portrait of # another member. + setRoles(self.portal, TEST_USER_ID, ['Member']) image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) self.assertRaises(Unauthorized, self.membership.changeMemberPortrait, @@ -257,7 +275,7 @@ def testChangeMemberPortraitAsManager(self): # member. image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) # This should not raise Unauthorized: self.membership.changeMemberPortrait(image, 'joe') self.assertEqual(self.membership.getPersonalPortrait('joe').getId(), @@ -282,9 +300,9 @@ def testCannotDeleteOtherPersonalPortrait(self): # another member. image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.membership.changeMemberPortrait(image, 'joe') - self.setRoles(['Member']) + setRoles(self.portal, TEST_USER_ID, ['Member']) self.assertRaises(Unauthorized, self.membership.deletePersonalPortrait, 'joe') @@ -293,7 +311,7 @@ def testDeleteOtherPersonalPortraitAsManager(self): # member. image = self.makeRealImage() self.membership.addMember('joe', 'secret', ['Member'], []) - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.membership.changeMemberPortrait(image, 'joe') self.membership.deletePersonalPortrait('joe') self.assertEqual( @@ -318,7 +336,7 @@ def testPortraitForNonStandardUserId(self): safe_id = self.membership._getSafeMemberId(user_id) self.assertEqual(safe_id, 'bob--jones-2Btest-40example.org') self.membership.addMember(user_id, 'secret', ['Member'], []) - self.login(user_id) + login(self.portal, user_id) # Should return the default portrait self.assertEqual( @@ -333,7 +351,7 @@ def testPortraitForNonStandardUserId(self): 'Image') # Other users should be able to see your portrait. - self.login(TEST_USER_NAME) + login(self.portal, TEST_USER_NAME) self.assertEqual( self.membership.getPersonalPortrait(user_id).getId(), safe_id) @@ -342,7 +360,7 @@ def testPortraitForNonStandardUserId(self): 'Image') # You can delete your own portrait. - self.login(user_id) + login(self.portal, user_id) self.membership.deletePersonalPortrait(user_id) self.assertEqual( self.membership.getPersonalPortrait(user_id).getId(), @@ -351,7 +369,7 @@ def testPortraitForNonStandardUserId(self): # Managers should be able to change the portrait of another # member and delete it. manager_image = self.makeRealImage() - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) # This should not raise Unauthorized: self.membership.changeMemberPortrait(manager_image, user_id) self.assertEqual(self.membership.getPersonalPortrait(user_id).getId(), @@ -406,7 +424,7 @@ def testSetPassword(self): def testSetPasswordIfAnonymous(self): # Anonymous should not be able to change password - self.logout() + logout() try: self.membership.setPassword('geheim') except BadRequest: @@ -424,9 +442,9 @@ def testSetPasswordAndKeepGroups(self): groups = self.groups groups.addGroup(group2, None, [], []) group = groups.getGroupById(group2) - self.loginAsPortalOwner() + setRoles(self.portal, TEST_USER_ID, ['Manager']) group.addMember(TEST_USER_ID) - self.login(TEST_USER_NAME) # Back to normal + login(self.portal, TEST_USER_NAME) # Back to normal ugroups = self.portal.acl_users.getUserById(TEST_USER_ID).getGroups() self.membership.setPassword('geheim') t_groups = self.portal.acl_users.getUserById(TEST_USER_ID).getGroups() @@ -460,20 +478,20 @@ def testGetAuthenticatedMemberIsWrapped(self): 'PluggableAuthService') def testGetAuthenticatedMemberIfAnonymous(self): - self.logout() + logout() member = self.membership.getAuthenticatedMember() self.assertEqual(member.getUserName(), 'Anonymous User') def testAnonymousMemberIsNotWrapped(self): # Also see http://dev.plone.org/plone/ticket/1851 - self.logout() + logout() member = self.membership.getAuthenticatedMember() self.assertNotEqual(member.__class__.__name__, 'MemberData') self.assertEqual(member.__class__.__name__, 'SpecialUser') def testIsAnonymousUser(self): self.assertFalse(self.membership.isAnonymousUser()) - self.logout() + logout() self.assertTrue(self.membership.isAnonymousUser()) def testWrapUserWrapsBareUser(self): @@ -513,14 +531,14 @@ def testWrapUserWrapsAnonymous(self): def testGetCandidateLocalRoles(self): self.assertEqual(self.membership.getCandidateLocalRoles(self.folder), ('Owner',)) - self.setRoles(['Member', 'Reviewer']) + setRoles(self.portal, TEST_USER_ID, ['Member', 'Reviewer']) self.assertEqual(self.membership.getCandidateLocalRoles(self.folder), ('Owner', 'Reviewer')) def testSetLocalRoles(self): self.assertTrue( 'Owner' in self.folder.get_local_roles_for_userid(TEST_USER_ID)) - self.setRoles(['Member', 'Reviewer']) + setRoles(self.portal, TEST_USER_ID, ['Member', 'Reviewer']) self.membership.setLocalRoles(self.folder, [TEST_USER_ID, 'user2'], 'Reviewer') self.assertEqual(self.folder.get_local_roles_for_userid(TEST_USER_ID), @@ -529,7 +547,7 @@ def testSetLocalRoles(self): ('Reviewer',)) def testDeleteLocalRoles(self): - self.setRoles(['Member', 'Reviewer']) + setRoles(self.portal, TEST_USER_ID, ['Member', 'Reviewer']) self.membership.setLocalRoles(self.folder, ['user2'], 'Reviewer') self.assertEqual(self.folder.get_local_roles_for_userid('user2'), ('Reviewer',)) @@ -630,7 +648,7 @@ def testGetCandidateLocalRolesForAssigned(self): def test_bug4333_delete_user_remove_memberdata(self): # delete user should delete portal_memberdata memberdata = self.portal.portal_memberdata - self.setRoles(['Manager']) + setRoles(self.portal, TEST_USER_ID, ['Manager']) self.addMember('barney', 'Barney Rubble', 'barney@bedrock.com', ['Member'], '2002-01-01') barney = self.membership.getMemberById('barney') @@ -655,7 +673,7 @@ def test_bug4333_delete_user_remove_memberdata(self): def testBogusMemberPortrait(self): # Should change the portrait image - bad_file = dummy.File(data='