예제 #1
0
def get_uris(settings):
    named = []
    for k, v in settings.items():
        if k.startswith(NAMED):
            name = k[len(NAMED):]
            if not name:
                raise ConfigurationError(
                    '%s is not a valid zodbconn identifier' % k)
            named.append((name, v))
    primary = settings.get('zodbconn.uri')
    if primary is None and named:
        raise ConfigurationError(
            'Must have primary zodbconn.uri in settings containing named uris')
    if primary:
        yield '', primary
        for name, uri in named:
            yield name, uri
예제 #2
0
 def add_authn_plugin(self, config, plugin):
     plugin_id = plugin.get_id()
     if plugin_id in self._plugins.keys():
         raise ConfigurationError(
             'Cannot register authentication plugin twice: "%s"', plugin_id)
     else:
         log.debug('Register authentication plugin: "%s"', plugin_id)
         self._plugins[plugin_id] = plugin
예제 #3
0
 def __call__(self, view):
     if (asyncio.iscoroutinefunction(view)
             or asyncio.iscoroutinefunction(getattr(view, '__call__', None))
             or self.is_class_method_coroutine(view)):
         raise ConfigurationError(
             'Coroutine {} mapped to executor.'.format(view))
     view = super().__call__(view)
     return self.run_in_executor_view(view)
 def ensure():
     if self.autocommit:
         return
     if self.registry.queryUtility(IAuthenticationPolicy) is None:
         raise ConfigurationError(
             'Cannot configure an authorization policy without '
             'also configuring an authentication policy '
             '(use the set_authorization_policy method)')
예제 #5
0
 def __init__(self, **settings):
     if not settings.get('name'):
         raise ConfigurationError(
             "You must provide a name for a content provider")
     if 'for_' in settings:
         if settings.get('context') is None:
             settings['context'] = settings['for_']
     self.__dict__.update(settings)
예제 #6
0
파일: i18n.py 프로젝트: rivalware/pyramid
    def add_translation_dirs(self, *specs):
        """ Add one or more :term:`translation directory` paths to the
        current configuration state.  The ``specs`` argument is a
        sequence that may contain absolute directory paths
        (e.g. ``/usr/share/locale``) or :term:`asset specification`
        names naming a directory path (e.g. ``some.package:locale``)
        or a combination of the two.

        Example:

        .. code-block:: python

           config.add_translation_dirs('/usr/share/locale',
                                       'some.package:locale')

        Later calls to ``add_translation_dir`` insert directories into the
        beginning of the list of translation directories created by earlier
        calls.  This means that the same translation found in a directory
        added later in the configuration process will be found before one
        added earlier in the configuration process.  However, if multiple
        specs are provided in a single call to ``add_translation_dirs``, the
        directories will be inserted into the beginning of the directory list
        in the order they're provided in the ``*specs`` list argument (items
        earlier in the list trump ones later in the list).
        """
        directories = []
        introspectables = []

        for spec in specs[::-1]:  # reversed
            package_name, filename = self._split_spec(spec)
            if package_name is None:  # absolute filename
                directory = filename
            else:
                __import__(package_name)
                package = sys.modules[package_name]
                directory = os.path.join(package_path(package), filename)

            if not os.path.isdir(os.path.realpath(directory)):
                raise ConfigurationError('"%s" is not a directory' % directory)
            intr = self.introspectable('translation directories', directory,
                                       spec, 'translation directory')
            intr['directory'] = directory
            intr['spec'] = spec
            introspectables.append(intr)
            directories.append(directory)

        def register():
            for directory in directories:

                tdirs = self.registry.queryUtility(ITranslationDirectories)
                if tdirs is None:
                    tdirs = []
                    self.registry.registerUtility(tdirs,
                                                  ITranslationDirectories)

                tdirs.insert(0, directory)

        self.action(None, register, introspectables=introspectables)
