add more filter tests
[matthijs/upstream/django-ldapdb.git] / examples / tests.py
1 # -*- coding: utf-8 -*-
2
3 # django-ldapdb
4 # Copyright (c) 2009-2010, Bolloré telecom
5 # All rights reserved.
6
7 # See AUTHORS file for a full list of contributors.
8
9 # Redistribution and use in source and binary forms, with or without modification,
10 # are permitted provided that the following conditions are met:
11
12 #     1. Redistributions of source code must retain the above copyright notice, 
13 #        this list of conditions and the following disclaimer.
14 #     
15 #     2. Redistributions in binary form must reproduce the above copyright 
16 #        notice, this list of conditions and the following disclaimer in the
17 #        documentation and/or other materials provided with the distribution.
18
19 #     3. Neither the name of Bolloré telecom nor the names of its contributors
20 #        may be used to endorse or promote products derived from this software
21 #        without specific prior written permission.
22
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #
34
35 from django.db.models import Q
36 from django.test import TestCase
37
38 import ldap
39 import ldapdb
40 from examples.models import LdapUser, LdapGroup
41
42 class BaseTestCase(TestCase):
43     def setUp(self):
44         cursor = ldapdb.connection._cursor()
45         for dn in [LdapGroup.base_dn, LdapUser.base_dn]:
46             rdn = dn.split(',')[0]
47             key, val = rdn.split('=')
48             attrs = [('objectClass', ['top', 'organizationalUnit']), (key, [val])]
49             try:
50                 cursor.connection.add_s(dn, attrs)
51             except ldap.ALREADY_EXISTS:
52                 pass
53
54     def tearDown(self):
55         cursor = ldapdb.connection._cursor()
56         for base in [LdapGroup.base_dn, LdapUser.base_dn]:
57             try:
58                 results = cursor.connection.search_s(base, ldap.SCOPE_SUBTREE)
59                 for dn, attrs in reversed(results):
60                     cursor.connection.delete_s(dn)
61             except ldap.NO_SUCH_OBJECT:
62                 pass
63
64 class GroupTestCase(BaseTestCase):
65     def setUp(self):
66         super(GroupTestCase, self).setUp()
67
68         g = LdapGroup()
69         g.name = "foogroup"
70         g.gid = 1000
71         g.usernames = ['foouser', 'baruser']
72         g.save()
73
74         g = LdapGroup()
75         g.name = "bargroup"
76         g.gid = 1001
77         g.usernames = ['zoouser', 'baruser']
78         g.save()
79
80         g = LdapGroup()
81         g.name = "wizgroup"
82         g.gid = 1002
83         g.usernames = ['wizuser', 'baruser']
84         g.save()
85
86     def test_count(self):
87         # empty query
88         qs = LdapGroup.objects.none()
89         self.assertEquals(qs.count(), 0)
90
91         qs = LdapGroup.objects.none()
92         self.assertEquals(len(qs), 0)
93
94         # all query
95         qs = LdapGroup.objects.all()
96         self.assertEquals(qs.count(), 3)
97
98         qs = LdapGroup.objects.all()
99         self.assertEquals(len(qs), 3)
100
101     def test_ldap_filter(self):
102         # single filter
103         qs = LdapGroup.objects.filter(name='foogroup')
104         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(cn=foogroup))')
105
106         qs = LdapGroup.objects.filter(Q(name='foogroup'))
107         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(cn=foogroup))')
108
109         # AND filter
110         qs = LdapGroup.objects.filter(gid=1000, name='foogroup')
111         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(&(gidNumber=1000)(cn=foogroup)))')
112
113         qs = LdapGroup.objects.filter(Q(gid=1000) & Q(name='foogroup'))
114         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(&(gidNumber=1000)(cn=foogroup)))')
115
116         # OR filter
117         qs = LdapGroup.objects.filter(Q(gid=1000) | Q(name='foogroup'))
118         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(|(gidNumber=1000)(cn=foogroup)))')
119
120         # single exclusion
121         qs = LdapGroup.objects.exclude(name='foogroup')
122         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(!(cn=foogroup)))')
123         
124         qs = LdapGroup.objects.filter(~Q(name='foogroup'))
125         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(!(cn=foogroup)))')
126
127         # multiple exclusion
128         qs = LdapGroup.objects.exclude(name='foogroup', gid=1000)
129         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(!(&(gidNumber=1000)(cn=foogroup))))')
130
131         qs = LdapGroup.objects.filter(name='foogroup').exclude(gid=1000)
132         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(&(cn=foogroup)(!(gidNumber=1000))))')
133
134     def test_filter(self):
135         qs = LdapGroup.objects.filter(name='foogroup')
136         self.assertEquals(qs.count(), 1)
137
138         qs = LdapGroup.objects.filter(name='foogroup')
139         self.assertEquals(len(qs), 1)
140
141         g = qs[0]
142         self.assertEquals(g.dn, 'cn=foogroup,%s' % LdapGroup.base_dn)
143         self.assertEquals(g.name, 'foogroup')
144         self.assertEquals(g.gid, 1000)
145         self.assertEquals(g.usernames, ['foouser', 'baruser'])
146
147         # try to filter non-existent entries
148         qs = LdapGroup.objects.filter(name='does_not_exist')
149         self.assertEquals(qs.count(), 0)
150
151         qs = LdapGroup.objects.filter(name='does_not_exist')
152         self.assertEquals(len(qs), 0)
153
154     def test_get(self):
155         g = LdapGroup.objects.get(name='foogroup')
156         self.assertEquals(g.dn, 'cn=foogroup,%s' % LdapGroup.base_dn)
157         self.assertEquals(g.name, 'foogroup')
158         self.assertEquals(g.gid, 1000)
159         self.assertEquals(g.usernames, ['foouser', 'baruser'])
160
161         # try to get a non-existent entry
162         self.assertRaises(LdapGroup.DoesNotExist, LdapGroup.objects.get, name='does_not_exist')
163
164     def test_order_by(self):
165         # ascending name 
166         qs = LdapGroup.objects.order_by('name')
167         self.assertEquals(len(qs), 3)
168         self.assertEquals(qs[0].name, 'bargroup')
169         self.assertEquals(qs[1].name, 'foogroup')
170         self.assertEquals(qs[2].name, 'wizgroup')
171
172         # descending name 
173         qs = LdapGroup.objects.order_by('-name')
174         self.assertEquals(len(qs), 3)
175         self.assertEquals(qs[0].name, 'wizgroup')
176         self.assertEquals(qs[1].name, 'foogroup')
177         self.assertEquals(qs[2].name, 'bargroup')
178
179         # ascending gid
180         qs = LdapGroup.objects.order_by('gid')
181         self.assertEquals(len(qs), 3)
182         self.assertEquals(qs[0].gid, 1000)
183         self.assertEquals(qs[1].gid, 1001)
184         self.assertEquals(qs[2].gid, 1002)
185
186         # descending gid
187         qs = LdapGroup.objects.order_by('-gid')
188         self.assertEquals(len(qs), 3)
189         self.assertEquals(qs[0].gid, 1002)
190         self.assertEquals(qs[1].gid, 1001)
191         self.assertEquals(qs[2].gid, 1000)
192
193     def test_bulk_delete(self):
194         LdapGroup.objects.all().delete()
195
196         qs = LdapGroup.objects.all()
197         self.assertEquals(len(qs), 0)
198
199     def test_slice(self):
200         qs = LdapGroup.objects.all()
201         objs = list(qs)
202         self.assertEquals(len(objs), 3)
203         self.assertEquals(objs[0].gid, 1000)
204         self.assertEquals(objs[1].gid, 1001)
205         self.assertEquals(objs[2].gid, 1002)
206
207         # limit only
208         qs = LdapGroup.objects.all()
209         objs = qs[:2]
210         self.assertEquals(objs.count(), 2)
211
212         objs = qs[:2]
213         self.assertEquals(len(objs), 2)
214         self.assertEquals(objs[0].gid, 1000)
215         self.assertEquals(objs[1].gid, 1001)
216
217         # offset only
218         qs = LdapGroup.objects.all()
219         objs = qs[1:]
220         self.assertEquals(objs.count(), 2)
221
222         objs = qs[1:]
223         self.assertEquals(len(objs), 2)
224         self.assertEquals(objs[0].gid, 1001)
225         self.assertEquals(objs[1].gid, 1002)
226
227         # offset and limit
228         qs = LdapGroup.objects.all()
229         objs = qs[1:2]
230         self.assertEquals(objs.count(), 1)
231
232         objs = qs[1:2]
233         self.assertEquals(len(objs), 1)
234         self.assertEquals(objs[0].gid, 1001)
235
236     def test_update(self):
237         g = LdapGroup.objects.get(name='foogroup')
238
239         g.gid = 1002
240         g.usernames = ['foouser2', 'baruser2']
241         g.save()
242
243         # make sure DN gets updated if we change the pk
244         g.name = 'foogroup2'
245         g.save()
246         self.assertEquals(g.dn, 'cn=foogroup2,%s' % LdapGroup.base_dn)
247
248     def test_values(self):
249         qs = LdapGroup.objects.values('name')
250         self.assertEquals(len(qs), 3)
251         self.assertEquals(qs[0], {'name': 'foogroup'})
252         self.assertEquals(qs[1], {'name': 'bargroup'})
253         self.assertEquals(qs[2], {'name': 'wizgroup'})
254
255     def test_values_list(self):
256         qs = LdapGroup.objects.values_list('name')
257         self.assertEquals(len(qs), 3)
258         self.assertEquals(qs[0], ('foogroup',))
259         self.assertEquals(qs[1], ('bargroup',))
260         self.assertEquals(qs[2], ('wizgroup',))
261
262     def test_delete(self):
263         g = LdapGroup.objects.get(name='foogroup')
264         g.delete()
265
266         qs = LdapGroup.objects.all()
267         self.assertEquals(len(qs), 2)
268
269 class UserTestCase(BaseTestCase):
270     def setUp(self):
271         super(UserTestCase, self).setUp()
272
273         u = LdapUser()
274         u.first_name = u"Fôo"
275         u.last_name = u"Usér"
276         u.full_name = u"Fôo Usér"
277
278         u.group = 1000
279         u.home_directory = "/home/foouser"
280         u.uid = 2000
281         u.username = "foouser"
282         u.photo = '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xfe\x00\x1cCreated with GIMP on a Mac\xff\xdb\x00C\x00\x05\x03\x04\x04\x04\x03\x05\x04\x04\x04\x05\x05\x05\x06\x07\x0c\x08\x07\x07\x07\x07\x0f\x0b\x0b\t\x0c\x11\x0f\x12\x12\x11\x0f\x11\x11\x13\x16\x1c\x17\x13\x14\x1a\x15\x11\x11\x18!\x18\x1a\x1d\x1d\x1f\x1f\x1f\x13\x17"$"\x1e$\x1c\x1e\x1f\x1e\xff\xdb\x00C\x01\x05\x05\x05\x07\x06\x07\x0e\x08\x08\x0e\x1e\x14\x11\x14\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\xff\xc0\x00\x11\x08\x00\x08\x00\x08\x03\x01"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x19\x10\x00\x03\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x06\x11A\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\x9d\xf29wU5Q\xd6\xfd\x00\x01\xff\xd9'
283         u.save()
284
285     def test_get(self):
286         u = LdapUser.objects.get(username='foouser')
287         self.assertEquals(u.first_name, u'Fôo')
288         self.assertEquals(u.last_name, u'Usér')
289         self.assertEquals(u.full_name, u'Fôo Usér')
290
291         self.assertEquals(u.group, 1000)
292         self.assertEquals(u.home_directory, '/home/foouser')
293         self.assertEquals(u.uid, 2000)
294         self.assertEquals(u.username, 'foouser')
295         self.assertEquals(u.photo, '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xfe\x00\x1cCreated with GIMP on a Mac\xff\xdb\x00C\x00\x05\x03\x04\x04\x04\x03\x05\x04\x04\x04\x05\x05\x05\x06\x07\x0c\x08\x07\x07\x07\x07\x0f\x0b\x0b\t\x0c\x11\x0f\x12\x12\x11\x0f\x11\x11\x13\x16\x1c\x17\x13\x14\x1a\x15\x11\x11\x18!\x18\x1a\x1d\x1d\x1f\x1f\x1f\x13\x17"$"\x1e$\x1c\x1e\x1f\x1e\xff\xdb\x00C\x01\x05\x05\x05\x07\x06\x07\x0e\x08\x08\x0e\x1e\x14\x11\x14\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\xff\xc0\x00\x11\x08\x00\x08\x00\x08\x03\x01"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x19\x10\x00\x03\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x06\x11A\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\x9d\xf29wU5Q\xd6\xfd\x00\x01\xff\xd9')
296
297         self.assertRaises(LdapUser.DoesNotExist, LdapUser.objects.get, username='does_not_exist')
298
299     def test_update(self):
300         u = LdapUser.objects.get(username='foouser')
301         u.first_name = u'Fôo2'
302         u.save()
303         
304         # make sure DN gets updated if we change the pk
305         u.username = 'foouser2'
306         u.save()
307         self.assertEquals(u.dn, 'uid=foouser2,%s' % LdapUser.base_dn)
308
309 class ScopedTestCase(BaseTestCase):
310     def setUp(self):
311         super(ScopedTestCase, self).setUp()
312
313         cursor = ldapdb.connection._cursor()
314         self.scoped_dn = "ou=contacts,%s" % LdapGroup.base_dn
315         attrs = [('objectClass', ['top', 'organizationalUnit']), ("ou", ["contacts"])]
316         cursor.connection.add_s(self.scoped_dn, attrs)
317
318     def test_scope(self):
319         ScopedGroup = LdapGroup.scoped(self.scoped_dn)
320
321         # create group
322         g = LdapGroup()
323         g.name = "foogroup"
324         g.gid = 1000
325         g.save()
326
327         qs = LdapGroup.objects.all()
328         self.assertEquals(qs.count(), 1)
329
330         qs = ScopedGroup.objects.all()
331         self.assertEquals(qs.count(), 0)
332
333         # create scoped group
334         g2 = ScopedGroup()
335         g2.name = "scopedgroup"
336         g2.gid = 5000
337         g2.save()
338
339         qs = LdapGroup.objects.all()
340         self.assertEquals(qs.count(), 2)
341
342         qs = ScopedGroup.objects.all()
343         self.assertEquals(qs.count(), 1)
344
345 class AdminTestCase(BaseTestCase):
346     fixtures = ['test_users.json']
347
348     def setUp(self):
349         super(AdminTestCase, self).setUp()
350
351         g = LdapGroup()
352         g.name = "foogroup"
353         g.gid = 1000
354         g.usernames = ['foouser', 'baruser']
355         g.save()
356
357         g = LdapGroup()
358         g.name = "bargroup"
359         g.gid = 1001
360         g.usernames = ['zoouser', 'baruser']
361         g.save()
362
363         u = LdapUser()
364         u.first_name = "Foo"
365         u.last_name = "User"
366         u.full_name = "Foo User"
367         u.group = 1000
368         u.home_directory = "/home/foouser"
369         u.uid = 2000
370         u.username = "foouser"
371         u.save()
372
373         u = LdapUser()
374         u.first_name = "Bar"
375         u.last_name = "User"
376         u.full_name = "Bar User"
377         u.group = 1001
378         u.home_directory = "/home/baruser"
379         u.uid = 2001
380         u.username = "baruser"
381         u.save()
382
383         self.client.login(username="test_user", password="password")
384
385     def test_index(self):
386         response = self.client.get('/admin/examples/')
387         self.assertContains(response, "Ldap groups")
388         self.assertContains(response, "Ldap users")
389
390     def test_group_list(self):
391         response = self.client.get('/admin/examples/ldapgroup/')
392         self.assertContains(response, "Ldap groups")
393         self.assertContains(response, "foogroup")
394         self.assertContains(response, "1000")
395
396         # order by name
397         response = self.client.get('/admin/examples/ldapgroup/?o=1')
398         self.assertContains(response, "Ldap groups")
399         self.assertContains(response, "foogroup")
400         self.assertContains(response, "1000")
401
402         # order by gid
403         response = self.client.get('/admin/examples/ldapgroup/?o=2')
404         self.assertContains(response, "Ldap groups")
405         self.assertContains(response, "foogroup")
406         self.assertContains(response, "1000")
407
408     def test_group_detail(self):
409         response = self.client.get('/admin/examples/ldapgroup/foogroup/')
410         self.assertContains(response, "foogroup")
411         self.assertContains(response, "1000")
412
413     def test_group_add(self):
414         response = self.client.post('/admin/examples/ldapgroup/add/', {'gid': '1002', 'name': 'wizgroup'})
415         self.assertRedirects(response, '/admin/examples/ldapgroup/')
416         qs = LdapGroup.objects.all()
417         self.assertEquals(qs.count(), 3)
418
419     def test_group_delete(self):
420         response = self.client.post('/admin/examples/ldapgroup/foogroup/delete/', {'yes': 'post'})
421         self.assertRedirects(response, '/admin/examples/ldapgroup/')
422         qs = LdapGroup.objects.all()
423         self.assertEquals(qs.count(), 1)
424
425     def test_group_search(self):
426         response = self.client.get('/admin/examples/ldapgroup/?q=foo')
427         self.assertContains(response, "Ldap groups")
428         self.assertContains(response, "foogroup")
429         self.assertContains(response, "1000")
430
431     def test_user_list(self):
432         response = self.client.get('/admin/examples/ldapuser/')
433         self.assertContains(response, "Ldap users")
434         self.assertContains(response, "foouser")
435         self.assertContains(response, "2000")
436
437         # order by username
438         response = self.client.get('/admin/examples/ldapuser/?o=1')
439         self.assertContains(response, "Ldap users")
440         self.assertContains(response, "foouser")
441         self.assertContains(response, "2000")
442
443         # order by uid
444         response = self.client.get('/admin/examples/ldapuser/?o=2')
445         self.assertContains(response, "Ldap users")
446         self.assertContains(response, "foouser")
447         self.assertContains(response, "2000")
448
449     def test_user_detail(self):
450         response = self.client.get('/admin/examples/ldapuser/foouser/')
451         self.assertContains(response, "foouser")
452         self.assertContains(response, "2000")
453
454     def test_user_delete(self):
455         response = self.client.post('/admin/examples/ldapuser/foouser/delete/', {'yes': 'post'})
456         self.assertRedirects(response, '/admin/examples/ldapuser/')
457