Ejemplo n.º 1
0
def convert_provider_data(provider_data, mapping, key_filter=None):
    """Converts data coming from the provider to be used by the application

    The result will have all the keys listed in `keys` with values
    coming either from `data` (using the key mapping defined in
    `mapping`) or ``None`` in case the key is not present. If
    `key_filter` is ``None``, all keys from `provider_data` will be used
    unless they are mapped to a different key in `mapping`.

    :param provider_data: dict -- Data coming from the provider.
    :param mapping: dict -- Mapping between keys used to define the data
                    in the provider and those used by the application.
                    All application keys will be present in the return
                    value, defaulting to ``None``.
    :param key_filter: list -- Keys to be exclusively considered. If
                       ``None``, all items will be returned. Keys not
                       present in the mapped data, will have a value of
                       ``None``.
    :return: dict -- containing the values of `app_data` mapped to the
             keys of the application as defined in the `mapping` and
             filtered out by `key_filter`.
    """
    provider_keys = set(mapping.values())
    result = {key: value for key, value in iteritems(provider_data) if key not in provider_keys}
    result.update((app_key, provider_data.get(provider_key)) for app_key, provider_key in iteritems(mapping))
    if key_filter is not None:
        key_filter = set(key_filter)
        result = {key: value for key, value in iteritems(result) if key in key_filter}
        result.update({key: None for key in key_filter - set(result)})
    return result
Ejemplo n.º 2
0
 def search_identities(self, criteria, exact=False):
     compare = operator.eq if exact else operator.contains
     for identifier, user in iteritems(self.settings['identities']):
         for key, values in iteritems(criteria):
             if not any(compare(user[key], v) for v in values):
                 break
         else:
             yield IdentityInfo(self, identifier, **user)
Ejemplo n.º 3
0
 def search_identities(self, criteria, exact=False):
     for identifier, user in iteritems(self.settings['identities']):
         for key, values in iteritems(criteria):
             # same logic as multidict
             user_value = user.get(key)
             user_values = set(user_value) if isinstance(user_value, (tuple, list)) else {user_value}
             if not any(user_values):
                 break
             elif exact and not user_values & set(values):
                 break
             elif not exact and not any(sv in uv for sv, uv in itertools.product(values, user_values)):
                 break
         else:
             yield IdentityInfo(self, identifier, **user)
Ejemplo n.º 4
0
def convert_app_data(app_data, mapping, key_filter=None):
    """Converts data coming from the application to be used by the provider.

    :param app_data: dict -- Data coming from the application.
    :param mapping: dict -- Mapping between keys used to define the data
                    in the application and those used by the provider.
    :param key_filter: list -- Keys to be exclusively considered. If
                       ``None``, all items will be returned.
    :return: dict -- containing the values of `app_data` mapped to the
             keys of the provider as defined in the `mapping` and
             filtered out by `key_filter`.
    """
    if key_filter:
        key_filter = set(key_filter)
        app_data = {k: v for k, v in iteritems(app_data) if k in key_filter}
    return {mapping.get(key, key): value for key, value in iteritems(app_data)}
Ejemplo n.º 5
0
def convert_app_data(app_data, mapping, key_filter=None):
    """Converts data coming from the application to be used by the provider.

    :param app_data: dict -- Data coming from the application.
    :param mapping: dict -- Mapping between keys used to define the data
                    in the application and those used by the provider.
    :param key_filter: list -- Keys to be exclusively considered. If
                       ``None``, all items will be returned.
    :return: dict -- containing the values of `app_data` mapped to the
             keys of the provider as defined in the `mapping` and
             filtered out by `key_filter`.
    """
    if key_filter:
        key_filter = set(key_filter)
        app_data = {k: v for k, v in iteritems(app_data) if k in key_filter}
    return {mapping.get(key, key): value for key, value in iteritems(app_data)}
Ejemplo n.º 6
0
    def search_identities(self, providers=None, exact=False, **criteria):
        """Searches user identities matching certain criteria

        :param providers: A list of providers to search in. If not
                          specified, all providers are searched.
        :param exact: If criteria need to match exactly, i.e. no
                      substring matches are performed.
        :param criteria: The criteria to search for. A criterion can
                         have a list, tuple or set as value if there are
                         many values for the same criterion.
        :return: An iterable of matching user identities.
        """
        for k, v in iteritems(criteria):
            if isinstance(v, multi_value_types):
                criteria[k] = v = set(v)
            elif not isinstance(v, set):
                criteria[k] = v = {v}
            if any(not x for x in v):
                raise ValueError('Empty search criterion: ' + k)

        for provider in itervalues(self.identity_providers):
            if providers is not None and provider.name not in providers:
                continue
            if not provider.supports_search:
                continue
            for identity_info in provider.search_identities(provider.map_search_criteria(criteria), exact=exact):
                yield identity_info