예제 #7
0
def initialize(config,
               version=None,
               settings_prefix='',
               default_settings=None):
    """Initialize kinto.core with the given configuration, version and project
    name.

    This will basically include kinto.core in Pyramid and set route prefix
    based on the specified version.

    :param config: Pyramid configuration
    :type config: ~pyramid:pyramid.config.Configurator
    :param str version: Current project version (e.g. '0.0.1') if not defined
        in application settings.
    :param str settings_prefix: Project name if not defined
        in application settings.
    :param dict default_settings: Override kinto.core default settings values.
    """
    from kinto.core import DEFAULT_SETTINGS

    settings = config.get_settings()

    settings_prefix = settings.pop(
        'kinto.settings_prefix',
        settings.get('settings_prefix')) or settings_prefix
    settings['settings_prefix'] = settings_prefix
    if not settings_prefix:
        warnings.warn('No value specified for `settings_prefix`')

    kinto_core_defaults = {**DEFAULT_SETTINGS}

    if default_settings:
        kinto_core_defaults.update(default_settings)

    load_default_settings(config, kinto_core_defaults)

    http_scheme = settings['http_scheme']
    if http_scheme != 'https':
        warnings.warn('HTTPS is not enabled')

    # Override project version from settings.
    project_version = settings.get('project_version') or version
    if not project_version:
        error_msg = 'Invalid project version: {}'.format(project_version)
        raise ConfigurationError(error_msg)
    settings['project_version'] = project_version = str(project_version)

    # HTTP API version.
    http_api_version = settings.get('http_api_version')
    if http_api_version is None:
        # The API version is derivated from the module version if not provided.
        http_api_version = '.'.join(project_version.split('.')[0:2])
    settings['http_api_version'] = http_api_version = str(http_api_version)
    api_version = 'v{}'.format(http_api_version.split('.')[0])

    # Include kinto.core views with the correct api version prefix.
    config.include('kinto.core', route_prefix=api_version)
    config.route_prefix = api_version
예제 #8
0
def initialize(config,
               version=None,
               settings_prefix="",
               default_settings=None):
    """Initialize kinto.core with the given configuration, version and project
    name.

    This will basically include kinto.core in Pyramid and set route prefix
    based on the specified version.

    :param config: Pyramid configuration
    :type config: ~pyramid:pyramid.config.Configurator
    :param str version: Current project version (e.g. '0.0.1') if not defined
        in application settings.
    :param str settings_prefix: Project name if not defined
        in application settings.
    :param dict default_settings: Override kinto.core default settings values.
    """
    from kinto.core import DEFAULT_SETTINGS

    settings = config.get_settings()

    settings_prefix = (settings.pop("kinto.settings_prefix",
                                    settings.get("settings_prefix"))
                       or settings_prefix)
    settings["settings_prefix"] = settings_prefix
    if not settings_prefix:
        warnings.warn("No value specified for `settings_prefix`")

    kinto_core_defaults = {**DEFAULT_SETTINGS}

    if default_settings:
        kinto_core_defaults.update(default_settings)

    load_default_settings(config, kinto_core_defaults)

    http_scheme = settings["http_scheme"]
    if http_scheme != "https":
        warnings.warn("HTTPS is not enabled")

    # Override project version from settings.
    project_version = settings.get("project_version") or version
    if not project_version:
        error_msg = f"Invalid project version: {project_version}"
        raise ConfigurationError(error_msg)
    settings["project_version"] = project_version = str(project_version)

    # HTTP API version.
    http_api_version = settings.get("http_api_version")
    if http_api_version is None:
        # The API version is derivated from the module version if not provided.
        http_api_version = ".".join(project_version.split(".")[0:2])
    settings["http_api_version"] = http_api_version = str(http_api_version)
    api_version = f"v{http_api_version.split('.')[0]}"

    # Include kinto.core views with the correct api version prefix.
    config.include("kinto.core", route_prefix=api_version)
    config.route_prefix = api_version
