Merge tag '0.10.2'
[ganeti_webmgr.git] / muddle_users / tests / views / group.py
blob741de8b32f81271e895a0fc4ebbc0a4ca49e1abf
1 from django.conf import settings
2 from django.contrib.auth.models import User, Group
3 from django.test import TestCase, Client
5 from object_permissions.registration import grant, revoke
6 from object_permissions.signals import view_add_user, view_remove_user
8 from muddle_users.signals import (view_group_edited, view_group_created,
9 view_group_deleted)
11 class TestGroupViews(TestCase):
13 def setUp(self):
14 self.anonymous = User(id=1, username='anonymous')
15 self.anonymous.save()
16 settings.ANONYMOUS_USER_ID = 1
18 self.user0 = User(id=2, username='tester0')
19 self.user0.set_password('secret')
20 self.user0.save()
21 self.user1 = User(id=3, username='tester1')
22 self.user1.set_password('secret')
23 self.user1.save()
25 def tearDown(self):
26 self.anonymous.delete()
27 self.user0.delete()
28 self.user1.delete()
30 def test_save(self, name='test'):
31 """ Test saving an Group """
32 group = Group(name=name)
33 group.save()
34 return group
36 def test_view_list(self):
37 """
38 Test viewing list of Groups
39 """
40 group = self.test_save()
41 group0 = self.test_save(name='group1')
42 group1 = self.test_save(name='group2')
43 group2 = self.test_save(name='group3')
44 c = Client()
45 url = '/groups/'
47 # anonymous user
48 response = c.get(url, follow=True)
49 self.assertEqual(200, response.status_code)
50 self.assertTemplateUsed(response, 'registration/login.html')
52 # unauthorized user (user with admin on no groups)
53 self.assertTrue(c.login(username=self.user0.username, password='secret'))
54 response = c.get(url)
55 self.assertEqual(403, response.status_code)
57 # authorized (permission)
58 self.user0.grant('admin', group)
59 self.user0.grant('admin', group1)
60 response = c.get(url)
61 self.assertEqual(200, response.status_code)
62 self.assertEquals('text/html; charset=utf-8', response['content-type'])
63 self.assertTemplateUsed(response, 'group/list.html')
64 groups = response.context['groups']
65 self.assertTrue(group in groups)
66 self.assertTrue(group1 in groups)
67 self.assertEqual(2, len(groups))
69 # authorized (superuser)
70 self.user0.revoke('admin', group0)
71 self.user0.revoke('admin', group1)
72 self.user0.is_superuser = True
73 self.user0.save()
74 response = c.get(url)
75 self.assertEqual(200, response.status_code)
76 self.assertEquals('text/html; charset=utf-8', response['content-type'])
77 self.assertTemplateUsed(response, 'group/list.html')
78 groups = response.context['groups']
79 self.assertTrue(group in groups)
80 self.assertTrue(group0 in groups)
81 self.assertTrue(group1 in groups)
82 self.assertTrue(group2 in groups)
83 self.assertEqual(4, len(groups))
85 def test_view_detail(self):
86 """
87 Test Viewing the detail for a Group
89 Verifies:
90 * 200 returned for valid group
91 * 404 returned for invalid group
92 """
93 group = self.test_save()
94 c = Client()
95 url = '/group/%s/'
96 args = group.id
98 # anonymous user
99 response = c.get(url % args, follow=True)
100 self.assertEqual(200, response.status_code)
101 self.assertTemplateUsed(response, 'registration/login.html')
103 # unauthorized user
104 self.assertTrue(c.login(username=self.user0.username, password='secret'))
105 response = c.get(url % args)
106 self.assertEqual(403, response.status_code)
108 # invalid user group
109 response = c.get(url % "DoesNotExist")
110 self.assertEqual(404, response.status_code)
112 # authorized (permission)
113 grant(self.user0, 'admin', group)
114 response = c.get(url % args)
115 self.assertEqual(200, response.status_code)
116 self.assertEquals('text/html; charset=utf-8', response['content-type'])
117 self.assertTemplateUsed(response, 'group/detail.html')
119 # authorized (superuser)
120 response = c.get(url % args)
121 self.assertEqual(200, response.status_code)
122 self.assertEquals('text/html; charset=utf-8', response['content-type'])
123 self.assertTemplateUsed(response, 'group/detail.html')
125 def test_view_edit(self):
126 group = self.test_save()
127 c = Client()
128 url = '/group/%s/edit/'
130 # anonymous user
131 response = c.post(url % group.id, follow=True)
132 self.assertEqual(200, response.status_code)
133 self.assertTemplateUsed(response, 'registration/login.html')
135 # unauthorized user
136 self.assertTrue(c.login(username=self.user0.username, password='secret'))
137 response = c.post(url % group.id)
138 self.assertEqual(403, response.status_code)
140 # invalid group
141 response = c.post(url % "DoesNotExist")
142 self.assertEqual(404, response.status_code)
144 # get form - authorized (permission)
145 # XXX need to implement Class wide permission for creating editing groups
146 #grant(user, 'admin', group)
147 #response = c.post(url % group.id)
148 #self.assertEqual(200, response.status_code)
149 #self.assertEquals('text/html; charset=utf-8', response['content-type'])
150 #self.assertTemplateUsed(response, 'group/edit.html')
152 # get form - authorized (permission)
153 grant(self.user0, 'admin', group)
154 response = c.post(url % group.id)
155 self.assertEqual(200, response.status_code)
156 self.assertEquals('text/html; charset=utf-8', response['content-type'])
157 self.assertTemplateUsed(response, 'group/edit.html')
159 # get form - authorized (superuser)
160 self.user0.revoke('admin', group)
161 self.user0.is_superuser = True
162 self.user0.save()
163 response = c.post(url % group.id)
164 self.assertEqual(200, response.status_code)
165 self.assertEquals('text/html; charset=utf-8', response['content-type'])
166 self.assertTemplateUsed(response, 'group/edit.html')
168 # missing name
169 data = {'id':group.id}
170 response = c.post(url % group.id, data)
171 self.assertEqual(200, response.status_code)
172 self.assertEquals('text/html; charset=utf-8', response['content-type'])
174 # setup signal
175 self.signal_editor = self.signal_group = None
176 def callback(sender, editor, **kwargs):
177 self.signal_user = self.user0
178 self.signal_group = sender
179 view_group_edited.connect(callback)
181 # successful edit
182 data = {'id':group.id, 'name':'EDITED_NAME'}
184 response = c.post(url % group.id, data)
185 self.assertRedirects(response, '/group/%s' % group.pk)
186 group = Group.objects.get(id=group.id)
187 self.assertEqual('EDITED_NAME', group.name)
189 # check signal set properties
190 self.assertEqual(group, self.signal_group)
191 self.assertEqual(self.user0, self.signal_user)
193 def test_view_create(self):
195 Test creating a new Group
197 group = self.test_save()
198 c = Client()
199 url = '/group/add/'
201 # anonymous user
202 response = c.post(url, follow=True)
203 self.assertEqual(200, response.status_code)
204 self.assertTemplateUsed(response, 'registration/login.html')
206 # unauthorized user
207 self.assertTrue(c.login(username=self.user0.username, password='secret'))
208 response = c.post(url)
209 self.assertEqual(403, response.status_code)
211 # get form - authorized (permission)
212 # XXX need to implement Class level permissions
213 #grant(user, 'admin', group)
214 #response = c.post(url % group.id)
215 #self.assertEqual(200, response.status_code)
216 #self.assertEquals('text/html; charset=utf-8', response['content-type'])
217 #self.assertTemplateUsed(response, 'group/edit.html')
219 # get form - authorized (superuser)
220 self.user0.revoke('admin', group)
221 self.user0.is_superuser = True
222 self.user0.save()
223 response = c.post(url)
224 self.assertEqual(200, response.status_code)
225 self.assertEquals('text/html; charset=utf-8', response['content-type'])
226 self.assertTemplateUsed(response, 'group/edit.html')
228 # missing name
229 response = c.post(url, {'name':''})
230 self.assertEqual(200, response.status_code)
231 self.assertEquals('text/html; charset=utf-8', response['content-type'])
232 self.assertTemplateUsed(response, 'group/edit.html')
234 # setup signal
235 self.signal_editor = self.signal_group = None
236 def callback(sender, editor, **kwargs):
237 self.signal_user = self.user0
238 self.signal_group = sender
239 view_group_created.connect(callback)
241 # successful edit
242 data = {'name':'ADD_NEW_GROUP'}
243 response = c.post(url, data)
244 group = Group.objects.get(name='ADD_NEW_GROUP')
245 self.assertRedirects(response, '/group/%s' % group.pk)
247 self.assertTrue(Group.objects.filter(name='ADD_NEW_GROUP').exists())
249 # check signal set properties
250 self.assertEqual(group, self.signal_group)
251 self.assertEqual(self.user0, self.signal_user)
253 def test_view_delete(self):
255 Test deleting a group
257 Verifies:
258 * group is deleted
259 * all associated permissions are deleted
261 group0 = self.test_save()
262 group1 = self.test_save(name='test2')
263 c = Client()
264 url = '/group/%s/edit/'
266 # anonymous user
267 response = c.delete(url % group0.id, follow=True)
268 self.assertEqual(200, response.status_code)
269 self.assertTemplateUsed(response, 'registration/login.html')
271 # unauthorized user
272 self.assertTrue(c.login(username=self.user0.username, password='secret'))
273 response = c.delete(url % group0.id)
274 self.assertEqual(403, response.status_code)
276 # invalid group
277 response = c.delete(url % "DoesNotExist")
278 self.assertEqual(404, response.status_code)
280 # get form - authorized (permission)
281 grant(self.user0, 'admin', group0)
282 response = c.delete(url % group0.id)
283 self.assertEqual(200, response.status_code)
284 self.assertEquals('application/json', response['content-type'])
285 self.assertFalse(Group.objects.filter(id=group0.id).exists())
286 self.assertEqual('1', response.content)
288 # setup signal
289 self.signal_editor = self.signal_group = None
290 def callback(sender, editor, **kwargs):
291 self.signal_user = self.user0
292 self.signal_group = sender
293 view_group_deleted.connect(callback)
295 # get form - authorized (superuser)
296 self.user0.is_superuser = True
297 self.user0.save()
298 response = c.delete(url % group1.id)
299 self.assertEqual(200, response.status_code)
300 self.assertEquals('application/json', response['content-type'])
301 self.assertFalse(Group.objects.filter(id=group1.id).exists())
302 self.assertEqual('1', response.content)
304 # check signal set properties
305 self.assertEqual(group1.name, self.signal_group.name)
306 self.assertEqual(self.user0, self.signal_user)
308 def test_view_add_user(self):
310 Test view for adding a user:
312 Verifies:
313 * request from unauthorized user results in 403
314 * GET returns a 200 code, response is html
315 * POST with a user id adds user, response is html for user
316 * POST without user id returns error as json
317 * POST for invalid user id returns error as json
318 * adding user a second time returns error as json
320 group = self.test_save()
321 c = Client()
322 url = '/group/%d/user/add/'
323 args = group.id
325 # anonymous user
326 response = c.get(url % args, follow=True)
327 self.assertEqual(200, response.status_code)
328 self.assertTemplateUsed(response, 'registration/login.html')
330 # unauthorized
331 self.assertTrue(c.login(username=self.user0.username, password='secret'))
332 response = c.get(url % args)
333 self.assertEqual(403, response.status_code)
334 response = c.post(url % args)
335 self.assertEqual(403, response.status_code)
337 # authorized get (perm granted)
338 grant(self.user0, 'admin', group)
339 response = c.get(url % args)
340 self.assertEqual(200, response.status_code)
341 self.assertEquals('text/html; charset=utf-8', response['content-type'])
342 self.assertTemplateUsed(response, 'group/add_user.html')
344 # authorized get (superuser)
345 revoke(self.user0, 'admin', group)
346 self.user0.is_superuser = True
347 self.user0.save()
348 response = c.get(url % args)
349 self.assertEqual(200, response.status_code)
350 self.assertEquals('text/html; charset=utf-8', response['content-type'])
351 self.assertTemplateUsed(response, 'group/add_user.html')
353 # missing user id
354 response = c.post(url % args)
355 self.assertEqual(200, response.status_code)
356 self.assertEquals('application/json', response['content-type'])
358 # invalid user
359 response = c.post(url % args, {'user':0})
360 self.assertEqual(200, response.status_code)
361 self.assertEquals('application/json', response['content-type'])
363 # setup signal
364 self.signal_sender = self.signal_user = self.signal_obj = None
365 def callback(sender, user, obj, **kwargs):
366 self.signal_sender = sender
367 self.signal_user = user
368 self.signal_obj = obj
369 view_add_user.connect(callback)
371 # valid post
372 data = {'user':self.user0.id}
373 response = c.post(url % args, data)
374 self.assertEqual(200, response.status_code)
375 self.assertEquals('text/html; charset=utf-8', response['content-type'])
376 self.assertTemplateUsed(response, 'muddle/group/user_row.html')
377 self.assertTrue(group.user_set.filter(id=self.user0.id).exists())
379 # check signal fired
380 self.assertEqual(self.signal_sender, self.user0)
381 self.assertEqual(self.signal_user, self.user0)
382 self.assertEqual(self.signal_obj, group)
383 view_add_user.disconnect(callback)
385 # same user again
386 response = c.post(url % args, data)
387 self.assertEqual(200, response.status_code)
388 self.assertEquals('application/json', response['content-type'])
389 self.assertEquals(group.user_set.filter(id=self.user0.id).count(), 1)
391 def test_view_remove_user(self):
393 Test view for adding a user:
395 Verifies:
396 * GET redirects user to 405
397 * POST with a user id remove user, returns 1
398 * POST without user id returns error as json
399 * users lacking perms receive 403
400 * removing user not in group returns error as json
401 * removing user that does not exist returns error as json
402 * user loses all permissions when removed from group
404 group = self.test_save()
405 c = Client()
406 group.user_set.add(self.user0)
407 url = '/group/%d/user/remove/'
408 args = group.id
410 # anonymous user
411 response = c.get(url % args, follow=True)
412 self.assertEqual(200, response.status_code)
413 self.assertTemplateUsed(response, 'registration/login.html')
415 # invalid permissions
416 self.assertTrue(c.login(username=self.user0.username, password='secret'))
417 response = c.get(url % args)
418 self.assertEqual(403, response.status_code)
419 response = c.post(url % args)
420 self.assertEqual(403, response.status_code)
422 # authorize and login
423 grant(self.user0, 'admin', group)
425 # invalid method
426 response = c.get(url % args)
427 self.assertEqual(405, response.status_code)
429 # valid request (perm)
430 data = {'user':self.user0.id}
431 response = c.post(url % args, data)
432 self.assertEqual(200, response.status_code)
433 self.assertEquals('application/json', response['content-type'])
434 self.assertEqual('1', response.content)
435 self.assertFalse(group.user_set.filter(id=self.user0.id).exists())
436 self.assertEqual([], self.user0.get_perms(group))
438 # setup signal
439 self.signal_sender = self.signal_user = self.signal_obj = None
440 def callback(sender, user, obj, **kwargs):
441 self.signal_sender = sender
442 self.signal_user = user
443 self.signal_obj = obj
444 view_remove_user.connect(callback)
446 # valid request (superuser)
447 revoke(self.user0, 'admin', group)
448 self.user0.is_superuser = True
449 self.user0.save()
450 group.user_set.add(self.user0)
451 response = c.post(url % args, data)
452 self.assertEqual(200, response.status_code)
453 self.assertEquals('application/json', response['content-type'])
454 self.assertEqual('1', response.content)
455 self.assertFalse(group.user_set.filter(id=self.user0.id).exists())
457 # check signal fired
458 self.assertEqual(self.signal_sender, self.user0)
459 self.assertEqual(self.signal_user, self.user0)
460 self.assertEqual(self.signal_obj, group)
461 view_remove_user.disconnect(callback)
463 # remove user again
464 response = c.post(url % args, data)
465 self.assertEqual(200, response.status_code)
466 self.assertEquals('application/json', response['content-type'])
467 self.assertFalse(group.user_set.filter(id=self.user0.id).exists())
468 self.assertNotEqual('1', response.content)
470 # remove invalid user
471 response = c.post(url % args, {'user':0})
472 self.assertEqual(200, response.status_code)
473 self.assertEquals('application/json', response['content-type'])
474 self.assertNotEqual('1', response.content)