def test_or_aggregate(self):
     filt = Filter.OR([
         Filter.attribute('givenName').equal_to('bilbo'),
         Filter.attribute('sn').equal_to('baggens')
     ])
     string = filt.to_string()
     assert string == '(|(givenName=bilbo)(sn=baggens))'
Example #2
0
    def filter(self, *args, **kwargs):
        """
        If there are positional arguments, they must all be F() objects.  This
        allows us to preconstruct an unbound filter and then use it later.

        Of the Django filter suffixes we support the following:

            * ``__iexact``
            * ``__istartswith``
            * ``__iendswith``
            * ``__icontains``
            * ``__in``

        Note that only the case insensitive versions of these filters are supported.
        LDAP searches are case insensitive, so we make you use ``__i*`` versions to
        remind you of that.

        We do support one additional LDAP specific filter: ``__exists``.  This
        will cause a filter to be added that just ensures that the returned
        objects have the associated attribute.  Unlike in SQL, where every row
        contains all available columns, in LDAP, attributes can be absent
        entirely from the record.
        """
        steps = self.__validate_positional_args(args)
        for key, value in kwargs.items():
            if isinstance(value, str):
                value = value.strip()
            if key.endswith('__istartswith'):
                steps.append(Filter.attribute(self.get_attribute(key[:-13])).starts_with(value))
            elif key.endswith('__iendswith'):
                steps.append(Filter.attribute(self.get_attribute(key[:-11])).ends_with(value))
            elif key.endswith('__icontains'):
                steps.append(Filter.attribute(self.get_attribute(key[:-11])).contains(value))
            elif key.endswith('__in'):
                if not isinstance(value, list):
                    raise ValueError('When using the "__in" filter you must supply a list')
                in_steps = []
                for v in value:
                    in_steps.append(Filter.attribute(self.get_attribute(key[:-4])).equal_to(v))
                steps.append(Filter.OR(in_steps))
            elif key.endswith('__exists'):
                # This one doesn't exist as a Django field lookup
                steps.append(Filter.attribute(self.get_attribute(key[:-8])).present())
            elif key.endswith('__iexact') or '__' not in key:
                # no suffix means do an __exact
                if '__' in key:
                    key = key[:-8]
                if value is None:
                    # If value is None, we search for the absence of that
                    # attribute
                    steps.append(Filter.NOT(Filter.attribute(self.get_attribute(key))))
                else:
                    steps.append(Filter.attribute(self.get_attribute(key)).equal_to(value))
            else:
                raise F.UnknownSuffix('The search filter "{}" uses an unknown filter suffix')
        self.chain.append(Filter.AND(steps))
        return self
 def test_and_aggregate(self):
     filt = Filter.AND([
         Filter.attribute('firstName').equal_to('Alice'),
         Filter.attribute('lastName').ends_with('Chains')
     ])
     assert filt.match({'firstName': 'Alice', 'lastName': 'Chains'})
     assert filt.match({'firstName': 'Alice', 'lastName': 'In-Chains'})
     assert not filt.match({'firstName': 'Bob', 'lastName': 'Chains'})
     assert not filt.match({'firstName': 'Alice'})
 def test_parser_matching(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*))'
     parsed = Filter.parse(filt)
     test = {'sn': 'ron', 'mail': '*****@*****.**'}
     assert parsed.match(test)
     test_fail = {'sn': 'ron'}
     assert not parsed.match(test_fail)
 def test_contains(self):
     filt = Filter.attribute('sn').contains('smith')
     assert filt.match({'sn': 'smith'})
     assert filt.match({'sn': 'smith-jonson'})
     assert filt.match({'sn': 'jonson-smith'})
     assert filt.match({'sn': 'Von Ubersmith'})
     assert not filt.match({'sn': 'Jonson'})
 def test_substring_match(self):
     filt = '(sn=*sammy*)'
     parsed = Filter.parse(filt)
     assert getattr(parsed, 'type') == 'filter'
     assert getattr(parsed, 'comp') == '='
     assert getattr(parsed, 'attr') == 'sn'
     assert getattr(parsed, 'val') == '*sammy*'
 def test_less_than_numeric(self):
     filt = Filter.attribute('age').lte('10')
     assert filt.match({'age': 9})
     assert filt.match({'age': '9'})
     assert filt.match({'age': 10})
     assert filt.match({'age': '10'})
     assert not filt.match({'age': 11})
     assert not filt.match({'age': '11'})