Ejemplo n.º 7
0
    def search_identities(self, providers=None, exact=False, **criteria):
        """Searches user identities matching certain criteria

        :param providers: A list of providers to search in. If not
                          specified, all providers are searched.
        :param exact: If criteria need to match exactly, i.e. no
                      substring matches are performed.
        :param criteria: The criteria to search for. A criterion can
                         have a list, tuple or set as value if there are
                         many values for the same criterion.
        :return: An iterable of matching user identities.
        """
        for k, v in iteritems(criteria):
            if isinstance(v, multi_value_types):
                criteria[k] = v = set(v)
            elif not isinstance(v, set):
                criteria[k] = v = {v}
            if any(not x for x in v):
                raise ValueError('Empty search criterion: ' + k)

        for provider in itervalues(self.identity_providers):
            if providers is not None and provider.name not in providers:
                continue
            if not provider.supports_search:
                continue
            for identity_info in provider.search_identities(
                    provider.map_search_criteria(criteria), exact=exact):
                yield identity_info
Ejemplo n.º 8
0
 def search_identities(self, criteria, exact=False):
     for identifier, user in iteritems(self.settings['identities']):
         for key, values in iteritems(criteria):
             # same logic as multidict
             user_value = user.get(key)
             user_values = set(user_value) if isinstance(
                 user_value, (tuple, list)) else {user_value}
             if not any(user_values):
                 break
             elif exact and not user_values & set(values):
                 break
             elif not exact and not any(
                     sv in uv
                     for sv, uv in itertools.product(values, user_values)):
                 break
         else:
             yield IdentityInfo(self, identifier, **user)
Ejemplo n.º 9
0
def ldap_connect(settings, use_cache=True):
    """Establishes an LDAP connection.

    Establishes a connection to the LDAP server from the `uri` in the
    ``settings``.

    To establish a connection, the settings must be specified:
     - ``uri``: valid URI which points to a LDAP server,
     - ``bind_dn``: `dn` used to initially bind every LDAP connection
     - ``bind_password``" password used for the initial bind
     - ``tls``: ``True`` if the connection should use TLS encryption
     - ``starttls``: ``True`` to negotiate TLS with the server

    `Note`: ``starttls`` is ignored if the URI uses LDAPS and ``tls`` is
    set to ``True``.

    This function re-uses an existing LDAP connection if there is one
    available in the application context, unless caching is disabled.

    :param settings: dict -- The settings for a LDAP provider.
    :param use_cache: bool -- If the connection should be cached.
    :return: The ldap connection.
    """

    if use_cache:
        cache = _get_ldap_cache()
        cache_key = frozenset(
            (k, hash(v)) for k, v in iteritems(settings) if k in conn_keys)
        conn = cache.get(cache_key)
        if conn is not None:
            return conn

    uri_info = urlparse(settings['uri'])
    use_ldaps = uri_info.scheme == 'ldaps'
    credentials = (settings['bind_dn'], settings['bind_password'])
    ldap_connection = ReconnectLDAPObject(settings['uri'])
    ldap_connection.protocol_version = ldap.VERSION3
    ldap_connection.set_option(ldap.OPT_REFERRALS, 0)
    ldap_connection.set_option(
        ldap.OPT_X_TLS,
        ldap.OPT_X_TLS_DEMAND if use_ldaps else ldap.OPT_X_TLS_NEVER)
    ldap_connection.set_option(
        ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND
        if settings['verify_cert'] else ldap.OPT_X_TLS_ALLOW)
    # force the creation of a new TLS context. This must be the last TLS option.
    # see: http://stackoverflow.com/a/27713355/298479
    ldap_connection.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
    if use_ldaps and settings['starttls']:
        warn(
            "Unable to start TLS, LDAP connection already secured over SSL (LDAPS)"
        )
    elif settings['starttls']:
        ldap_connection.start_tls_s()
    # TODO: allow anonymous bind
    ldap_connection.simple_bind_s(*credentials)
    if use_cache:
        cache[cache_key] = ldap_connection
    return ldap_connection