예제 #9
0
    def _add_view_from_route(self,
                             route_name,
                             view,
                             context,
                             permission,
                             renderer,
                             attr,
                             ):
        if view:
            self.add_view(
                permission=permission,
                context=context,
                view=view,
                name='',
                route_name=route_name,
                renderer=renderer,
                attr=attr,
                )
        else:
            # prevent mistakes due to misunderstanding of how hybrid calls to
            # add_route and add_view interact
            if attr:
                raise ConfigurationError(
                    'view_attr argument not permitted without view '
                    'argument')
            if context:
                raise ConfigurationError(
                    'view_context argument not permitted without view '
                    'argument')
            if permission:
                raise ConfigurationError(
                    'view_permission argument not permitted without view '
                    'argument')
            if renderer:
                raise ConfigurationError(
                    'view_renderer argument not permitted without '
                    'view argument')

        warnings.warn(
            'Passing view-related arguments to add_route() is deprecated as of '
            'Pyramid 1.1.  Use add_view() to associate a view with a route '
            'instead.  See "Deprecations" in "What\'s New in Pyramid 1.1" '
            'within the general Pyramid documentation for further details.',
            DeprecationWarning,
            4)
예제 #10
0
파일: __init__.py 프로젝트: stloma/kinto
def includeme(config):
    config.add_api_capability(
        'accounts',
        description='Manage user accounts.',
        url='https://kinto.readthedocs.io/en/latest/api/1.x/accounts.html')

    config.scan('kinto.plugins.accounts.views')

    PERMISSIONS_INHERITANCE_TREE['root'].update({
        'account:create': {}
    })
    PERMISSIONS_INHERITANCE_TREE['account'] = {
        'write': {'account': ['write']},
        'read': {'account': ['write', 'read']}
    }

    # Add some safety to avoid weird behaviour with basicauth default policy.
    settings = config.get_settings()
    auth_policies = settings['multiauth.policies']
    if 'basicauth' in auth_policies and 'account' in auth_policies:
        if auth_policies.index('basicauth') < auth_policies.index('account'):
            error_msg = ("'basicauth' should not be mentioned before 'account' "
                         "in 'multiauth.policies' setting.")
            raise ConfigurationError(error_msg)

    # We assume anyone in account_create_principals is to create
    # accounts for other people.
    # No one can create accounts for other people unless they are an
    # "admin", defined as someone matching account_write_principals.
    # Therefore any account that is in account_create_principals
    # should be in account_write_principals too.
    creators = set(settings.get('account_create_principals', '').split())
    admins = set(settings.get('account_write_principals', '').split())
    cant_create_anything = creators.difference(admins)
    # system.Everyone isn't an account.
    cant_create_anything.discard('system.Everyone')
    if cant_create_anything:
        message = ('Configuration has some principals in account_create_principals '
                   'but not in account_write_principals. These principals will only be '
                   'able to create their own accounts. This may not be what you want.\n'
                   'If you want these users to be able to create accounts for other users, '
                   'add them to account_write_principals.\n'
                   'Affected users: {}'.format(list(cant_create_anything)))

        raise ConfigurationError(message)
예제 #11
0
    def __init__(self,
                 name,
                 path=None,
                 description=None,
                 cors_policy=None,
                 depth=1,
                 pyramid_route=None,
                 **kw):
        self.name = name
        self.path = path
        self.pyramid_route = pyramid_route

        if not self.path and not self.pyramid_route:
            raise TypeError('You need to pass path or pyramid_route arg')

        self.description = description
        self.cors_expose_all_headers = True
        self._cors_enabled = None

        if cors_policy:
            for key, value in cors_policy.items():
                kw.setdefault('cors_' + key, value)

        for key in self.list_arguments:
            # default_{validators,filters} and {filters,validators} don't
            # have to be mutables, so we need to create a new list from them
            extra = to_list(kw.get(key, []))
            kw[key] = []
            kw[key].extend(getattr(self, 'default_%s' % key, []))
            kw[key].extend(extra)

        self.arguments = self.get_arguments(kw)
        for key, value in self.arguments.items():
            # avoid squashing Service.decorator if ``decorator``
            # argument is used to specify a default pyramid view
            # decorator
            if key != 'decorator':
                setattr(self, key, value)

        if hasattr(self, 'acl'):
            raise ConfigurationError("'acl' is not supported")

        # instantiate some variables we use to keep track of what's defined for
        # this service.
        self.defined_methods = []
        self.definitions = []

        # add this service to the list of available services
        SERVICES.append(self)

        # this callback will be called when config.scan (from pyramid) will
        # be triggered.
        def callback(context, name, ob):
            config = context.config.with_package(info.module)
            config.add_cornice_service(self)

        info = venusian.attach(self, callback, category='pyramid', depth=depth)
