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