Ejemplo n.º 10
0
def test_validate_provider_map(valid, auth_providers, identity_providers, provider_map):
    state = _MultipassState(None, None)
    state.auth_providers = {x: {} for x in auth_providers}
    state.identity_providers = {x: {} for x in identity_providers}
    state.provider_map = {a: [{'identity_provider': u}] for a, u in iteritems(provider_map)}
    if valid:
        validate_provider_map(state)
    else:
        pytest.raises(ValueError, validate_provider_map, state)
Ejemplo n.º 11
0
 def _shibboleth_callback(self):
     attributes = {
         k: v
         for k, v in iteritems(request.environ)
         if k.startswith(self.settings['attrs_prefix'])
     }
     if not attributes:
         raise AuthenticationFailed("No valid data received")
     return self.multipass.handle_auth_success(AuthInfo(self, **attributes))
Ejemplo n.º 12
0
def get_canonical_provider_map(provider_map):
    """Converts the configured provider map to a canonical form"""
    canonical = {}
    for auth_provider_name, identity_providers in iteritems(provider_map):
        if not isinstance(identity_providers, (list, tuple, set)):
            identity_providers = [identity_providers]
        identity_providers = tuple({'identity_provider': p} if isinstance(p, string_types) else p
                                   for p in identity_providers)
        canonical[auth_provider_name] = identity_providers
    return canonical
Ejemplo n.º 13
0
def build_search_filter(criteria, type_filter, mapping=None, exact=False):
    """Builds a valid LDAP search filter for retrieving entries.

    :param criteria: dict -- Criteria to be ANDed together to build the
                     filter, if a criterion has many values they will
                     be ORed together.
    :param mapping: dict -- Mapping from criteria to LDAP attributes
    :param exact: bool -- Match attributes values exactly if ``True``,
                  othewise perform substring matching.
    :return: str -- Valid LDAP search filter.
    """

    assertions = convert_app_data(criteria, mapping or {})
    assert_templates = [_build_assert_template(value, exact) for _, value in iteritems(assertions)]
    assertions = [(k, v) for k, values in iteritems(assertions) if k and values for v in values]
    if not assertions:
        return None
    filter_template = '(&{}{})'.format("".join(assert_templates), type_filter)
    return filter_format(filter_template, (item for assertion in assertions for item in assertion))
Ejemplo n.º 14
0
def ldap_connect(settings, use_cache=True):
    """Establishes an LDAP connection.

    Establishes a connection to the LDAP server from the `uri` in the
    ``settings``.

    To establish a connection, the settings must be specified:
     - ``uri``: valid URI which points to a LDAP server,
     - ``bind_dn``: `dn` used to initially bind every LDAP connection
     - ``bind_password``" password used for the initial bind
     - ``tls``: ``True`` if the connection should use TLS encryption
     - ``starttls``: ``True`` to negotiate TLS with the server

    `Note`: ``starttls`` is ignored if the URI uses LDAPS and ``tls`` is
    set to ``True``.

    This function re-uses an existing LDAP connection if there is one
    available in the application context, unless caching is disabled.

    :param settings: dict -- The settings for a LDAP provider.
    :param use_cache: bool -- If the connection should be cached.
    :return: The ldap connection.
    """

    if use_cache:
        cache = _get_ldap_cache()
        cache_key = frozenset((k, hash(v)) for k, v in iteritems(settings) if k in conn_keys)
        conn = cache.get(cache_key)
        if conn is not None:
            return conn

    uri_info = urlparse(settings['uri'])
    use_ldaps = uri_info.scheme == 'ldaps'
    credentials = (settings['bind_dn'], settings['bind_password'])
    ldap_connection = ReconnectLDAPObject(settings['uri'])
    ldap_connection.protocol_version = ldap.VERSION3
    ldap_connection.set_option(ldap.OPT_REFERRALS, 0)
    ldap_connection.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND if use_ldaps else ldap.OPT_X_TLS_NEVER)
    if settings['cert_file']:
        ldap_connection.set_option(ldap.OPT_X_TLS_CACERTFILE, settings['cert_file'])
    ldap_connection.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,
                               ldap.OPT_X_TLS_DEMAND if settings['verify_cert'] else ldap.OPT_X_TLS_ALLOW)
    # force the creation of a new TLS context. This must be the last TLS option.
    # see: http://stackoverflow.com/a/27713355/298479
    ldap_connection.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
    if use_ldaps and settings['starttls']:
        warn("Unable to start TLS, LDAP connection already secured over SSL (LDAPS)")
    elif settings['starttls']:
        ldap_connection.start_tls_s()
    # TODO: allow anonymous bind
    ldap_connection.simple_bind_s(*credentials)
    if use_cache:
        cache[cache_key] = ldap_connection
    return ldap_connection