예제 #12
0
def scan_handler(config, handler, route_name, action_decorator,
                 **default_view_args):
    """Scan a handler for automatically exposed views to register"""
    autoexpose = getattr(handler, '__autoexpose__', r'[A-Za-z]+')
    if autoexpose:
        try:
            autoexpose = re.compile(autoexpose).match
        except (re.error, TypeError), why:
            raise ConfigurationError(why[0])
예제 #13
0
 def __call__(self, view):
     if inspect.isclass(view):
         view = getattr(view, self.attr)
     if asyncio.iscoroutinefunction(view) or asyncio.iscoroutinefunction(
             getattr(view, '__call__', None)):
         raise ConfigurationError(
             'Coroutine {} mapped to executor.'.format(view))
     view = super().__call__(view)
     return self.run_in_executor_view(view)
예제 #14
0
def _parse_settings(settings):
    """
    Convenience function to collect settings prefixed by 'mongoengine_session' and
    coerce settings to ``int``, ``float``, and ``bool`` as needed.
    """
    keys = [s for s in settings if s.startswith('mongoengine_sessions.')]

    options = {}

    for k in keys:
        param = k.split('.')[-1]
        value = settings[k]
        options[param] = value

    # only required setting
    if 'secret' not in options:
        raise ConfigurationError(
            'mongoengine_sessions.secret is a required setting')

    # coerce bools
    for b in ('cookie_secure', 'cookie_httponly', 'cookie_on_exception'):
        if b in options:
            options[b] = asbool(options[b])

    # coerce ints
    for i in ('timeout', 'port', 'db', 'cookie_max_age'):
        if i in options:
            options[i] = int(options[i])

    # coerce float
    if 'socket_timeout' in options:
        options['socket_timeout'] = float(options['socket_timeout'])

    # check for settings conflict
    if 'prefix' in options and 'id_generator' in options:
        err = 'cannot specify custom id_generator and a key prefix'
        raise ConfigurationError(err)

    # convenience setting for overriding key prefixes
    if 'prefix' in options:
        prefix = options.pop('prefix')
        options['id_generator'] = partial(prefixed_id, prefix=prefix)

    return options
예제 #15
0
    def __init__(self,
                 name,
                 path,
                 description=None,
                 cors_policy=None,
                 depth=1,
                 **kw):
        self.name = name
        self.path = path
        self.description = description
        self.cors_expose_all_headers = True
        self._cors_enabled = None

        if cors_policy:
            for key, value in cors_policy.items():
                kw.setdefault('cors_' + key, value)

        for key in self.list_arguments:
            # default_{validators,filters} and {filters,validators} don't
            # have to be mutables, so we need to create a new list from them
            extra = to_list(kw.get(key, []))
            kw[key] = []
            kw[key].extend(getattr(self, 'default_%s' % key, []))
            kw[key].extend(extra)

        self.arguments = self.get_arguments(kw)
        for key, value in self.arguments.items():
            # avoid squashing Service.decorator if ``decorator``
            # argument is used to specify a default pyramid view
            # decorator
            if key != 'decorator':
                setattr(self, key, value)

        if hasattr(self, 'factory') and hasattr(self, 'acl'):
            raise ConfigurationError("Cannot specify both 'acl' and 'factory'")

        # instantiate some variables we use to keep track of what's defined for
        # this service.
        self.defined_methods = []
        self.definitions = []

        # add this service to the list of available services
        SERVICES.append(self)

        # register aliases for the decorators
        for verb in ('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'):
            setattr(self, verb.lower(),
                    functools.partial(self.decorator, verb))

        # this callback will be called when config.scan (from pyramid) will
        # be triggered.
        def callback(context, name, ob):
            config = context.config.with_package(info.module)
            config.add_cornice_service(self)

        info = venusian.attach(self, callback, category='pyramid', depth=depth)
