fix "exclude" operations
[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.test import TestCase
36
37 import ldap
38 import ldapdb
39 from examples.models import LdapUser, LdapGroup
40
41 class BaseTestCase(TestCase):
42     def setUp(self):
43         cursor = ldapdb.connection._cursor()
44         for dn in [LdapGroup.base_dn, LdapUser.base_dn]:
45             rdn = dn.split(',')[0]
46             key, val = rdn.split('=')
47             attrs = [('objectClass', ['top', 'organizationalUnit']), (key, [val])]
48             try:
49                 cursor.connection.add_s(dn, attrs)
50             except ldap.ALREADY_EXISTS:
51                 pass
52
53     def tearDown(self):
54         cursor = ldapdb.connection._cursor()
55         for base in [LdapGroup.base_dn, LdapUser.base_dn]:
56             try:
57                 results = cursor.connection.search_s(base, ldap.SCOPE_SUBTREE)
58                 for dn, attrs in reversed(results):
59                     cursor.connection.delete_s(dn)
60             except ldap.NO_SUCH_OBJECT:
61                 pass
62
63 class GroupTestCase(BaseTestCase):
64     def setUp(self):
65         super(GroupTestCase, self).setUp()
66
67         g = LdapGroup()
68         g.name = "foogroup"
69         g.gid = 1000
70         g.usernames = ['foouser', 'baruser']
71         g.save()
72
73         g = LdapGroup()
74         g.name = "bargroup"
75         g.gid = 1001
76         g.usernames = ['zoouser', 'baruser']
77         g.save()
78
79         g = LdapGroup()
80         g.name = "wizgroup"
81         g.gid = 1002
82         g.usernames = ['wizuser', 'baruser']
83         g.save()
84
85     def test_count(self):
86         # empty query
87         qs = LdapGroup.objects.none()
88         self.assertEquals(qs.count(), 0)
89
90         qs = LdapGroup.objects.none()
91         self.assertEquals(len(qs), 0)
92
93         # all query
94         qs = LdapGroup.objects.all()
95         self.assertEquals(qs.count(), 3)
96
97         qs = LdapGroup.objects.all()
98         self.assertEquals(len(qs), 3)
99
100     def test_ldap_filter(self):
101         qs = LdapGroup.objects.filter(name='foogroup')
102         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(cn=foogroup))')
103
104         qs = LdapGroup.objects.filter(name='foogroup', gid=1000)
105         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(&(gidNumber=1000)(cn=foogroup)))')
106
107         qs = LdapGroup.objects.exclude(name='foogroup')
108         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(!(cn=foogroup)))')
109         
110         qs = LdapGroup.objects.exclude(name='foogroup', gid=1000)
111         self.assertEquals(qs.query._ldap_filter(), '(&(objectClass=posixGroup)(!(&(gidNumber=1000)(cn=foogroup))))')
112
113     def test_filter(self):
114         qs = LdapGroup.objects.filter(name='foogroup')
115         self.assertEquals(qs.count(), 1)
116
117         qs = LdapGroup.objects.filter(name='foogroup')
118         self.assertEquals(len(qs), 1)
119
120         g = qs[0]
121         self.assertEquals(g.dn, 'cn=foogroup,%s' % LdapGroup.base_dn)
122         self.assertEquals(g.name, 'foogroup')
123         self.assertEquals(g.gid, 1000)
124         self.assertEquals(g.usernames, ['foouser', 'baruser'])
125
126         # try to filter non-existent entries
127         qs = LdapGroup.objects.filter(name='does_not_exist')
128         self.assertEquals(qs.count(), 0)
129
130         qs = LdapGroup.objects.filter(name='does_not_exist')
131         self.assertEquals(len(qs), 0)
132
133     def test_get(self):
134         g = LdapGroup.objects.get(name='foogroup')
135         self.assertEquals(g.dn, 'cn=foogroup,%s' % LdapGroup.base_dn)
136         self.assertEquals(g.name, 'foogroup')
137         self.assertEquals(g.gid, 1000)
138         self.assertEquals(g.usernames, ['foouser', 'baruser'])
139
140         # try to get a non-existent entry
141         self.assertRaises(LdapGroup.DoesNotExist, LdapGroup.objects.get, name='does_not_exist')
142
143     def test_order_by(self):
144         # ascending name 
145         qs = LdapGroup.objects.order_by('name')
146         self.assertEquals(len(qs), 3)
147         self.assertEquals(qs[0].name, 'bargroup')
148         self.assertEquals(qs[1].name, 'foogroup')
149         self.assertEquals(qs[2].name, 'wizgroup')
150
151         # descending name 
152         qs = LdapGroup.objects.order_by('-name')
153         self.assertEquals(len(qs), 3)
154         self.assertEquals(qs[0].name, 'wizgroup')
155         self.assertEquals(qs[1].name, 'foogroup')
156         self.assertEquals(qs[2].name, 'bargroup')
157
158         # ascending gid
159         qs = LdapGroup.objects.order_by('gid')
160         self.assertEquals(len(qs), 3)
161         self.assertEquals(qs[0].gid, 1000)
162         self.assertEquals(qs[1].gid, 1001)
163         self.assertEquals(qs[2].gid, 1002)
164
165         # descending gid
166         qs = LdapGroup.objects.order_by('-gid')
167         self.assertEquals(len(qs), 3)
168         self.assertEquals(qs[0].gid, 1002)
169         self.assertEquals(qs[1].gid, 1001)
170         self.assertEquals(qs[2].gid, 1000)
171
172     def test_bulk_delete(self):
173         LdapGroup.objects.all().delete()
174
175         qs = LdapGroup.objects.all()
176         self.assertEquals(len(qs), 0)
177
178     def test_slice(self):
179         qs = LdapGroup.objects.all()
180         objs = list(qs)
181         self.assertEquals(len(objs), 3)
182         self.assertEquals(objs[0].gid, 1000)
183         self.assertEquals(objs[1].gid, 1001)
184         self.assertEquals(objs[2].gid, 1002)
185
186         # limit only
187         qs = LdapGroup.objects.all()
188         objs = qs[:2]
189         self.assertEquals(objs.count(), 2)
190
191         objs = qs[:2]
192         self.assertEquals(len(objs), 2)
193         self.assertEquals(objs[0].gid, 1000)
194         self.assertEquals(objs[1].gid, 1001)
195
196         # offset only
197         qs = LdapGroup.objects.all()
198         objs = qs[1:]
199         self.assertEquals(objs.count(), 2)
200
201         objs = qs[1:]
202         self.assertEquals(len(objs), 2)
203         self.assertEquals(objs[0].gid, 1001)
204         self.assertEquals(objs[1].gid, 1002)
205
206         # offset and limit
207         qs = LdapGroup.objects.all()
208         objs = qs[1:2]
209         self.assertEquals(objs.count(), 1)
210
211         objs = qs[1:2]
212         self.assertEquals(len(objs), 1)
213         self.assertEquals(objs[0].gid, 1001)
214
215     def test_update(self):
216         g = LdapGroup.objects.get(name='foogroup')
217
218         g.gid = 1002
219         g.usernames = ['foouser2', 'baruser2']
220         g.save()
221
222         # make sure DN gets updated if we change the pk
223         g.name = 'foogroup2'
224         g.save()
225         self.assertEquals(g.dn, 'cn=foogroup2,%s' % LdapGroup.base_dn)
226
227     def test_values(self):
228         qs = LdapGroup.objects.values('name')
229         self.assertEquals(len(qs), 3)
230         self.assertEquals(qs[0], {'name': 'foogroup'})
231         self.assertEquals(qs[1], {'name': 'bargroup'})
232         self.assertEquals(qs[2], {'name': 'wizgroup'})
233
234     def test_values_list(self):
235         qs = LdapGroup.objects.values_list('name')
236         self.assertEquals(len(qs), 3)
237         self.assertEquals(qs[0], ('foogroup',))
238         self.assertEquals(qs[1], ('bargroup',))
239         self.assertEquals(qs[2], ('wizgroup',))
240
241     def test_delete(self):
242         g = LdapGroup.objects.get(name='foogroup')
243         g.delete()
244
245         qs = LdapGroup.objects.all()
246         self.assertEquals(len(qs), 2)
247
248 class UserTestCase(BaseTestCase):
249     def setUp(self):
250         super(UserTestCase, self).setUp()
251
252         u = LdapUser()
253         u.first_name = u"Fôo"
254         u.last_name = u"Usér"
255         u.full_name = u"Fôo Usér"
256
257         u.group = 1000
258         u.home_directory = "/home/foouser"
259         u.uid = 2000
260         u.username = "foouser"
261         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'
262         u.save()
263
264     def test_get(self):
265         u = LdapUser.objects.get(username='foouser')
266         self.assertEquals(u.first_name, u'Fôo')
267         self.assertEquals(u.last_name, u'Usér')
268         self.assertEquals(u.full_name, u'Fôo Usér')
269
270         self.assertEquals(u.group, 1000)
271         self.assertEquals(u.home_directory, '/home/foouser')
272         self.assertEquals(u.uid, 2000)
273         self.assertEquals(u.username, 'foouser')
274         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')
275
276         self.assertRaises(LdapUser.DoesNotExist, LdapUser.objects.get, username='does_not_exist')
277
278     def test_update(self):
279         u = LdapUser.objects.get(username='foouser')
280         u.first_name = u'Fôo2'
281         u.save()
282         
283         # make sure DN gets updated if we change the pk
284         u.username = 'foouser2'
285         u.save()
286         self.assertEquals(u.dn, 'uid=foouser2,%s' % LdapUser.base_dn)
287
288 class ScopedTestCase(BaseTestCase):
289     def setUp(self):
290         super(ScopedTestCase, self).setUp()
291
292         cursor = ldapdb.connection._cursor()
293         self.scoped_dn = "ou=contacts,%s" % LdapGroup.base_dn
294         attrs = [('objectClass', ['top', 'organizationalUnit']), ("ou", ["contacts"])]
295         cursor.connection.add_s(self.scoped_dn, attrs)
296
297     def test_scope(self):
298         ScopedGroup = LdapGroup.scoped(self.scoped_dn)
299
300         # create group
301         g = LdapGroup()
302         g.name = "foogroup"
303         g.gid = 1000
304         g.save()
305
306         qs = LdapGroup.objects.all()
307         self.assertEquals(qs.count(), 1)
308
309         qs = ScopedGroup.objects.all()
310         self.assertEquals(qs.count(), 0)
311
312         # create scoped group
313         g2 = ScopedGroup()
314         g2.name = "scopedgroup"
315         g2.gid = 5000
316         g2.save()
317
318         qs = LdapGroup.objects.all()
319         self.assertEquals(qs.count(), 2)
320
321         qs = ScopedGroup.objects.all()
322         self.assertEquals(qs.count(), 1)
323
324 class AdminTestCase(BaseTestCase):
325     fixtures = ['test_users.json']
326
327     def setUp(self):
328         super(AdminTestCase, self).setUp()
329
330         g = LdapGroup()
331         g.name = "foogroup"
332         g.gid = 1000
333         g.usernames = ['foouser', 'baruser']
334         g.save()
335
336         g = LdapGroup()
337         g.name = "bargroup"
338         g.gid = 1001
339         g.usernames = ['zoouser', 'baruser']
340         g.save()
341
342         u = LdapUser()
343         u.first_name = "Foo"
344         u.last_name = "User"
345         u.full_name = "Foo User"
346         u.group = 1000
347         u.home_directory = "/home/foouser"
348         u.uid = 2000
349         u.username = "foouser"
350         u.save()
351
352         u = LdapUser()
353         u.first_name = "Bar"
354         u.last_name = "User"
355         u.full_name = "Bar User"
356         u.group = 1001
357         u.home_directory = "/home/baruser"
358         u.uid = 2001
359         u.username = "baruser"
360         u.save()
361
362         self.client.login(username="test_user", password="password")
363
364     def test_index(self):
365         response = self.client.get('/admin/examples/')
366         self.assertContains(response, "Ldap groups")
367         self.assertContains(response, "Ldap users")
368
369     def test_group_list(self):
370         response = self.client.get('/admin/examples/ldapgroup/')
371         self.assertContains(response, "Ldap groups")
372         self.assertContains(response, "foogroup")
373         self.assertContains(response, "1000")
374
375         # order by name
376         response = self.client.get('/admin/examples/ldapgroup/?o=1')
377         self.assertContains(response, "Ldap groups")
378         self.assertContains(response, "foogroup")
379         self.assertContains(response, "1000")
380
381         # order by gid
382         response = self.client.get('/admin/examples/ldapgroup/?o=2')
383         self.assertContains(response, "Ldap groups")
384         self.assertContains(response, "foogroup")
385         self.assertContains(response, "1000")
386
387     def test_group_detail(self):
388         response = self.client.get('/admin/examples/ldapgroup/foogroup/')
389         self.assertContains(response, "foogroup")
390         self.assertContains(response, "1000")
391
392     def test_group_add(self):
393         response = self.client.post('/admin/examples/ldapgroup/add/', {'gid': '1002', 'name': 'wizgroup'})
394         self.assertRedirects(response, '/admin/examples/ldapgroup/')
395         qs = LdapGroup.objects.all()
396         self.assertEquals(qs.count(), 3)
397
398     def test_group_delete(self):
399         response = self.client.post('/admin/examples/ldapgroup/foogroup/delete/', {'yes': 'post'})
400         self.assertRedirects(response, '/admin/examples/ldapgroup/')
401         qs = LdapGroup.objects.all()
402         self.assertEquals(qs.count(), 1)
403
404     def test_group_search(self):
405         response = self.client.get('/admin/examples/ldapgroup/?q=foo')
406         self.assertContains(response, "Ldap groups")
407         self.assertContains(response, "foogroup")
408         self.assertContains(response, "1000")
409
410     def test_user_list(self):
411         response = self.client.get('/admin/examples/ldapuser/')
412         self.assertContains(response, "Ldap users")
413         self.assertContains(response, "foouser")
414         self.assertContains(response, "2000")
415
416         # order by username
417         response = self.client.get('/admin/examples/ldapuser/?o=1')
418         self.assertContains(response, "Ldap users")
419         self.assertContains(response, "foouser")
420         self.assertContains(response, "2000")
421
422         # order by uid
423         response = self.client.get('/admin/examples/ldapuser/?o=2')
424         self.assertContains(response, "Ldap users")
425         self.assertContains(response, "foouser")
426         self.assertContains(response, "2000")
427
428     def test_user_detail(self):
429         response = self.client.get('/admin/examples/ldapuser/foouser/')
430         self.assertContains(response, "foouser")
431         self.assertContains(response, "2000")
432
433     def test_user_delete(self):
434         response = self.client.post('/admin/examples/ldapuser/foouser/delete/', {'yes': 'post'})
435         self.assertRedirects(response, '/admin/examples/ldapuser/')
436