Ejemplo n.º 15
0
def get_canonical_provider_map(provider_map):
    """Converts the configured provider map to a canonical form"""
    canonical = {}
    for auth_provider_name, identity_providers in iteritems(provider_map):
        if not isinstance(identity_providers, (list, tuple, set)):
            identity_providers = [identity_providers]
        identity_providers = tuple(
            {'identity_provider': p} if isinstance(p, string_types) else p
            for p in identity_providers)
        canonical[auth_provider_name] = identity_providers
    return canonical
Ejemplo n.º 16
0
def to_unicode(data):
    if isinstance(data, bytes):
        return data.decode('utf-8', 'replace')
    elif isinstance(data, dict):
        return {to_unicode(k): to_unicode(v) for k, v in iteritems(data)}
    elif isinstance(data, list):
        return [to_unicode(x) for x in data]
    elif isinstance(data, set):
        return {to_unicode(x) for x in data}
    elif isinstance(data, tuple):
        return tuple(to_unicode(x) for x in data)
    else:
        return data
Ejemplo n.º 17
0
def to_bytes_recursive(obj):
    if isinstance(obj, dict):
        return dict((bytes(k), to_bytes_recursive(v)) for k, v in iteritems(obj))
    elif isinstance(obj, list):
        return map(to_bytes_recursive, obj)
    elif isinstance(obj, set):
        return {to_bytes_recursive(x) for x in obj}
    elif isinstance(obj, tuple):
        return tuple(to_bytes_recursive(x) for x in obj)
    elif isinstance(obj, unicode):
        return bytes(obj)
    else:
        return obj
Ejemplo n.º 18
0
    def search_identities_ex(self,
                             providers=None,
                             exact=False,
                             limit=None,
                             criteria=None):
        """Search user identities matching search criteria.

        This is very similar to :meth:`search_identities`, but instead of just
        yielding identities, it allows specifying a limit and only returns up
        to that number of identities *per provider*. It also returns the total
        number of found identities so the application can decide to inform the
        user that their search criteria may be too broad.

        :return: A tuple containing ``(identities, total_count)``.
        """
        for k, v in iteritems(criteria):
            if isinstance(v, multi_value_types):
                criteria[k] = v = set(v)
            elif not isinstance(v, set):
                criteria[k] = v = {v}
            if any(not x for x in v):
                raise ValueError('Empty search criterion: ' + k)

        found_identities = []
        total = 0
        for provider in itervalues(self.identity_providers):
            if providers is not None and provider.name not in providers:
                continue
            if not provider.supports_search:
                continue
            if provider.supports_search_ex:
                result, subtotal = provider.search_identities_ex(
                    provider.map_search_criteria(criteria),
                    exact=exact,
                    limit=limit)
                found_identities += result
                total += subtotal
            else:
                result_iter = provider.search_identities(
                    provider.map_search_criteria(criteria), exact=exact)
                if limit is not None:
                    result = list(itertools.islice(result_iter, limit))
                    found_identities += result
                    total += len(result) + sum(1 for _ in result_iter)
                else:
                    result = list(result_iter)
                    found_identities += result
                    total += len(result)

        return found_identities, total
Ejemplo n.º 19
0
 def set_defaults(self):
     self.ldap_settings.setdefault('timeout', 30)
     self.ldap_settings.setdefault('verify_cert', True)
     self.ldap_settings.setdefault('cert_file', certifi.where() if certifi else None)
     self.ldap_settings.setdefault('starttls', False)
     self.ldap_settings.setdefault('page_size', 1000)
     self.ldap_settings.setdefault('uid', 'uid')
     self.ldap_settings.setdefault('user_filter', '(objectClass=person)')
     if not self.ldap_settings['cert_file'] and self.ldap_settings['verify_cert']:
         warn("You should install certifi or provide a certificate file in order to verify the LDAP certificate.")
     # Convert LDAP settings to bytes since python-ldap chokes on unicode strings
     for key, value in iteritems(self.ldap_settings):
         if isinstance(value, unicode):
             self.ldap_settings[key] = bytes(value)
Ejemplo n.º 20
0
def to_bytes_recursive(obj):
    if isinstance(obj, dict):
        return dict(
            (bytes(k), to_bytes_recursive(v)) for k, v in iteritems(obj))
    elif isinstance(obj, list):
        return map(to_bytes_recursive, obj)
    elif isinstance(obj, set):
        return {to_bytes_recursive(x) for x in obj}
    elif isinstance(obj, tuple):
        return tuple(to_bytes_recursive(x) for x in obj)
    elif isinstance(obj, unicode):
        return bytes(obj)
    else:
        return obj