예제 #16
0
def prepare(request=None, registry=None):
    """ This function pushes data onto the Pyramid threadlocal stack
    (request and registry), making those objects 'current'.  It
    returns a dictionary useful for bootstrapping a Pyramid
    application in a scripting environment.

    ``request`` is passed to the :app:`Pyramid` application root
    factory to compute the root. If ``request`` is None, a default
    will be constructed using the registry's :term:`Request Factory`
    via the :meth:`pyramid.interfaces.IRequestFactory.blank` method.

    If ``registry`` is not supplied, the last registry loaded from
    :attr:`pyramid.config.global_registries` will be used. If you
    have loaded more than one :app:`Pyramid` application in the
    current process, you may not want to use the last registry
    loaded, thus you can search the ``global_registries`` and supply
    the appropriate one based on your own criteria.

    The function returns a dictionary composed of ``root``,
    ``closer``, ``registry``, ``request`` and ``root_factory``.  The
    ``root`` returned is the application's root resource object.  The
    ``closer`` returned is a callable (accepting no arguments) that
    should be called when your scripting application is finished
    using the root.  ``registry`` is the registry object passed or
    the last registry loaded into
    :attr:`pyramid.config.global_registries` if no registry is passed.
    ``request`` is the request object passed or the constructed request
    if no request is passed.  ``root_factory`` is the root factory used
    to construct the root.
    """
    if registry is None:
        registry = getattr(request, 'registry', global_registries.last)
    if registry is None:
        raise ConfigurationError('No valid Pyramid applications could be '
                                 'found, make sure one has been created '
                                 'before trying to activate it.')
    if request is None:
        request = _make_request('/', registry)
    # NB: even though _make_request might have already set registry on
    # request, we reset it in case someone has passed in their own
    # request.
    request.registry = registry 
    threadlocals = {'registry':registry, 'request':request}
    threadlocal_manager.push(threadlocals)
    extensions = registry.queryUtility(IRequestExtensions)
    if extensions is not None:
        request._set_extensions(extensions)
    def closer():
        threadlocal_manager.pop()
    root_factory = registry.queryUtility(IRootFactory,
                                         default=DefaultRootFactory)
    root = root_factory(request)
    if getattr(request, 'context', None) is None:
        request.context = root
    return {'root':root, 'closer':closer, 'registry':registry,
            'request':request, 'root_factory':root_factory}
예제 #17
0
def safe_json(get, section, key):
    try:
        value = get(key)
        json_value = json.loads(value)
    except ValueError:
        msg = 'The %s=%s is not valid json in section %s' % (key, value,
                                                             section)
        raise ConfigurationError(msg)

    return json_value
예제 #18
0
def get_ldap_connector(request):
    """ Return the LDAP connector attached to the request.  If
    :meth:`pyramid.config.Configurator.ldap_setup` was not called, using
    this function will raise an :exc:`pyramid.exceptions.ConfigurationError`."""
    connector = getattr(request, 'ldap_connector', None)
    if connector is None:
        raise ConfigurationError(
            'You must call Configurator.ldap_setup during setup '
            'to use an ldap connector')
    return connector
예제 #19
0
    def __call__(self, view):
        if not asyncio.iscoroutinefunction(view) and is_generator(view):
            view = asyncio.coroutine(view)
        else:
            raise ConfigurationError(
                'Non-coroutine {} mapped to coroutine.'.format(view)
            )

        view = super().__call__(view)
        return self.run_in_coroutine_view(view)