Example #8
0
    def _filter(self):
        """
        Return a list of filters ready to be converted to a filter string.

        This means throwing an "(& )" around the list of filter components
        we've accrued.
        """
        if len(self.chain) == 0:
            raise self.NoFilterSpecified('You need to at least specify one filter in order to do LDAP searches.')
        elif len(self.chain) == 1:
            return self.chain[0]
        else:
            return Filter.AND(self.chain).simplify()
 def test_escaped_values(self):
     filt = '(o=Parens R Us \\28for all your parenthetical needs\\29)'
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == '(o=Parens R Us (for all your parenthetical needs))'
 def test_oid_attributes(self):
     filt = '(1.3.6.1.4.1.1466.115.121.1.38=picture)'
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == filt
 def test_allowed_characters(self):
     filt = '(orgUnit=%)'
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == filt
 def test_less_than_lexical(self):
     filt = Filter.attribute('name').lte('bob')
     assert filt.match({'name': 'acme'})
     assert filt.match({'name': 'bob'})
     assert not filt.match({'name': 'cell'})
 def test_allows_whitespace_no_parenthesis(self):
     filt = ' \n sn=ron '
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == '(sn=ron)'
Example #14
0
 def test_custom_indent_char_beautify(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*))'
     parsed = Filter.parse(filt)
     string = parsed.to_string(indent=2, indt_char='!')
     assert string == '(&\n!!(|\n!!!!(sn=ron)\n!!!!(sn=bob)\n!!)\n!!(mail=*)\n)'
Example #15
0
 def test_custom_indent_beautify(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*))'
     parsed = Filter.parse(filt)
     string = parsed.to_string(2)
     assert string == '(&\n  (|\n    (sn=ron)\n    (sn=bob)\n  )\n  (mail=*)\n)'
Example #16
0
 def test_default_beautify(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*))'
     parsed = Filter.parse(filt)
     string = parsed.to_string(True)
     assert string == '(&\n    (|\n        (sn=ron)\n        (sn=bob)\n    )\n    (mail=*)\n)'
Example #17
0
 def test_to_complex_concat(self):
     filt = '(&(sn=ron)(sn=bob))'
     string = Filter.parse(filt) + 'test'
     assert string == '(&(sn=ron)(sn=bob))test'
Example #18
0
 def test_to_simple_concat(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*)(!(account=disabled)))'
     string = Filter.parse(filt) + ''
     assert string == filt
Example #19
0
 def test_string_typecast(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*)(!(account=disabled)))'
     string = str(Filter.parse(filt))
     assert string == filt
 def test_no_parenthesis(self):
     filt = 'sn=ron'
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == '(sn=ron)'
 def test_simple_filter(self):
     filt = '(sn=ron)'
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == filt
 def test_simple_malformed_error(self):
     with pytest.raises(ParseError):
         filt = '(sn=sammy'
         Filter.parse(filt)
Example #23
0
 def test_unoptimized_filter(self):
     filt = '(&(|(sn=ron)(&(sn=bob)))(|(mail=*))(!(account=disabled)))'
     optimized = '(&(|(sn=ron)(sn=bob))(mail=*)(!(account=disabled)))'
     parsed = Filter.parse(filt)
     string = parsed.simplify().to_string()
     assert string == optimized
 def test_approx(self):
     filt = Filter.attribute('name').approx('ashcroft')
     assert filt.match({'name': 'Ashcroft'})
     assert filt.match({'name': 'Ashcraft'})
     assert not filt.match({'name': 'Ashsoft'})
 def test_complex_malformed_error(self):
     with pytest.raises(ParseError):
         filt = '(&(orgUnit=accounting))\n([email protected]) f'
         Filter.parse(filt)
Example #26
0
 def __or__(self, other):
     self.chain = Filter.OR([self._filter, other._filter])
     return F(manager=self.manager, f=self)
 def test_complex_filter(self):
     filt = '(&(|(sn=ron)(sn=bob))(mail=*)(!(account=disabled)))'
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == filt
 def test_equality(self):
     filt = Filter.attribute('sn').equal_to('smith')
     assert filt.match({'sn': 'smith'})
     assert filt.match({'sn': 'SMITH'})
     assert not filt.match({'sn': 'bob'})
Example #29
0
 def __and__(self, other):
     self.chain = Filter.AND([self._filter, other._filter])
     return F(manager=self.manager, f=self)
 def test_allows_whitespace(self):
     filt = ' (&  (sn=smith with spaces)(one-two<=morespaces) (objectType=object Type) \n )  '
     parsed = Filter.parse(filt)
     string = parsed.to_string()
     assert string == '(&(sn=smith with spaces)(one-two<=morespaces)(objectType=object Type))'