Ejemplo n.º 21
0
def convert_provider_data(provider_data, mapping, key_filter=None):
    """Converts data coming from the provider to be used by the application

    The result will have all the keys listed in `keys` with values
    coming either from `data` (using the key mapping defined in
    `mapping`) or ``None`` in case the key is not present. If
    `key_filter` is ``None``, all keys from `provider_data` will be used
    unless they are mapped to a different key in `mapping`.

    :param provider_data: dict -- Data coming from the provider.
    :param mapping: dict -- Mapping between keys used to define the data
                    in the provider and those used by the application.
                    All application keys will be present in the return
                    value, defaulting to ``None``.
    :param key_filter: list -- Keys to be exclusively considered. If
                       ``None``, all items will be returned. Keys not
                       present in the mapped data, will have a value of
                       ``None``.
    :return: dict -- containing the values of `app_data` mapped to the
             keys of the application as defined in the `mapping` and
             filtered out by `key_filter`.
    """
    provider_keys = set(mapping.values())
    result = {
        key: value
        for key, value in iteritems(provider_data) if key not in provider_keys
    }
    result.update((app_key, provider_data.get(provider_key))
                  for app_key, provider_key in iteritems(mapping))
    if key_filter is not None:
        key_filter = set(key_filter)
        result = {
            key: value
            for key, value in iteritems(result) if key in key_filter
        }
        result.update({key: None for key in key_filter - set(result)})
    return result
Ejemplo n.º 22
0
def build_search_filter(criteria, type_filter, mapping=None, exact=False):
    """Builds a valid LDAP search filter for retrieving entries.

    :param criteria: dict -- Criteria to be ANDed together to build the
                     filter, if a criterion has many values they will
                     be ORed together.
    :param mapping: dict -- Mapping from criteria to LDAP attributes
    :param exact: bool -- Match attributes values exactly if ``True``,
                  othewise perform substring matching.
    :return: str -- Valid LDAP search filter.
    """

    assertions = convert_app_data(criteria, mapping or {})
    assert_templates = [
        _build_assert_template(value, exact)
        for _, value in iteritems(assertions)
    ]
    assertions = [(k, v) for k, values in iteritems(assertions) if k and values
                  for v in values]
    if not assertions:
        return None
    filter_template = '(&{}{})'.format("".join(assert_templates), type_filter)
    return filter_format(filter_template, (item for assertion in assertions
                                           for item in assertion))
Ejemplo n.º 23
0
def test_validate_provider_map(valid, auth_providers, identity_providers,
                               provider_map):
    state = _MultipassState(None, None)
    state.auth_providers = {x: {} for x in auth_providers}
    state.identity_providers = {x: {} for x in identity_providers}
    state.provider_map = {
        a: [{
            'identity_provider': u
        }]
        for a, u in iteritems(provider_map)
    }
    if valid:
        validate_provider_map(state)
    else:
        pytest.raises(ValueError, validate_provider_map, state)
Ejemplo n.º 24
0
 def set_defaults(self):
     self.ldap_settings.setdefault('timeout', 30)
     self.ldap_settings.setdefault('verify_cert', True)
     self.ldap_settings.setdefault('cert_file',
                                   certifi.where() if certifi else None)
     self.ldap_settings.setdefault('starttls', False)
     self.ldap_settings.setdefault('page_size', 1000)
     self.ldap_settings.setdefault('uid', 'uid')
     self.ldap_settings.setdefault('user_filter', '(objectClass=person)')
     if not self.ldap_settings['cert_file'] and self.ldap_settings[
             'verify_cert']:
         warn(
             "You should install certifi or provide a certificate file in order to verify the LDAP certificate."
         )
     # Convert LDAP settings to bytes since python-ldap chokes on unicode strings
     for key, value in iteritems(self.ldap_settings):
         if isinstance(value, unicode):
             self.ldap_settings[key] = bytes(value)
Ejemplo n.º 25
0
    def _create_providers(self, key, base):
        """Instantiates all providers

        :param key: The key to insert into the config option name
                    ``MULTIPASS_*_PROVIDERS``
        :param base: The base class of the provider type.
        """
        registry = self.provider_registry[AuthProvider if key == 'AUTH' else IdentityProvider]
        providers = {}
        provider_classes = set()
        for name, settings in iteritems(current_app.config['MULTIPASS_{}_PROVIDERS'.format(key)]):
            settings = settings.copy()
            cls = resolve_provider_type(base, settings.pop('type'), registry)
            if not cls.multi_instance and cls in provider_classes:
                raise RuntimeError('Provider does not support multiple instances: ' + cls.__name__)
            providers[name] = cls(self, name, settings)
            provider_classes.add(cls)
        return providers
Ejemplo n.º 26
0
    def _create_providers(self, key, base):
        """Instantiates all providers

        :param key: The key to insert into the config option name
                    ``MULTIPASS_*_PROVIDERS``
        :param base: The base class of the provider type.
        """
        registry = self.provider_registry[AuthProvider if key == 'AUTH' else IdentityProvider]
        providers = {}
        provider_classes = set()
        for name, settings in iteritems(current_app.config['MULTIPASS_{}_PROVIDERS'.format(key)]):
            settings = settings.copy()
            cls = resolve_provider_type(base, settings.pop('type'), registry)
            if not cls.multi_instance and cls in provider_classes:
                raise RuntimeError('Provider does not support multiple instances: ' + cls.__name__)
            providers[name] = cls(self, name, settings)
            provider_classes.add(cls)
        return providers
Ejemplo n.º 27
0
    def _shibboleth_callback(self):
        mapping = _lower_keys(
            iteritems(
                request.headers if self.from_headers else request.environ))
        # get all attrs in the 'attrs' list, if empty use 'attrs_prefix'
        if self.attrs is None:
            attributes = {
                k: _to_unicode(v)
                for k, v in mapping if k.startswith(self.attrs_prefix)
            }
        else:
            attributes = {
                k: _to_unicode(v)
                for k, v in mapping if k in self.attrs
            }

        if not attributes:
            raise AuthenticationFailed("No valid data received", provider=self)
        return self.multipass.handle_auth_success(AuthInfo(self, **attributes))
Ejemplo n.º 28
0
 def __new__(mcs, name, bases, dct):
     cls = type.__new__(mcs, name, bases, dct)
     base = next((x for x in reversed(getmro(cls)) if type(x) is mcs and x is not cls), None)
     if base is None:
         return cls
     for attr, methods in iteritems(base.__support_attrs__):
         if isinstance(methods, string_types):
             methods = methods,
         if isinstance(attr, tuple):
             supported = attr[0](cls)
             message = attr[1]
         else:
             supported = getattr(cls, attr, getattr(base, attr))
             message = '{} is True'.format(attr)
         for method in methods:
             is_overridden = (getattr(base, method) != getattr(cls, method))
             if not supported and is_overridden:
                 raise TypeError('{} cannot override {} unless {}'.format(name, method, message))
             elif supported and not is_overridden:
                 raise TypeError('{} must override {} if {}'.format(name, method, message))
     return cls
Ejemplo n.º 29
0
 def __new__(mcs, name, bases, dct):
     cls = type.__new__(mcs, name, bases, dct)
     base = next((x for x in reversed(getmro(cls))
                  if type(x) is mcs and x is not cls), None)
     if base is None:
         return cls
     for attr, methods in iteritems(base.__support_attrs__):
         if isinstance(methods, string_types):
             methods = methods,
         if isinstance(attr, tuple):
             supported = attr[0](cls)
             message = attr[1]
         else:
             supported = getattr(cls, attr, getattr(base, attr))
             message = '{} is True'.format(attr)
         for method in methods:
             is_overridden = (getattr(base, method) != getattr(cls, method))
             if not supported and is_overridden:
                 raise TypeError('{} cannot override {} unless {}'.format(
                     name, method, message))
             elif supported and not is_overridden:
                 raise TypeError('{} must override {} if {}'.format(
                     name, method, message))
     return cls
Ejemplo n.º 30
0
def to_unicode(data):
    return {text_type(k): [x.decode('utf-8', 'replace') for x in v] for k, v in iteritems(data)}
Ejemplo n.º 31
0
def to_unicode(data):
    return {
        text_type(k): [x.decode('utf-8', 'replace') for x in v]
        for k, v in iteritems(data)
    }
Ejemplo n.º 32
0
 def _shibboleth_callback(self):
     attributes = {k: v for k, v in iteritems(request.environ) if k.startswith(self.settings['attrs_prefix'])}
     if not attributes:
         raise AuthenticationFailed("No valid data received")
     return self.multipass.handle_auth_success(AuthInfo(self, **attributes))