예제 #20
0
def includeme(config):
    settings = config.registry.settings
    servers = splitlines(settings.get('velruse.store.servers', ''))
    key_prefix = settings.get('velruse.store.key_prefix', 'velruse_ustore')

    if not servers:
        raise ConfigurationError('Missing "velruse.store.servers" setting')

    store = MemcachedStore(servers=servers, key_prefix=key_prefix)
    config.registry.velruse_store = store
예제 #21
0
    def action():
        storage = cfg.registry.get(ID_LAYER, {})
        layers = storage.get(layer, [])
        for intr in layers:
            if intr['name'] == name:
                intr['filters'][template] = mapped_view
                return

        raise ConfigurationError("Can't find layer: %s%s" %
                                 (layer, '(%s)' % name if name else ''))
예제 #22
0
    def add_translation_dirs(self, *specs):
        """ Add one or more :term:`translation directory` paths to the
        current configuration state.  The ``specs`` argument is a
        sequence that may contain absolute directory paths
        (e.g. ``/usr/share/locale``) or :term:`asset specification`
        names naming a directory path (e.g. ``some.package:locale``)
        or a combination of the two.

        Example:

        .. code-block:: python

           config.add_translation_dirs('/usr/share/locale',
                                       'some.package:locale')

        Later calls to ``add_translation_dir`` insert directories into the
        beginning of the list of translation directories created by earlier
        calls.  This means that the same translation found in a directory
        added later in the configuration process will be found before one
        added earlier in the configuration process.  However, if multiple
        specs are provided in a single call to ``add_translation_dirs``, the
        directories will be inserted into the beginning of the directory list
        in the order they're provided in the ``*specs`` list argument (items
        earlier in the list trump ones later in the list).
        """
        for spec in specs[::-1]:  # reversed

            package_name, filename = self._split_spec(spec)
            if package_name is None:  # absolute filename
                directory = filename
            else:
                __import__(package_name)
                package = sys.modules[package_name]
                directory = os.path.join(package_path(package), filename)

            if not os.path.isdir(os.path.realpath(directory)):
                raise ConfigurationError('"%s" is not a directory' % directory)

            tdirs = self.registry.queryUtility(ITranslationDirectories)
            if tdirs is None:
                tdirs = []
                self.registry.registerUtility(tdirs, ITranslationDirectories)

            tdirs.insert(0, directory)
            # XXX no action?

        if specs:

            # We actually only need an IChameleonTranslate function
            # utility to be registered zero or one times.  We register the
            # same function once for each added translation directory,
            # which does too much work, but has the same effect.

            ctranslate = ChameleonTranslate(translator)
            self.registry.registerUtility(ctranslate, IChameleonTranslate)
예제 #23
0
 def __init__(self, request):
     try:
         self.tempdir=request.registry.settings['substanced.uploads_tempdir']
     except KeyError:
         raise ConfigurationError(
             'To use FileUploadTempStore, you must set a  '
             '"substanced.uploads_tempdir" key in your .ini settings. It '
             'points to a directory which will temporarily '
             'hold uploaded files when form validation fails.')
     self.request = request
     self.session = request.session
예제 #24
0
def load_provider(config, provider):
    settings = config.registry.settings
    impl = settings.get('provider.%s.impl' % provider) or provider

    login_cfg = settings_adapter.get(impl)
    if login_cfg is None:
        raise ConfigurationError(
            'could not find configuration method for provider %s'
            '' % provider)
    loader = getattr(config, login_cfg)
    loader(prefix='provider.%s.' % provider)
예제 #25
0
def includeme(config):
    config.add_directive('load_and_include', load_and_include)
    config.include('.models')
    if config.registry.settings.get('pyramid_settings.includes', None):
        raise ConfigurationError("'pyramid_settings.includes' was in the paster ini file. "
                                 "That setting is only ment for included config files. If you need to load something "
                                 "before this package, use the default 'pyramid.includes'")
    filenames = config.registry.settings.get('pyramid_settings.files', "").splitlines()
    for fn in filenames:
        if fn:
            config.load_and_include(fn)
예제 #26
0
    def __call__(self, view):
        if is_unbound_method(view) and self.attr is None:
            raise ConfigurationError((
                'Unbound method calls are not supported, please set the class '
                'as your `view` and the method as your `attr`'))

        if inspect.isclass(view):
            view = self.map_class(view)
        else:
            view = self.map_nonclass(view)
        return view
예제 #27
0
def get_callable_name(name):
    """
    Verifies that the ``name`` is ascii and will raise a ``ConfigurationError``
    if it is not.
    """
    try:
        return native_(name, 'ascii')
    except (UnicodeEncodeError, UnicodeDecodeError):
        msg = ('`name="%s"` is invalid. `name` must be ascii because it is '
               'used on __name__ of the method')
        raise ConfigurationError(msg % name)
예제 #28
0
 def explorer_view(request):
     settings = config.registry.settings
     if settings.get('pyramid_openapi3') is None:
         ConfigurationError('You need to call config.pyramid_openapi3_spec for explorer to work.')
     with open(resolved_template.abspath()) as f:
         template = Template(f.read())
         html = template.safe_substitute(
             ui_version=ui_version,
             spec_url=request.route_url(settings['pyramid_openapi3']["spec_route_name"]),
         )
     return Response(html)
예제 #29
0
    def authenticate(self, login, password, attributes=ALL_ATTRIBUTES):
        """ Given a login name and a password, return a tuple of ``(dn,
        attrdict)`` if the matching user if the user exists and his password
        is correct.  Otherwise return ``None``.

        In a ``(dn, attrdict)`` return value, ``dn`` will be the
        distinguished name of the authenticated user.  Attrdict will be a
        dictionary mapping LDAP user attributes to sequences of values.  The
        keys and values in the dictionary values provided will be decoded
        from UTF-8, recursively, where possible.  The dictionary returned is
        a case-insensitive dictionary implemenation.

        A zero length password will always be considered invalid since it
        results in a request for "unauthenticated authentication" which should
        not be used for LDAP based authentication. See `section 5.1.2 of
        RFC-4513 <http://tools.ietf.org/html/rfc4513#section-5.1.2>`_ for a
        description of this behavior.

        If :meth:`pyramid.config.Configurator.ldap_set_login_query` was not
        called, using this function will raise an
        :exc:`pyramid.exceptions.ConfiguratorError`."""
        if password == '':
            return None

        #with self.manager.connection() as conn:
        #with self.connection as conn:
        conn = self.connection
        conn.open()
        search = getattr(self.registry, 'ldap_login_query', None)
        if search is None:
            raise ConfigurationError(
                'ldap_set_login_query was not called during setup')

        result = search.execute(conn, login=login, password=password, attributes=attributes)
        if len(result) > 1:
            conn.result['description'] = 'invalidCredentials'
            conn.result['message'] = ''
            return None
        elif len(result) < 1:
            conn.result['description'] = 'invalidCredentials'
            conn.result['message'] = ''
            return None
        else:
            login_dn = result[0]['dn']
        try:
            conn.user = login_dn
            conn.password = password
            conn.bind()
            # must invoke the __enter__ of this thing for it to connect
            return _ldap_decode(result[0])
        except ldap3.LDAPException:
            logger.debug('Exception in authenticate with login %r' % login,
                         exc_info=True)
            return None
예제 #30
0
 def session(self):
     """ Obtain the :term:`session` object associated with this
     request.  If a :term:`session factory` has not been registered
     during application configuration, a
     :class:`pyramid.exceptions.ConfigurationError` will be raised"""
     factory = self.registry.queryUtility(ISessionFactory)
     if factory is None:
         raise ConfigurationError(
             'No session factory registered '
             '(see the Sessions chapter of the Pyramid documentation)')
     return factory(self)