Commit 5fc71985 authored by Boxiang Sun's avatar Boxiang Sun

apply 3.0.12 implementation with some Pyston change

parent 97bc7e89
Changelog
=========
2.13.14 (2015-12-21)
--------------------
For changes before verison 3.0, see ``HISTORY.txt``.
3.0.12 (2015-12-21)
-------------------
- Avoid acquiring ``access`` from module wrapped by
``SecurityInfo._ModuleSecurityInfo``. See:
https://github.com/zopefoundation/AccessControl/issues/12
2.13.13 (2013-07-16)
--------------------
- LP #1169923: ensure initialization of shared ``ImplPython`` state
(used by ``ImplC``) when using the "C" security policy. Thanks to
Arnaud Fontaine for the patch.
2.13.12 (2012-10-31)
--------------------
3.0.11 (2014-11-02)
-------------------
- LP #1071067: Use a stronger random number generator and a constant time
comparison function.
- Harden test fix for machines that do not define `localhost`.
2.13.11 (2012-10-21)
--------------------
3.0.10 (2014-11-02)
-------------------
- LP #966101: Recognize special ``zope2.Private`` permission in ZCML
role directive.
- Test fix for machines that do not define `localhost`.
2.13.10 (2012-09-09)
--------------------
3.0.9 (2014-08-08)
------------------
- LP #1047318: Tighten import restrictions for restricted code.
- GitHub #6: Do not pass SecurityInfo instance itself to declarePublic/declarePrivate
when using the public/private decorator. This fixes ``Conflicting security declarations``
warnings on Zope startup.
2.13.9 (2012-08-23)
-------------------
- LP #1248529: Leave existing security manager in place inside
``RoleManager.manage_getUserRolesAndPermissions``.
- Fix a bug in ZopeSecurityPolicy.py. Global variable ``rolesForPermissionOn``
could be overridden if ``__role__`` had custom ``rolesForPermissionOn``.
3.0.8 (2013-07-16)
------------------
2.13.8 (2012-06-22)
-------------------
- LP #1169923: ensure initialization of shared ``ImplPython`` state
(used by ``ImplC``) when using the "C" security policy. Thanks to
Arnaud Fontaine for the patch.
- Add Anonymous as a default role for Public permission.
3.0.7 (2013-05-14)
------------------
2.13.7 (2011-12-12)
-------------------
- Remove long-deprecated 'Shared' roles support (pre-dates Zope, never
used by Zope itself)
- Exclude compiled ``.so`` and ``.dll`` files from source distributions.
- Prevent infinite loop when looking up local roles in an acquisition chain
with cycles.
2.13.6 (2011-12-12)
-------------------
3.0.6 (2012-10-31)
------------------
- Added ``manifest.in`` to ensure the inclusion of the ``include`` directory
into the release.
- LP #1071067: Use a stronger random number generator and a constant time
comparison function.
2.13.5 (2011-12-12)
-------------------
3.0.5 (2012-10-21)
------------------
- Apply changes made available in ``Products.Zope_Hotfix_20111024`` and make
them more robust.
- LP #966101: Recognize special `zope2.Private` permission in ZCML
role directive.
2.13.4 (2011-01-11)
-------------------
3.0.4 (2012-09-09)
------------------
- Return the created user in ``_doAddUser``.
- LP #1047318: Tighten import restrictions for restricted code.
- Added ``IUser`` interface.
3.0.3 (2012-08-23)
------------------
- LP #659968: Added support for ``level`` argument to the ``__import__``
function as introduced in Python 2.5. Currently only ``level = -1`` is
supported.
- Fix a bug in ZopeSecurityPolicy.py. Global variable `rolesForPermissionOn`
could be overridden if `__role__` had custom rolesForPermissionOn.
2.13.3 (2010-08-28)
-------------------
3.0.2 (2012-06-22)
------------------
- Added a ``role`` subdirective for the ``permission`` ZCML directive. If any
roles are specified, they will override the default set of default roles
(Manager).
- Add Anonymous as a default role for Public permission.
2.13.2 (2010-07-16)
-------------------
3.0.1 (2012-05-24)
------------------
- Added ``override_existing_protection`` parameter to the protectName helper.
- Fix tests under Python 2.6.
2.13.1 (2010-06-19)
-------------------
3.0 (2012-05-12)
----------------
- Restore security declarations for deprecated ``sets`` module.
- Added decorators for public, private and protected security declarations.
2.13.0 (2010-06-19)
-------------------
- Update tests to take advantage of automatic test suite discovery.
- Released as separate package.
Pre 3.0 Changelog
=================
2.13.12 (2012-10-31)
--------------------
- LP #1071067: Use a stronger random number generator and a constant time
comparison function.
2.13.11 (2012-10-21)
--------------------
- LP #966101: Recognize special `zope2.Private` permission in ZCML
role directive.
2.13.10 (2012-09-09)
--------------------
- LP #1047318: Tighten import restrictions for restricted code.
2.13.9 (2012-08-23)
-------------------
- Fix a bug in ZopeSecurityPolicy.py. Global variable `rolesForPermissionOn`
could be overridden if `__role__` had custom rolesForPermissionOn.
2.13.8 (2012-06-22)
-------------------
- Add Anonymous as a default role for Public permission.
2.13.7 (2011-12-12)
-------------------
- Exclude compiled `.so` and `.dll` files from source distributions.
2.13.6 (2011-12-12)
-------------------
- Added `manifest.in` to ensure the inclusion of the `include` directory into
the release.
2.13.5 (2011-12-12)
-------------------
- Apply changes made available in `Products.Zope_Hotfix_20111024` and make them
more robust.
2.13.4 (2011-01-11)
-------------------
- Return the created user in _doAddUser.
- Added IUser interface.
- LP #659968: Added support for level argument to the ``__import__`` function
as introduced in Python 2.5. Currently only level=-1 is supported.
2.13.3 (2010-08-28)
-------------------
- Added a ``role`` subdirective for the ``permission`` ZCML directive. If any
roles are specified, they will override the default set of default roles
(Manager).
2.13.2 (2010-07-16)
-------------------
- Added ``override_existing_protection`` parameter to the protectName helper.
2.13.1 (2010-06-19)
-------------------
- Restore security declarations for deprecated ``sets`` module.
2.13.0 (2010-06-19)
-------------------
- Released as separate package.
include *.txt
include *.rst
recursive-include include *
recursive-include src/AccessControl *
......
......@@ -18,75 +18,14 @@ The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os, shutil, sys, tempfile, urllib, urllib2, subprocess
import os
import shutil
import sys
import tempfile
from optparse import OptionParser
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
quote = str
# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
stdout, stderr = subprocess.Popen(
[sys.executable, '-Sc',
'try:\n'
' import ConfigParser\n'
'except ImportError:\n'
' print 1\n'
'else:\n'
' print 0\n'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
has_broken_dash_S = bool(int(stdout.strip()))
# In order to be more robust in the face of system Pythons, we want to
# run without site-packages loaded. This is somewhat tricky, in
# particular because Python 2.6's distutils imports site, so starting
# with the -S flag is not sufficient. However, we'll start with that:
if not has_broken_dash_S and 'site' in sys.modules:
# We will restart with python -S.
args = sys.argv[:]
args[0:0] = [sys.executable, '-S']
args = map(quote, args)
os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:]
import site # imported because of its side effects
sys.path[:] = clean_path
for k, v in sys.modules.items():
if k in ('setuptools', 'pkg_resources') or (
hasattr(v, '__path__') and
len(v.__path__) == 1 and
not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))):
# This is a namespace package. Remove it.
sys.modules.pop(k)
is_jython = sys.platform.startswith('java')
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
distribute_source = 'http://python-distribute.org/distribute_setup.py'
# parsing arguments
def normalize_to_url(option, opt_str, value, parser):
if value:
if '://' not in value: # It doesn't smell like a URL.
value = 'file://%s' % (
urllib.pathname2url(
os.path.abspath(os.path.expanduser(value))),)
if opt_str == '--download-base' and not value.endswith('/'):
# Download base needs a trailing slash to make the world happy.
value += '/'
else:
value = None
name = opt_str[2:].replace('-', '_')
setattr(parser.values, name, value)
tmpeggs = tempfile.mkdtemp()
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
......@@ -96,31 +35,13 @@ Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --setup-source and --download-base to point to
local resources, you can keep this script from going over the network.
Note that by using --find-links to point to local resources, you can keep
this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="use_distribute", default=False,
help="Use Distribute rather than Setuptools.")
parser.add_option("--setup-source", action="callback", dest="setup_source",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or file location for the setup file. "
"If you use Setuptools, this will default to " +
setuptools_source + "; if you use Distribute, this "
"will default to " + distribute_source + "."))
parser.add_option("--download-base", action="callback", dest="download_base",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or directory for downloading "
"zc.buildout and either Setuptools or Distribute. "
"Defaults to PyPI."))
parser.add_option("--eggs",
help=("Specify a directory for storing eggs. Defaults to "
"a temporary directory that is deleted when the "
"bootstrap script completes."))
parser.add_option("-v", "--version", help="use a specific zc.buildout version")
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
......@@ -130,80 +51,80 @@ parser.add_option("-t", "--accept-buildout-test-releases",
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", None, action="store", dest="config_file",
help=("Specify the path to the buildout configuration "
"file to be used."))
options, args = parser.parse_args()
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
parser.add_option("--allow-site-packages",
action="store_true", default=False,
help=("Let bootstrap.py use existing site packages"))
parser.add_option("--setuptools-version",
help="use a specific setuptools version")
if options.eggs:
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
else:
eggs_dir = tempfile.mkdtemp()
if options.setup_source is None:
if options.use_distribute:
options.setup_source = distribute_source
else:
options.setup_source = setuptools_source
options, args = parser.parse_args()
if options.accept_buildout_test_releases:
args.insert(0, 'buildout:accept-buildout-test-releases=true')
######################################################################
# load/install setuptools
try:
import pkg_resources
import setuptools # A flag. Sometimes pkg_resources is installed alone.
if not hasattr(pkg_resources, '_distribute'):
raise ImportError
if options.allow_site_packages:
import setuptools
import pkg_resources
from urllib.request import urlopen
except ImportError:
ez_code = urllib2.urlopen(
options.setup_source).read().replace('\r\n', '\n')
ez = {}
exec ez_code in ez
setup_args = dict(to_dir=eggs_dir, download_delay=0)
if options.download_base:
setup_args['download_base'] = options.download_base
if options.use_distribute:
setup_args['no_fake'] = True
if sys.version_info[:2] == (2, 4):
setup_args['version'] = '0.6.32'
ez['use_setuptools'](**setup_args)
if 'pkg_resources' in sys.modules:
reload(sys.modules['pkg_resources'])
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
cmd = [quote(sys.executable),
'-c',
quote('from setuptools.command.easy_install import main; main()'),
'-mqNxd',
quote(eggs_dir)]
if not has_broken_dash_S:
cmd.insert(1, '-S')
find_links = options.download_base
if not find_links:
find_links = os.environ.get('bootstrap-testing-find-links')
if not find_links and options.accept_buildout_test_releases:
find_links = 'http://downloads.buildout.org/'
if find_links:
cmd.extend(['-f', quote(find_links)])
from urllib2 import urlopen
ez = {}
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages:
# ez_setup imports site, which adds site packages
# this will remove them from the path to ensure that incompatible versions
# of setuptools are not in the path
import site
# inside a virtualenv, there is no 'getsitepackages'.
# We can't remove these reliably
if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages():
sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version
ez['use_setuptools'](**setup_args)
import setuptools
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
######################################################################
# Install buildout
if options.use_distribute:
setup_requirement = 'distribute'
else:
setup_requirement = 'setuptools'
ws = pkg_resources.working_set
setup_requirement_path = ws.find(
pkg_resources.Requirement.parse(setup_requirement)).location
env = dict(
os.environ,
PYTHONPATH=setup_requirement_path)
cmd = [sys.executable, '-c',
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', find_links])
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
requirement = 'zc.buildout'
version = options.version
......@@ -213,12 +134,17 @@ if version is None and not options.accept_buildout_test_releases:
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
try:
return not parsed_version.is_prerelease
except AttributeError:
# Older setuptools
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setup_requirement_path])
search_path=[setuptools_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
......@@ -227,8 +153,6 @@ if version is None and not options.accept_buildout_test_releases:
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if distv >= pkg_resources.parse_version('2dev'):
continue
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
......@@ -238,40 +162,28 @@ if version is None and not options.accept_buildout_test_releases:
if best:
best.sort()
version = best[-1].version
if version:
requirement += '=='+version
else:
requirement += '<2dev'
requirement = '=='.join((requirement, version))
cmd.append(requirement)
if is_jython:
import subprocess
exitcode = subprocess.Popen(cmd, env=env).wait()
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
if exitcode != 0:
sys.stdout.flush()
sys.stderr.flush()
print ("An error occurred when trying to install zc.buildout. "
"Look above this message for any errors that "
"were output by easy_install.")
sys.exit(exitcode)
ws.add_entry(eggs_dir)
import subprocess
if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0:
raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
# If there isn't already a command in the args, add bootstrap
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout's main function
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
if not options.eggs: # clean up temporary egg directory
shutil.rmtree(eggs_dir)
shutil.rmtree(tmpeggs)
[buildout]
develop = .
parts = interpreter test
parts = interpreter test coverage
[interpreter]
recipe = zc.recipe.egg
......@@ -10,3 +10,8 @@ eggs = AccessControl
[test]
recipe = zc.recipe.testrunner
eggs = AccessControl
[coverage]
recipe = zc.recipe.testrunner
eggs = AccessControl
defaults = ['--coverage', '../../coverage', '-v', '--auto-progress']
......@@ -212,7 +212,7 @@ static PyExtensionClass NAME ## Type = { PyObject_HEAD_INIT(NULL) 0, # NAME, \
(PyMethod_Check((M)) ? ((PyMethodObject*)(M))->im_self : NULL)
/* Check whether an object has an __of__ method for returning itself
in the context of it's container. */
in the context of its container. */
#define has__of__(O) (PyObject_TypeCheck((O)->ob_type, ECExtensionClassType) \
&& (O)->ob_type->tp_descr_get != NULL)
......
......@@ -27,6 +27,19 @@ setup(name='AccessControl',
packages=find_packages('src'),
package_dir={'': 'src'},
classifiers=[
"Development Status :: 6 - Mature",
"Environment :: Web Environment",
"Framework :: Zope2",
"License :: OSI Approved :: Zope Public License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2 :: Only",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: Pyston",
],
ext_modules=[Extension(
name='AccessControl.cAccessControl',
include_dirs=['include', 'src'],
......@@ -37,6 +50,8 @@ setup(name='AccessControl',
install_requires=[
'Acquisition',
'DateTime', # optional dependency of RestrictedPython
# Pyston change: Pyston will use pure Python implementation.
# So the version of ExtenstionClass is not important.
'ExtensionClass',
'Persistence',
'Record',
......
......@@ -93,7 +93,8 @@ _policy_names = {
# start with the default, mostly because we need something for the tests
setImplementation("C")
# Pyston change: use Python implementation by default
setImplementation("Python")
# allow the implementation to change from the default
_implementation_set = 0
......@@ -51,16 +51,16 @@ Persistent.__class_init__ = InitializeClass
LOG = getLogger('SecurityInfo')
# Security constants - these are imported into the AccessControl
# namespace and can be referenced as AccessControl.PUBLIC etc.
ACCESS_NONE = _what_not_even_god_should_do
ACCESS_NONE = _what_not_even_god_should_do
ACCESS_PRIVATE = ()
ACCESS_PUBLIC = None
ACCESS_PUBLIC = None
_marker = []
class SecurityInfo(Implicit):
"""Encapsulate security information."""
......@@ -71,6 +71,7 @@ class SecurityInfo(Implicit):
def __init__(self):
self.names = {}
self.roles = {}
self._unused_protected_decorators = set()
def _setaccess(self, names, access):
for name in names:
......@@ -79,37 +80,67 @@ class SecurityInfo(Implicit):
self._warnings = 1
self.names[name] = access
declarePublic__roles__=ACCESS_PRIVATE
declarePublic__roles__ = ACCESS_PRIVATE
def declarePublic(self, name, *names):
"""Declare names to be publicly accessible."""
self._setaccess((name,) + names, ACCESS_PUBLIC)
declarePrivate__roles__=ACCESS_PRIVATE
declarePrivate__roles__ = ACCESS_PRIVATE
def declarePrivate(self, name, *names):
"""Declare names to be inaccessible to restricted code."""
self._setaccess((name,) + names, ACCESS_PRIVATE)
declareProtected__roles__=ACCESS_PRIVATE
declareProtected__roles__ = ACCESS_PRIVATE
def declareProtected(self, permission_name, name, *names):
"""Declare names to be associated with a permission."""
self._setaccess((name,) + names, permission_name)
declareObjectPublic__roles__=ACCESS_PRIVATE
declareObjectPublic__roles__ = ACCESS_PRIVATE
def declareObjectPublic(self):
"""Declare the object to be publicly accessible."""
self._setaccess(('',), ACCESS_PUBLIC)
declareObjectPrivate__roles__=ACCESS_PRIVATE
declareObjectPrivate__roles__ = ACCESS_PRIVATE
def declareObjectPrivate(self):
"""Declare the object to be inaccessible to restricted code."""
self._setaccess(('',), ACCESS_PRIVATE)
declareObjectProtected__roles__=ACCESS_PRIVATE
declareObjectProtected__roles__ = ACCESS_PRIVATE
def declareObjectProtected(self, permission_name):
"""Declare the object to be associated with a permission."""
self._setaccess(('',), permission_name)
setPermissionDefault__roles__=ACCESS_PRIVATE
public__roles__ = ACCESS_PRIVATE
def public(self, func):
"""Decorate a function to be publicly accessible."""
self.declarePublic(func.__name__)
return func
private__roles__ = ACCESS_PRIVATE
def private(self, func):
"""Decorate a function to be inaccessible to restricted code."""
self.declarePrivate(func.__name__)
return func
protected__roles__ = ACCESS_PRIVATE
def protected(self, permission_name):
"""Return a decorator to associate a function with a permission."""
# the decorator returned is remembered in a set and will
# remove itself upon call. self.apply will check for an empty
# set and raise an AssertionError otherwise.
key = "'%s':%s" % (permission_name, id(lambda x: x))
def decor(func):
self.declareProtected(permission_name, func.__name__)
self._unused_protected_decorators.remove(key)
return func
# make sure our key algo creates unique-enough keys
if key in self._unused_protected_decorators:
raise KeyError("Duplicate key: %s" % (key,))
self._unused_protected_decorators.add(key)
return decor
setPermissionDefault__roles__ = ACCESS_PRIVATE
def setPermissionDefault(self, permission_name, roles):
"""Declare default roles for a permission"""
rdict = {}
......@@ -121,7 +152,7 @@ class SecurityInfo(Implicit):
self._warnings = 1
self.roles[permission_name] = rdict
setDefaultAccess__roles__=ACCESS_PRIVATE
setDefaultAccess__roles__ = ACCESS_PRIVATE
def setDefaultAccess(self, access):
"""Declare default attribute access policy.
......@@ -135,7 +166,7 @@ class SecurityInfo(Implicit):
elif access == 'deny':
access = 0
else:
raise ValueError, "'allow' or 'deny' expected"
raise ValueError("'allow' or 'deny' expected")
self.access = access
......@@ -148,13 +179,19 @@ class ClassSecurityInfo(SecurityInfo):
def apply(self, classobj):
"""Apply security information to the given class object."""
dict = classobj.__dict__
# make sure all decorators handed out by security.protected were used
if self._unused_protected_decorators:
msg = "Class '%r' has %d non-decorator security.protected calls!"
raise AssertionError(msg % (classobj,
len(self._unused_protected_decorators)))
cdict = classobj.__dict__
# Check the class for an existing __ac_permissions__ and
# incorporate that if present to support older classes or
# classes that haven't fully switched to using SecurityInfo.
if dict.has_key('__ac_permissions__'):
for item in dict['__ac_permissions__']:
if '__ac_permissions__' in cdict:
for item in cdict['__ac_permissions__']:
permission_name = item[0]
self._setaccess(item[1], permission_name)
if len(item) > 2:
......@@ -167,7 +204,7 @@ class ClassSecurityInfo(SecurityInfo):
if access in (ACCESS_PRIVATE, ACCESS_PUBLIC, ACCESS_NONE):
setattr(classobj, '%s__roles__' % name, access)
else:
if not ac_permissions.has_key(access):
if access not in ac_permissions:
ac_permissions[access] = []
ac_permissions[access].append(name)
......@@ -201,6 +238,7 @@ class ClassSecurityInfo(SecurityInfo):
LOG.warn('Class "%s" had conflicting '
'security declarations' % classobj.__name__)
class ClassSecurityInformation(ClassSecurityInfo):
# Default policy is disallow
access = 0
......@@ -208,6 +246,7 @@ class ClassSecurityInformation(ClassSecurityInfo):
_moduleSecurity = {}
_appliedModuleSecurity = {}
def secureModule(mname, *imp):
modsec = _moduleSecurity.get(mname, None)
if modsec is None:
......@@ -223,6 +262,7 @@ def secureModule(mname, *imp):
_appliedModuleSecurity[mname] = modsec
return module
def ModuleSecurityInfo(module_name=None):
if module_name is not None:
modsec = _moduleSecurity.get(module_name, None)
......@@ -246,10 +286,11 @@ def ModuleSecurityInfo(module_name=None):
# leading to the module
modname = module_name[dot + 1:]
pmodsec = ModuleSecurityInfo(module_name[:dot])
if not pmodsec.names.has_key(modname):
if modname not in pmodsec.names:
pmodsec.declarePublic(modname)
return _ModuleSecurityInfo(module_name)
class _ModuleSecurityInfo(SecurityInfo):
"""Encapsulate security information for modules."""
......@@ -284,23 +325,24 @@ class _ModuleSecurityInfo(SecurityInfo):
LOG.warn('Module "%s" had conflicting '
'security declarations' % dict['__name__'])
declareProtected__roles__=ACCESS_PRIVATE
declareProtected__roles__ = ACCESS_PRIVATE
def declareProtected(self, permission_name, *names):
"""Cannot declare module names protected."""
pass
declareObjectProtected__roles__=ACCESS_PRIVATE
declareObjectProtected__roles__ = ACCESS_PRIVATE
def declareObjectProtected(self, permission_name):
"""Cannot declare module protected."""
pass
setDefaultRoles__roles__=ACCESS_PRIVATE
setDefaultRoles__roles__ = ACCESS_PRIVATE
def setDefaultRoles(self, permission_name, roles):
"""Cannot set default roles for permissions in a module."""
pass
# Handy little utility functions
def allow_module(module_name):
"""Allow a module and all its contents to be used from a
restricted Script. The argument module_name may be a simple
......@@ -312,6 +354,7 @@ def allow_module(module_name):
ModuleSecurityInfo(module_name[:dot]).setDefaultAccess(1)
dot = module_name.find('.', dot + 1)
def allow_class(Class):
"""Allow a class and all of its methods to be used from a
restricted Script. The argument Class must be a class."""
......
......@@ -13,7 +13,7 @@
"""Place to find special users
This is needed to avoid a circular import problem. The 'real' values
are stored here by the AccessControl.User module as part of it's
are stored here by the AccessControl.User module as part of its
initialization.
"""
......
......@@ -894,7 +894,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) {
/*| # We have an object without roles and we didn't get
**| # a list of roles passed in. Presumably, the value
**| # is some simple object like a string or a list.
**| # We'll try to get roles from it's container
**| # We'll try to get roles from its container
**|
**| if container is None: raise Unauthorized(name, value)
*/
......
......@@ -158,7 +158,6 @@ class RoleManager(Base, RoleManager):
else:
current = current.__parent__
newSecurityManager(None, userObj) # necessary?
userObj = userObj.__of__(uf)
d = {'user_defined_in': '/' + uf.absolute_url(1)}
......
......@@ -10,24 +10,39 @@
# FOR A PARTICULAR PURPOSE
#
##############################################################################
""" Unit tests for ClassSecurityInfo.
"""
import unittest
class ClassSecurityInfoTests(unittest.TestCase):
def _getTargetClass(self):
from AccessControl.SecurityInfo import ClassSecurityInfo
return ClassSecurityInfo
def test_SetPermissionDefault(self):
def assertRaises(self, excClass, callableObj, *args, **kwargs):
"""Fail unless an exception of class excClass is thrown
by callableObj when invoked with arguments args and keyword
arguments kwargs. If a different type of exception is
thrown, it will not be caught, and the test case will be
deemed to have suffered an error, exactly as for an
unexpected exception.
Return the raised exception object, if it matches the expected type.
"""
try:
callableObj(*args, **kwargs)
except excClass as e:
return e
else:
if getattr(excClass,'__name__', None) is not None:
excName = excClass.__name__
else:
excName = str(excClass)
raise self.failureException("%s not raised" % excName)
def test_SetPermissionDefault(self):
# Test setting default roles for permissions.
from AccessControl.class_init import InitializeClass
from ExtensionClass import Base
......@@ -38,22 +53,39 @@ class ClassSecurityInfoTests(unittest.TestCase):
"""Test class
"""
__ac_roles__ = ('Role A', 'Role B', 'Role C')
meta_type = "Test"
security = ClassSecurityInfo()
security.setPermissionDefault('Make food', ('Chef',))
security.setPermissionDefault(
'Test permission',
('Manager', 'Role A', 'Role B', 'Role C')
)
security.declareProtected('Test permission', 'foo')
def foo(self, REQUEST=None):
security.declarePublic('public')
def public(self, REQUEST=None):
""" """
security.declarePrivate('private')
def private(self, REQUEST=None):
""" """
security.declareProtected('Test permission', 'protected')
def protected(self, REQUEST=None):
""" """
# same with decorators
@security.public
def public_new(self, REQUEST=None):
""" """
@security.private
def private_new(self, REQUEST=None):
""" """
@security.protected('Test permission')
def protected_new(self, REQUEST=None):
""" """
pass
# Do class initialization.
InitializeClass(Test)
......@@ -62,7 +94,24 @@ class ClassSecurityInfoTests(unittest.TestCase):
# correctly. Note that this uses carnal knowledge of the internal
# structures used to store this information!
object = Test()
imPermissionRole = [r for r in object.foo__roles__
self.assertEqual(object.public__roles__, None)
self.assertEqual(object.private__roles__, ())
imPermissionRole = [r for r in object.protected__roles__
if not r.endswith('_Permission')]
self.failUnless(len(imPermissionRole) == 4)
for item in ('Manager', 'Role A', 'Role B', 'Role C'):
self.failUnless(item in imPermissionRole)
# functions exist, i.e. decorators returned them
self.assertEqual(object.public_new.__name__, 'public_new')
self.assertEqual(object.private_new.__name__, 'private_new')
self.assertEqual(object.protected_new.__name__, 'protected_new')
# roles for functions have been set via decorators
self.assertEqual(object.public_new__roles__, None)
self.assertEqual(object.private_new__roles__, ())
imPermissionRole = [r for r in object.protected_new__roles__
if not r.endswith('_Permission')]
self.failUnless(len(imPermissionRole) == 4)
......@@ -74,11 +123,61 @@ class ClassSecurityInfoTests(unittest.TestCase):
self.assertEquals([t for t in Test.__ac_permissions__ if not t[1]],
[('Make food', (), ('Chef',))])
def test_EnsureProtectedDecoCall(self):
from AccessControl.class_init import InitializeClass
from ExtensionClass import Base
ClassSecurityInfo = self._getTargetClass()
class Test(Base):
"""Test class
"""
meta_type = "Test"
security = ClassSecurityInfo()
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ClassSecurityInfoTests))
return suite
security.protected('Test permission 1')
def unprotected1(self, REQUEST=None):
""" """
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
security.protected('Test permission 2')
def unprotected2(self, REQUEST=None):
""" """
@security.protected('Test permission 3')
def protected(self, REQUEST=None):
""" """
# Do class initialization.
exc = self.assertRaises(AssertionError,
InitializeClass, Test)
self.assertTrue('has 2 non-decorator' in str(exc))
def test_aq_context_in_decorators(self):
from Acquisition import Implicit
info = self._getTargetClass()
class A(Implicit):
security = info()
a = 1
@security.public
def public(self):
return self.a
@security.private
def private(self):
# make sure the acquisition context is still intact
return self.b
class B(Implicit):
security = info()
b = 2
a = A()
b = B()
a = a.__of__(b)
self.assertEqual(a.b, 2)
self.assertEqual(a.public(), 1)
self.assertEqual(a.private(), 2)
......@@ -62,6 +62,3 @@ class AccessControlImplementationTest(unittest.TestCase):
def test_suite():
return unittest.makeSuite(AccessControlImplementationTest)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
......@@ -84,7 +84,3 @@ class ModuleSecurityTests(unittest.TestCase):
def test_level_nondefault(self):
self.assertUnauth('AccessControl.tests.public_module', (), level=1)
def test_suite():
return unittest.makeSuite(ModuleSecurityTests)
......@@ -290,10 +290,3 @@ class OwnershipChangeTests(unittest.TestCase):
self.assertEquals( self.root.parent.child.grandchild._owner
, previous_grandchild_owner
)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(OwnedTests),
unittest.makeSuite(OwnershipChangeTests),
))
......@@ -78,15 +78,3 @@ class PasswordDigestTests (unittest.TestCase):
# Sanity check
pw = 'my-password'
assert AuthEncoding.pw_validate(pw, pw)
def test_suite():
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite( PasswordDigestTests ) )
return suite
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
main()
......@@ -9,9 +9,3 @@ class TestRoleManager(unittest.TestCase):
from zope.interface.verify import verifyClass
verifyClass(IPermissionMappingSupport, RoleManager)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(TestRoleManager),
))
......@@ -114,14 +114,3 @@ class PermissionRoleTests (unittest.TestCase):
self.failUnless(getattr(a, '_d') == ('Manager',))
self.failUnless(getattr(a, '__name__') == 'a')
self.failUnless(getattr(a, '_p') == '_a_Permission')
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(PermissionRoleTests))
return suite
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
main()
import unittest
def _makeRootAndUser():
from AccessControl.rolemanager import RoleManager
from Acquisition import Implicit, Explicit
class DummyContext(Implicit, RoleManager):
__roles__ = ('Manager',)
class DummyUser(Explicit):
def getRoles(self):
return ('Manager',)
def getRolesInContext(self, context):
return ('Manager',)
def has_permission(self, permission, context):
return True
class DummyAclUsers(Explicit):
def getUser(self, user_id):
user = DummyUser()
return user.__of__(self)
def absolute_url(self, relative=0):
return 'acl_users'
class DummyRoot(Explicit):
acl_users = DummyAclUsers()
root = DummyRoot()
root.acl_users = DummyAclUsers()
root.context1 = DummyContext()
root.context2 = DummyContext()
user = DummyUser().__of__(root.acl_users)
return root, user
class TestRoleManager(unittest.TestCase):
def tearDown(self):
from AccessControl.SecurityManagement import noSecurityManager
noSecurityManager()
def test_interfaces(self):
from AccessControl.interfaces import IRoleManager
from AccessControl.rolemanager import RoleManager
......@@ -10,8 +55,12 @@ class TestRoleManager(unittest.TestCase):
verifyClass(IRoleManager, RoleManager)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(TestRoleManager),
))
def test_manage_getUserRolesAndPermissions(self):
from AccessControl.ImplPython import verifyAcquisitionContext
from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.SecurityManagement import newSecurityManager
root, user = _makeRootAndUser()
newSecurityManager(None, user)
root.context1.manage_getUserRolesAndPermissions('dummy_user')
user = getSecurityManager().getUser()
self.assertTrue(verifyAcquisitionContext(user, root.context2, ()))
......@@ -262,10 +262,6 @@ class C_SecurityManagerTests(SecurityManagerTestBase,
def test_suite():
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite( PythonSecurityManagerTests ) )
suite.addTest( unittest.makeSuite( C_SecurityManagerTests ) )
suite.addTest(unittest.makeSuite(PythonSecurityManagerTests))
suite.addTest(unittest.makeSuite(C_SecurityManagerTests))
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
......@@ -438,6 +438,7 @@ def test_register_permission_with_non_default_roles():
>>> tearDown()
"""
def test_suite():
import doctest
return doctest.DocTestSuite(optionflags=doctest.ELLIPSIS)
......@@ -857,9 +857,9 @@ protected_inplacevar allows inplce ops on sets:
[2, 7, 8, 9]
>>> sorted(s)
[2, 7, 8, 9]
"""
def test_suite():
suite = unittest.TestSuite([
doctest.DocTestSuite(),
......@@ -874,7 +874,3 @@ def test_suite():
):
suite.addTest(unittest.makeSuite(cls))
return suite
if __name__ == '__main__':
unittest.main()
......@@ -11,6 +11,7 @@
#
##############################################################################
from doctest import DocTestSuite
import sys
import thread
import unittest
......@@ -635,10 +636,8 @@ def test_zsp_gets_right_roles_for_methods():
>>> c.__allow_access_to_unprotected_subobjects__ = 1
>>> bool(zsp.validate(c, c, 'bar', c.bar, Context(User(['spam']))))
True
"""
from doctest import DocTestSuite
class GetRolesWithMultiThreadTest(unittest.TestCase):
......
......@@ -14,18 +14,16 @@
from zope.interface import implements
from zope.publisher.interfaces.browser import IBrowserRequest
class DummyRequest:
implements(IBrowserRequest)
def __init__(self, method):
self.method = method
def test_suite():
from doctest import DocFileSuite
return DocFileSuite('../requestmethod.txt',
globs=dict(GET=DummyRequest('GET'),
POST=DummyRequest('POST')))
if __name__ == '__main__':
import unittest
unittest.main(defaultTest='test_suite')
......@@ -60,7 +60,3 @@ class SafeIterTestCase(unittest.TestCase):
self.assertEqual(self.checks, [(contid, 1),
(contid, 2),
(contid, 3)])
def test_suite():
return unittest.makeSuite(SafeIterTestCase)
......@@ -151,9 +151,3 @@ class TestTaintedString(unittest.TestCase):
def testQuoted(self):
self.assertEquals(self.tainted.quoted(), self.quoted)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestTaintedString))
return suite
......@@ -168,9 +168,3 @@ class UserFolderTests(unittest.TestCase):
self.assertEqual(user.__, ENCRYPTED)
self.failUnless(uf._isPasswordEncrypted(user.__))
self.failUnless(pw_validate(user.__, PASSWORD))
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(UserFolderTests))
return suite
......@@ -54,11 +54,363 @@ class BasicUserTests(unittest.TestCase):
self.assertRaises(NotImplementedError, derived.getRoles)
self.assertRaises(NotImplementedError, derived.getDomains)
# TODO: def test_getRolesInContext (w/wo local, callable, aq)
# TODO: def test_authenticate (w/wo domains)
# TODO: def test_allowed (...)
# TODO: def test_has_role (w/wo str, context)
# TODO: def test_has_permission (w/wo str)
def test_getRolesInContext_no_aq_no_local_roles(self):
derived = self._makeDerived()
derived.getId = lambda *x: 'user'
derived.getRoles = lambda *x: ['Manager']
self.assertEqual(derived.getRolesInContext(self), ['Manager'])
def test_getRolesInContext_no_aq_w_local_roles_as_dict(self):
class Target(object):
__ac_local_roles__ = {'user': ['Other']}
derived = self._makeDerived()
derived.getId = lambda *x: 'user'
derived.getRoles = lambda *x: ['Manager']
self.assertEqual(derived.getRolesInContext(Target()),
['Manager', 'Other'])
def test_getRolesInContext_no_aq_w_local_roles_as_callable(self):
class Context(object):
def __ac_local_roles__(self):
return {'user': ['Other']}
derived = self._makeDerived()
derived.getId = lambda *x: 'user'
derived.getRoles = lambda *x: ['Manager']
self.assertEqual(derived.getRolesInContext(Context()),
['Manager', 'Other'])
def test_getRolesInContext_w_aq(self):
class Context(object):
pass
derived = self._makeDerived()
derived.getId = lambda *x: 'user'
derived.getRoles = lambda *x: ['Manager']
parent = Context()
parent.__ac_local_roles__ = {'user': ['Another']}
target = Context()
target.__ac_local_roles__ = {'user': ['Other']}
target.__parent__ = parent
self.assertEqual(derived.getRolesInContext(target),
['Manager', 'Other', 'Another'])
def test_getRolesInContext_w_method(self):
class Context(object):
__ac_local_roles__ = {'user': ['Other']}
def method(self):
pass
derived = self._makeDerived()
derived.getId = lambda *x: 'user'
derived.getRoles = lambda *x: ['Manager']
target = Context()
self.assertEqual(derived.getRolesInContext(target.method),
['Manager', 'Other'])
def test_authenticate_miss_wo_domains(self):
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ()
self.assertFalse(derived.authenticate('notpassword', {}))
def test_authenticate_hit_wo_domains(self):
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ()
self.assertTrue(derived.authenticate('password', {}))
def test_authenticate_hit_w_domains_any(self):
class Request(dict):
def getClientAddr(self):
return '192.168.1.1'
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('*',)
request = Request(REMOTE_HOST='example.com')
self.assertTrue(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_both(self):
class Request(dict):
def getClientAddr(self):
return '192.168.1.1'
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('127.0.0.1',)
request = Request(REMOTE_HOST='example.com')
self.assertFalse(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_wo_host_wo_addr(self):
class Request(dict):
def getClientAddr(self):
return ''
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('127.0.0.1',)
request = Request(REMOTE_HOST='')
self.assertFalse(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_host_hit_addr(self):
class Request(dict):
def getClientAddr(self):
return '127.0.0.1'
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('127.0.0.1',)
request = Request(REMOTE_HOST='example.com')
self.assertTrue(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_host_hit_addr_wo_host(self):
class Request(dict):
def getClientAddr(self):
return '127.0.0.1'
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('127.0.0.1',)
request = Request(REMOTE_HOST='')
self.assertTrue(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_host_hit_addr_wo_addr(self):
class Request(dict):
def getClientAddr(self):
return ''
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('127.0.0.1',)
request = Request(REMOTE_HOST='localhost')
self.assertTrue(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_addr_hit_host(self):
class Request(dict):
def getClientAddr(self):
return '192.168.1.1'
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('example.com',)
request = Request(REMOTE_HOST='host.example.com')
self.assertTrue(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_addr_hit_host_wo_addr(self):
class Request(dict):
def getClientAddr(self):
return ''
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('example.com',)
request = Request(REMOTE_HOST='host.example.com')
self.assertTrue(derived.authenticate('password', request))
def test_authenticate_hit_w_domains_miss_addr_hit_host_wo_host(self):
class Request(dict):
def getClientAddr(self):
return '127.0.0.1'
derived = self._makeDerived()
derived._getPassword = lambda *x: 'password'
derived.getDomains = lambda *x: ('localhost',)
request = Request(REMOTE_HOST='localhost')
self.assertTrue(derived.authenticate('password', request))
def test_allowed__what_not_even_god_should_do(self):
from AccessControl.PermissionRole import _what_not_even_god_should_do
derived = self._makeDerived()
self.assertFalse(derived.allowed(self, _what_not_even_god_should_do))
def test_allowed_w_roles_is_None(self):
derived = self._makeDerived()
self.assertTrue(derived.allowed(self, None))
def test_allowed_w_Anonymous_in_roles(self):
derived = self._makeDerived()
self.assertTrue(derived.allowed(self, ['Anonymous']))
def test_allowed_w_Authenticated_in_roles_w_Anonymous(self):
derived = self._makeDerived()
derived.getUserName = lambda *x: 'Anonymous User'
derived.getRoles = lambda *x: ['Anonymous']
self.assertFalse(derived.allowed(self, ['Authenticated']))
def test_allowed_w_Authenticated_in_roles_not_Anonymous(self):
derived = self._makeDerived()
derived.getUserName = lambda *x: 'user'
self.assertTrue(derived.allowed(self, ['Authenticated']))
def test_allowed_w_Authenticated_in_roles_not_Anonymous_context_miss(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: []
self.assertFalse(derived.allowed(self, ['Authenticated']))
def test_allowed_w_Authenticated_in_roles_not_Anonymous_context_hit(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: []
self.assertTrue(derived.allowed(folder, ['Authenticated']))
# TODO: def test_allowed_w_Shared_in_roles XXX rip that out instead
def test_allowed_w_global_roles_hit_context_miss(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: ['Editor']
self.assertFalse(derived.allowed(self, ['Editor']))
def test_allowed_w_global_roles_hit_context_hit(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: ['Editor']
self.assertTrue(derived.allowed(folder, ['Editor']))
def test_allowed_w_global_roles_miss_wo_local_roles_wo_aq(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: ['Author']
self.assertFalse(derived.allowed(self, ['Editor']))
def test_allowed_w_global_roles_miss_w_local_roles_miss_wo_aq(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
class Folder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
other = Folder() # no aq
other.__ac_local_roles__ = {'user': ['Editor']}
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: ['Author']
self.assertFalse(derived.allowed(other, ['Reviewer']))
def test_allowed_w_global_roles_miss_w_local_roles_hit_wo_aq(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
class Folder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
other = Folder() # no aq
other.__ac_local_roles__ = {'user': ['Editor']}
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: ['Author']
self.assertFalse(derived.allowed(other, ['Editor']))
def test_allowed_w_global_roles_miss_w_local_roles_hit_w_aq(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
class Folder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
other = Folder().__of__(root)
other.__ac_local_roles__ = {'user': ['Editor']}
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: ['Author']
self.assertTrue(derived.allowed(other, ['Editor']))
def test_has_role_w_str_wo_context_miss(self):
derived = self._makeDerived()
derived.getRoles = lambda *x: ['Author']
self.assertFalse(derived.has_role('Editor'))
def test_has_role_w_list_wo_context_hit(self):
derived = self._makeDerived()
derived.getRoles = lambda *x: ['Author']
self.assertTrue(derived.has_role(['Author']))
def test_has_role_w_list_w_context_miss(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class Folder(Implicit):
pass
root = Root()
root.__ac_local_roles__ = {'user': ['Editor']}
folder = Folder().__of__(root)
derived = self._makeDerived()
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: []
self.assertFalse(derived.has_role(['Author'], folder))
def test_has_role_w_list_w_context_hit(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class Folder(Implicit):
pass
root = Root()
root.__ac_local_roles__ = {'user': ['Editor']}
folder = Folder().__of__(root)
derived = self._makeDerived()
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: []
self.assertTrue(derived.has_role(['Editor'], folder))
def test_has_permission_miss(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getUserName = lambda *x: 'user'
derived.getRoles = lambda *x: []
self.assertFalse(derived.has_permission('Permission', folder))
def test_has_permission_hit(self):
from Acquisition import Implicit
class Root(Implicit):
pass
class UserFolder(Implicit):
pass
root = Root()
folder = UserFolder().__of__(root)
derived = self._makeDerived().__of__(folder)
derived.getRoles = lambda *x: ['Manager']
self.assertTrue(derived.has_permission('Permission', folder))
def test___len__(self):
derived = self._makeDerived()
......@@ -252,13 +604,3 @@ class NullUnrestrictedUserTests(unittest.TestCase):
# See https://bugs.launchpad.net/zope2/+bug/142563
null = self._makeOne()
self.assertEqual(str(null), "<NullUnrestrictedUser (None, None)>")
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(BasicUserTests))
suite.addTest(unittest.makeSuite(SimpleUserTests))
suite.addTest(unittest.makeSuite(SpecialUserTests))
suite.addTest(unittest.makeSuite(UnrestrictedUserTests))
suite.addTest(unittest.makeSuite(NullUnrestrictedUserTests))
return suite
......@@ -55,7 +55,7 @@ class BasicUser(Implicit):
# functionality that we cant anticipate from the base scaffolding.
def __allow_access_to_unprotected_subobjects__(self, name, value=None):
deny_names=('name', '__', 'roles', 'domains', '_getPassword',
'authenticate', '_shared_roles')
'authenticate')
if name in deny_names:
return 0
return 1
......@@ -128,29 +128,6 @@ class BasicUser(Implicit):
return result and domainSpecMatch(domains, request)
return result
def _shared_roles(self, parent):
r=[]
while 1:
if hasattr(parent, '__roles__'):
roles = parent.__roles__
if roles is None:
return 'Anonymous',
if 'Shared' in roles:
roles=list(roles)
roles.remove('Shared')
r = r + roles
else:
try:
return r + list(roles)
except:
return r
if getattr(parent, '__parent__', None) is not None:
while hasattr(parent.aq_self, 'aq_self'):
parent = parent.aq_self
parent = aq_parent(parent)
else:
return r
def _check_context(self, object):
# Check that 'object' exists in the acquisition context of
# the parent of the acl_users object containing this user,
......@@ -188,14 +165,6 @@ class BasicUser(Implicit):
if self._check_context(object):
return 1
# Check for ancient role data up front, convert if found.
# This should almost never happen, and should probably be
# deprecated at some point.
if 'Shared' in object_roles:
object_roles = self._shared_roles(object)
if object_roles is None or 'Anonymous' in object_roles:
return 1
# Check for a role match with the normal roles given to
# the user, then with local roles only if necessary. We
# want to avoid as much overhead as possible.
......@@ -211,6 +180,7 @@ class BasicUser(Implicit):
# we can incur only the overhead required to find a match.
inner_obj = getattr(object, 'aq_inner', object)
userid = self.getId()
parents = set()
while 1:
local_roles = getattr(inner_obj, '__ac_local_roles__', None)
if local_roles:
......@@ -226,16 +196,19 @@ class BasicUser(Implicit):
inner = getattr(inner_obj, 'aq_inner', inner_obj)
parent = getattr(inner, '__parent__', None)
if parent is not None:
if parent in parents:
break
parents.add(parent)
inner_obj = parent
continue
if hasattr(inner_obj, 'im_self'):
inner_obj=inner_obj.im_self
inner_obj=getattr(inner_obj, 'aq_inner', inner_obj)
inner_obj = inner_obj.im_self
inner_obj = getattr(inner_obj, 'aq_inner', inner_obj)
continue
break
return None
domains=[]
domains = []
def has_role(self, roles, object=None):
"""Check if the user has at least one role from a list of roles.
......@@ -459,14 +432,18 @@ def domainSpecMatch(spec, request):
if not host:
try:
host=socket.gethostbyaddr(addr)[0]
except:
host = socket.gethostbyaddr(addr)[0]
except Exception:
pass
if not addr:
try:
addr=socket.gethostbyname(host)
except:
pass
addr = socket.gethostbyname(host)
except Exception:
# always define localhost, even if the underlying system
# doesn't know about it, this fixes tests on travis
if host == 'localhost':
addr = '127.0.0.1'
_host = host.split('.')
_addr = addr.split('.')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment