Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tests / auth.py @ b1cb2583

History | View | Annotate | Download (68.8 kB)

1
# -*- coding: utf-8 -*-
2
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
3
#
4
# Redistribution and use in source and binary forms, with or
5
# without modification, are permitted provided that the following
6
# conditions are met:
7
#
8
#   1. Redistributions of source code must retain the above
9
#      copyright notice, this list of conditions and the following
10
#      disclaimer.
11
#
12
#   2. Redistributions in binary form must reproduce the above
13
#      copyright notice, this list of conditions and the following
14
#      disclaimer in the documentation and/or other materials
15
#      provided with the distribution.
16
#
17
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
# POSSIBILITY OF SUCH DAMAGE.
29
#
30
# The views and conclusions contained in the software and
31
# documentation are those of the authors and should not be
32
# interpreted as representing official policies, either expressed
33
# or implied, of GRNET S.A.
34

    
35
import urlparse
36
import urllib
37

    
38
from astakos.im.tests.common import *
39

    
40
ui_url = lambda url: '/' + astakos_settings.BASE_PATH + '/ui/%s' % url
41

    
42

    
43
class ShibbolethTests(TestCase):
44
    """
45
    Testing shibboleth authentication.
46
    """
47

    
48
    def setUp(self):
49
        self.client = ShibbolethClient()
50
        astakos_settings.IM_MODULES = ['local', 'shibboleth']
51
        astakos_settings.MODERATION_ENABLED = True
52

    
53
    def tearDown(self):
54
        AstakosUser.objects.all().delete()
55

    
56
    @im_settings(FORCE_PROFILE_UPDATE=False)
57
    def test_create_account(self):
58

    
59
        client = ShibbolethClient()
60

    
61
        # shibboleth views validation
62
        # eepn required
63
        r = client.get(ui_url('login/shibboleth?'), follow=True)
64
        self.assertContains(r, messages.SHIBBOLETH_MISSING_USER_ID % {
65
            'domain': astakos_settings.BASE_HOST,
66
            'contact_email': settings.CONTACT_EMAIL
67
        })
68
        client.set_tokens(remote_user="kpapeppn", eppn="kpapeppn")
69

    
70
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = True
71
        # shibboleth user info required
72
        r = client.get(ui_url('login/shibboleth?'), follow=True)
73
        self.assertContains(r, messages.SHIBBOLETH_MISSING_NAME)
74
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = False
75

    
76
        # shibboleth logged us in
77
        client.set_tokens(mail="kpap@synnefo.org", remote_user="kpapeppn",
78
                          cn="Kostas Papadimitriou" + 30*"*",
79
                          ep_affiliation="Test Affiliation")
80
        r = client.get(ui_url('login/shibboleth?'), follow=True,
81
                       **{'HTTP_SHIB_CUSTOM_IDP_KEY': 'test'})
82

    
83
        # name exceeds first_name character limit, validation error skipped
84
        self.assertEqual(r.status_code, 200)
85
        pending = PendingThirdPartyUser.objects.get()
86
        self.assertEqual(pending.first_name, "Kostas")
87
        self.assertEqual(pending.last_name, None)
88

    
89
        # shibboleth logged us in
90
        client.set_tokens(mail="kpap@synnefo.org", remote_user="kpapeppn",
91
                          cn="Kostas Papadimitriou",
92
                          ep_affiliation="Test Affiliation")
93
        r = client.get(ui_url('login/shibboleth?'), follow=True,
94
                       **{'HTTP_SHIB_CUSTOM_IDP_KEY': 'test'})
95
        pending = PendingThirdPartyUser.objects.get()
96
        token = pending.token
97
        self.assertEqual(pending.first_name, "Kostas")
98
        self.assertEqual(pending.last_name, "Papadimitriou")
99

    
100
        self.assertRedirects(r, ui_url('signup?third_party_token=%s' % token))
101
        self.assertEqual(r.status_code, 200)
102

    
103
        # a new pending user created
104
        pending_user = PendingThirdPartyUser.objects.get(
105
            third_party_identifier="kpapeppn")
106
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
107
        # keep the token for future use
108
        token = pending_user.token
109
        # from now on no shibboleth headers are sent to the server
110
        client.reset_tokens()
111

    
112
        # this is the old way, it should fail, to avoid pending user take over
113
        r = client.get(ui_url('shibboleth/signup/%s' % pending_user.username))
114
        self.assertEqual(r.status_code, 404)
115

    
116
        # this is the signup unique url associated with the pending user
117
        # created
118
        r = client.get(ui_url('signup/?third_party_token=%s' % token))
119
        identifier = pending_user.third_party_identifier
120
        post_data = {'third_party_identifier': identifier,
121
                     'first_name': 'Kostas',
122
                     'third_party_token': token,
123
                     'last_name': 'Mitroglou',
124
                     'provider': 'shibboleth'}
125

    
126
        signup_url = reverse('signup')
127

    
128
        # invalid request
129
        invalid_data = copy.copy(post_data)
130
        invalid_data['provider'] = ''
131
        r = client.post(signup_url, invalid_data, follow=True)
132
        self.assertRedirects(r, reverse('signup'))
133

    
134
        # invlid email
135
        post_data['email'] = 'kpap'
136
        r = client.post(signup_url, post_data)
137
        self.assertContains(r, token)
138

    
139
        # existing email
140
        existing_user = get_local_user('test@test.com')
141
        post_data['email'] = 'test@test.com'
142
        r = client.post(signup_url, post_data)
143
        self.assertContains(r, messages.EMAIL_USED)
144
        existing_user.delete()
145

    
146
        # and finally a valid signup
147
        post_data['email'] = 'kpap-takeover@synnefo.org'
148
        r = client.post(signup_url, post_data, follow=True)
149
        self.assertContains(r, messages.VERIFICATION_SENT)
150

    
151
        # takeover of the uverified the shibboleth identifier
152
        client = ShibbolethClient()
153
        client.set_tokens(mail="kpap@synnefo.org", remote_user="kpapeppn",
154
                          eppn="kpapeppn",
155
                          cn="Kostas Papadimitriou",
156
                          ep_affiliation="Test Affiliation")
157
        r = client.get(ui_url('login/shibboleth?'), follow=True,
158
                       **{'HTTP_SHIB_CUSTOM_IDP_KEY': 'test'})
159
        # a new pending user created, previous one was deleted
160
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
161
        pending_user = PendingThirdPartyUser.objects.get(
162
            third_party_identifier="kpapeppn")
163
        identifier = pending_user.third_party_identifier
164
        token = pending_user.token
165
        post_data = {'third_party_identifier': identifier,
166
                     'third_party_token': token}
167
        post_data['email'] = 'kpap@synnefo.org'
168
        r = client.post(signup_url, post_data)
169
        self.assertEqual(PendingThirdPartyUser.objects.count(), 0)
170
        # previously unverified user associated with kpapeppn gets deleted
171
        user_qs = AstakosUser.objects.filter(email="kpap-takeover@synnefo.org")
172
        self.assertEqual(user_qs.count(), 0)
173

    
174
        # entires commited as expected
175
        self.assertEqual(AstakosUser.objects.count(), 1)
176
        self.assertEqual(AstakosUserAuthProvider.objects.count(), 1)
177

    
178
        user = AstakosUser.objects.get()
179
        provider = user.get_auth_provider("shibboleth")
180
        headers = provider.provider_details['info']['headers']
181
        self.assertEqual(headers.get('SHIB_CUSTOM_IDP_KEY'), 'test')
182

    
183
        # provider info stored
184
        provider = AstakosUserAuthProvider.objects.get(module="shibboleth")
185
        self.assertEqual(provider.affiliation, 'Test Affiliation')
186
        self.assertEqual(provider.info['email'], u'kpap@synnefo.org')
187
        self.assertEqual(provider.info['eppn'], u'kpapeppn')
188
        self.assertEqual(provider.info['name'], u'Kostas Papadimitriou')
189
        self.assertTrue('headers' in provider.info)
190

    
191
        # login (not verified yet)
192
        client.set_tokens(mail="kpap@synnefo.org", remote_user="kpapeppn",
193
                          cn="Kostas Papadimitriou")
194
        r = client.get(ui_url("login/shibboleth?"), follow=True)
195
        self.assertContains(r, 'A pending registration exists for')
196
        self.assertNotContains(r, 'pending moderation')
197
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
198
        tmp_third_party = PendingThirdPartyUser.objects.get()
199

    
200
        # user gets verified
201
        u = AstakosUser.objects.get(username="kpap@synnefo.org")
202
        backend = activation_backends.get_backend()
203
        activation_result = backend.verify_user(u, u.verification_code)
204
        client.set_tokens(mail="kpap@synnefo.org", remote_user="kpapeppn",
205
                          cn="Kostas Papadimitriou")
206
        r = client.get(ui_url("login/shibboleth?"), follow=True)
207
        self.assertNotContains(r, 'A pending registration exists for')
208
        self.assertContains(r, 'pending moderation')
209

    
210
        # temporary signup process continues. meanwhile the user have verified
211
        # her account. The signup process should fail
212
        tp = tmp_third_party
213
        post_data = {'third_party_identifier': tp.third_party_identifier,
214
                     'email': 'unsed-email@synnefo.org',
215
                     'third_party_token': tp.token}
216
        r = client.post(signup_url, post_data)
217
        self.assertEqual(r.status_code, 404)
218

    
219
        r = client.post(reverse('astakos.im.views.target.local.password_reset'),
220
                        {'email': 'kpap@synnefo.org'})
221
        self.assertContains(r, 'Classic login is not enabled for your account')
222

    
223
        # admin activates the user
224
        u = AstakosUser.objects.get(username="kpap@synnefo.org")
225
        backend = activation_backends.get_backend()
226
        activation_result = backend.verify_user(u, u.verification_code)
227
        activation_result = backend.accept_user(u)
228
        self.assertFalse(activation_result.is_error())
229
        backend.send_result_notifications(activation_result, u)
230
        self.assertEqual(u.is_active, True)
231

    
232

    
233
        # we see our profile
234
        r = client.get(ui_url("login/shibboleth?"), follow=True)
235
        self.assertRedirects(r, ui_url('landing'))
236
        self.assertEqual(r.status_code, 200)
237

    
238
    def test_existing(self):
239
        """
240
        Test adding of third party login to an existing account
241
        """
242

    
243
        # this is our existing user
244
        existing_user = get_local_user('kpap@synnefo.org')
245
        existing_inactive = get_local_user('kpap-inactive@synnefo.org')
246
        existing_inactive.is_active = False
247
        existing_inactive.save()
248

    
249
        existing_unverified = get_local_user('kpap-unverified@synnefo.org')
250
        existing_unverified.is_active = False
251
        existing_unverified.activation_sent = None
252
        existing_unverified.email_verified = False
253
        existing_unverified.is_verified = False
254
        existing_unverified.save()
255

    
256
        client = ShibbolethClient()
257
        # shibboleth logged us in, notice that we use different email
258
        client.set_tokens(mail="kpap@shibboleth.gr", remote_user="kpapeppn",
259
                          cn="Kostas Papadimitriou", )
260
        r = client.get(ui_url("login/shibboleth?"), follow=True)
261

    
262
        # a new pending user created
263
        pending_user = PendingThirdPartyUser.objects.get()
264
        token = pending_user.token
265
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
266
        pending_key = pending_user.token
267
        client.reset_tokens()
268
        self.assertRedirects(r, ui_url("signup?third_party_token=%s" % token))
269

    
270
        form = r.context['login_form']
271
        signupdata = copy.copy(form.initial)
272
        signupdata['email'] = 'kpap@synnefo.org'
273
        signupdata['third_party_token'] = token
274
        signupdata['provider'] = 'shibboleth'
275
        signupdata.pop('id', None)
276

    
277
        # the email exists to another user
278
        r = client.post(ui_url("signup"), signupdata)
279
        self.assertContains(r, "There is already an account with this email "
280
                               "address")
281
        # change the case, still cannot create
282
        signupdata['email'] = 'KPAP@synnefo.org'
283
        r = client.post(ui_url("signup"), signupdata)
284
        self.assertContains(r, "There is already an account with this email "
285
                               "address")
286
        # inactive user
287
        signupdata['email'] = 'KPAP-inactive@synnefo.org'
288
        r = client.post(ui_url("signup"), signupdata)
289
        self.assertContains(r, "There is already an account with this email "
290
                               "address")
291

    
292
        # unverified user, this should pass, old entry will be deleted
293
        signupdata['email'] = 'KAPAP-unverified@synnefo.org'
294
        r = client.post(ui_url("signup"), signupdata)
295

    
296
        post_data = {'password': 'password',
297
                     'username': 'kpap@synnefo.org'}
298
        r = client.post(ui_url('local'), post_data, follow=True)
299
        self.assertTrue(r.context['request'].user.is_authenticated())
300
        client.set_tokens(mail="kpap@shibboleth.gr", remote_user="kpapeppn",
301
                          cn="Kostas Papadimitriou", )
302
        r = client.get(ui_url("login/shibboleth?"), follow=True)
303
        self.assertContains(r, "enabled for this account")
304
        client.reset_tokens()
305

    
306
        user = existing_user
307
        self.assertTrue(user.has_auth_provider('shibboleth'))
308
        self.assertTrue(user.has_auth_provider('local',
309
                                               auth_backend='astakos'))
310
        client.logout()
311

    
312
        # look Ma, i can login with both my shibboleth and local account
313
        client.set_tokens(mail="kpap@shibboleth.gr", remote_user="kpapeppn",
314
                          cn="Kostas Papadimitriou")
315
        r = client.get(ui_url("login/shibboleth?"), follow=True)
316
        self.assertTrue(r.context['request'].user.is_authenticated())
317
        self.assertTrue(r.context['request'].user.email == "kpap@synnefo.org")
318
        self.assertRedirects(r, ui_url('landing'))
319
        self.assertEqual(r.status_code, 200)
320

    
321
        user = r.context['request'].user
322
        client.logout()
323
        client.reset_tokens()
324

    
325
        # logged out
326
        r = client.get(ui_url("profile"), follow=True)
327
        self.assertFalse(r.context['request'].user.is_authenticated())
328

    
329
        # login with local account also works
330
        post_data = {'password': 'password',
331
                     'username': 'kpap@synnefo.org'}
332
        r = self.client.post(ui_url('local'), post_data, follow=True)
333
        self.assertTrue(r.context['request'].user.is_authenticated())
334
        self.assertTrue(r.context['request'].user.email == "kpap@synnefo.org")
335
        self.assertRedirects(r, ui_url('landing'))
336
        self.assertEqual(r.status_code, 200)
337

    
338
        # cannot add the same eppn
339
        client.set_tokens(mail="secondary@shibboleth.gr",
340
                          remote_user="kpapeppn",
341
                          cn="Kostas Papadimitriou", )
342
        r = client.get(ui_url("login/shibboleth?"), follow=True)
343
        self.assertRedirects(r, ui_url('landing'))
344
        self.assertTrue(r.status_code, 200)
345
        self.assertEquals(existing_user.auth_providers.count(), 2)
346

    
347
        # only one allowed by default
348
        client.set_tokens(mail="secondary@shibboleth.gr",
349
                          remote_user="kpapeppn2",
350
                          cn="Kostas Papadimitriou", ep_affiliation="affil2")
351
        prov = auth_providers.get_provider('shibboleth')
352
        r = client.get(ui_url("login/shibboleth?"), follow=True)
353
        self.assertContains(r, "Failed to add")
354
        self.assertRedirects(r, ui_url('profile'))
355
        self.assertTrue(r.status_code, 200)
356
        self.assertEquals(existing_user.auth_providers.count(), 2)
357
        client.logout()
358
        client.reset_tokens()
359

    
360
        # cannot login with another eppn
361
        client.set_tokens(mail="kpap@synnefo.org",
362
                          remote_user="kpapeppninvalid",
363
                          cn="Kostas Papadimitriou")
364
        r = client.get(ui_url("login/shibboleth?"), follow=True)
365
        self.assertFalse(r.context['request'].user.is_authenticated())
366

    
367
        # cannot
368

    
369
        # lets remove local password
370
        user = AstakosUser.objects.get(username="kpap@synnefo.org",
371
                                       email="kpap@synnefo.org")
372
        remove_local_url = user.get_auth_provider('local').get_remove_url
373
        remove_shibbo_url = user.get_auth_provider('shibboleth',
374
                                                   'kpapeppn').get_remove_url
375
        client.set_tokens(mail="kpap@shibboleth.gr", remote_user="kpapeppn",
376
                          cn="Kostas Papadimtriou")
377
        r = client.get(ui_url("login/shibboleth?"), follow=True)
378
        client.reset_tokens()
379

    
380
        # only POST is allowed (for CSRF protection)
381
        r = client.get(remove_local_url, follow=True)
382
        self.assertEqual(r.status_code, 405)
383

    
384
        r = client.post(remove_local_url, follow=True)
385
        # 2 providers left
386
        self.assertEqual(user.auth_providers.count(), 1)
387
        # cannot remove last provider
388
        r = client.post(remove_shibbo_url)
389
        self.assertEqual(r.status_code, 403)
390
        self.client.logout()
391

    
392
        # cannot login using local credentials (notice we use another client)
393
        post_data = {'password': 'password',
394
                     'username': 'kpap@synnefo.org'}
395
        r = self.client.post(ui_url('local'), post_data, follow=True)
396
        self.assertFalse(r.context['request'].user.is_authenticated())
397

    
398
        # we can reenable the local provider by setting a password
399
        r = client.get(ui_url("password_change"), follow=True)
400
        r = client.post(ui_url("password_change"), {'new_password1': '111',
401
                                                    'new_password2': '111'},
402
                        follow=True)
403
        user = r.context['request'].user
404
        self.assertTrue(user.has_auth_provider('local'))
405
        self.assertTrue(user.has_auth_provider('shibboleth'))
406
        self.assertTrue(user.check_password('111'))
407
        self.assertTrue(user.has_usable_password())
408

    
409
        # change password via profile form
410
        r = client.post(ui_url("profile"), {
411
            'old_password': '111',
412
            'new_password': '',
413
            'new_password2': '',
414
            'change_password': 'on',
415
        }, follow=False)
416
        self.assertEqual(r.status_code, 200)
417
        self.assertFalse(r.context['profile_form'].is_valid())
418

    
419
        self.client.logout()
420

    
421
        # now we can login
422
        post_data = {'password': '111',
423
                     'username': 'kpap@synnefo.org'}
424
        r = self.client.post(ui_url('local'), post_data, follow=True)
425
        self.assertTrue(r.context['request'].user.is_authenticated())
426

    
427
        client.reset_tokens()
428

    
429
        # we cannot take over another shibboleth identifier
430
        user2 = get_local_user('another@synnefo.org')
431
        user2.add_auth_provider('shibboleth', identifier='existingeppn')
432
        # login
433
        client.set_tokens(mail="kpap@shibboleth.gr", remote_user="kpapeppn",
434
                          cn="Kostas Papadimitriou")
435
        r = client.get(ui_url("login/shibboleth?"), follow=True)
436
        # try to assign existing shibboleth identifier of another user
437
        client.set_tokens(mail="kpap_second@shibboleth.gr",
438
                          remote_user="existingeppn",
439
                          cn="Kostas Papadimitriou")
440
        r = client.get(ui_url("login/shibboleth?"), follow=True)
441
        self.assertContains(r, "is already in use")
442

    
443

    
444
class TestLocal(TestCase):
445

    
446
    def setUp(self):
447
        settings.ADMINS = (('admin', 'support@cloud.synnefo.org'),)
448
        settings.SERVER_EMAIL = 'no-reply@synnefo.org'
449
        self._orig_moderation = astakos_settings.MODERATION_ENABLED
450
        settings.ASTAKOS_MODERATION_ENABLED = True
451

    
452
    def tearDown(self):
453
        settings.ASTAKOS_MODERATION_ENABLED = self._orig_moderation
454
        AstakosUser.objects.all().delete()
455

    
456
    @im_settings(RECAPTCHA_ENABLED=True, RATELIMIT_RETRIES_ALLOWED=3)
457
    def test_login_ratelimit(self):
458
        from django.core.cache import cache
459
        cache.clear()
460
        [cache.delete(key) for key in cache._cache.keys()]
461

    
462
        credentials = {'username': 'γιού τι έφ', 'password': 'password'}
463
        r = self.client.post(ui_url('local'), credentials, follow=True)
464
        fields = r.context['login_form'].fields.keyOrder
465
        self.assertFalse('recaptcha_challenge_field' in fields)
466
        r = self.client.post(ui_url('local'), credentials, follow=True)
467
        fields = r.context['login_form'].fields.keyOrder
468
        self.assertFalse('recaptcha_challenge_field' in fields)
469
        r = self.client.post(ui_url('local'), credentials, follow=True)
470
        fields = r.context['login_form'].fields.keyOrder
471
        self.assertTrue('recaptcha_challenge_field' in fields)
472

    
473
    def test_no_moderation(self):
474
        # disable moderation
475
        astakos_settings.MODERATION_ENABLED = False
476

    
477
        # create a new user
478
        r = self.client.get(ui_url("signup"))
479
        self.assertEqual(r.status_code, 200)
480
        data = {'email': 'kpap@synnefo.org', 'password1': 'password',
481
                'password2': 'password', 'first_name': 'Kostas',
482
                'last_name': 'Mitroglou', 'provider': 'local'}
483
        r = self.client.post(ui_url("signup"), data)
484

    
485
        # user created
486
        self.assertEqual(AstakosUser.objects.count(), 1)
487
        user = AstakosUser.objects.get(username="kpap@synnefo.org",
488
                                       email="kpap@synnefo.org")
489
        self.assertEqual(user.username, 'kpap@synnefo.org')
490
        self.assertEqual(user.has_auth_provider('local'), True)
491
        self.assertFalse(user.is_active)
492

    
493
        # user (but not admin) gets notified
494
        self.assertEqual(len(get_mailbox('support@cloud.synnefo.org')), 0)
495
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
496
        astakos_settings.MODERATION_ENABLED = True
497

    
498
    def test_email_case(self):
499
        data = {
500
            'email': 'kPap@synnefo.org',
501
            'password1': '1234',
502
            'password2': '1234'
503
        }
504

    
505
        form = forms.LocalUserCreationForm(data)
506
        self.assertTrue(form.is_valid())
507
        user = form.create_user()
508

    
509
        u = AstakosUser.objects.get()
510
        self.assertEqual(u.email, 'kPap@synnefo.org')
511
        self.assertEqual(u.username, 'kpap@synnefo.org')
512
        u.is_active = True
513
        u.email_verified = True
514
        u.save()
515

    
516
        data = {'username': 'kpap@synnefo.org', 'password': '1234'}
517
        login = forms.LoginForm(data=data)
518
        self.assertTrue(login.is_valid())
519

    
520
        data = {'username': 'KpaP@synnefo.org', 'password': '1234'}
521
        login = forms.LoginForm(data=data)
522
        self.assertTrue(login.is_valid())
523

    
524
        data = {
525
            'email': 'kpap@synnefo.org',
526
            'password1': '1234',
527
            'password2': '1234'
528
        }
529
        form = forms.LocalUserCreationForm(data)
530
        self.assertFalse(form.is_valid())
531

    
532
    @im_settings(HELPDESK=(('support', 'support@synnefo.org'),),
533
                 FORCE_PROFILE_UPDATE=False, MODERATION_ENABLED=True)
534
    def test_local_provider(self):
535
        self.helpdesk_email = astakos_settings.HELPDESK[0][1]
536

    
537
        # create a user
538
        r = self.client.get(ui_url("signup"))
539
        self.assertEqual(r.status_code, 200)
540
        data = {'email': 'kpap@synnefo.org', 'password1': 'password',
541
                'password2': 'password', 'first_name': 'Kostas',
542
                'last_name': 'Mitroglou', 'provider': 'local'}
543
        r = self.client.post(ui_url("signup"), data)
544

    
545
        # user created
546
        self.assertEqual(AstakosUser.objects.count(), 1)
547
        user = AstakosUser.objects.get(username="kpap@synnefo.org",
548
                                       email="kpap@synnefo.org")
549
        self.assertEqual(user.username, 'kpap@synnefo.org')
550
        self.assertEqual(user.has_auth_provider('local'), True)
551
        self.assertFalse(user.is_active)  # not activated
552
        self.assertFalse(user.email_verified)  # not verified
553
        self.assertTrue(user.activation_sent)  # activation automatically sent
554
        self.assertFalse(user.moderated)
555
        self.assertFalse(user.email_verified)
556

    
557
        # admin gets notified and activates the user from the command line
558
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
559
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
560
                                               'password': 'password'},
561
                             follow=True)
562
        self.assertContains(r, messages.VERIFICATION_SENT)
563
        backend = activation_backends.get_backend()
564

    
565
        user = AstakosUser.objects.get(username="kpap@synnefo.org")
566
        backend.send_user_verification_email(user)
567

    
568
        # user activation fields updated and user gets notified via email
569
        user = AstakosUser.objects.get(pk=user.pk)
570
        self.assertTrue(user.activation_sent)
571
        self.assertFalse(user.email_verified)
572
        self.assertFalse(user.is_active)
573
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 2)
574

    
575
        # user forgot she got registered and tries to submit registration
576
        # form. Notice the upper case in email
577
        data = {'email': 'KPAP@synnefo.org', 'password1': 'password',
578
                'password2': 'password', 'first_name': 'Kostas',
579
                'last_name': 'Mitroglou', 'provider': 'local'}
580
        r = self.client.post(ui_url("signup"), data, follow=True)
581
        self.assertRedirects(r, reverse('login'))
582
        self.assertContains(r, messages.VERIFICATION_SENT)
583

    
584
        user = AstakosUser.objects.get()
585
        # previous user replaced
586
        self.assertTrue(user.activation_sent)
587
        self.assertFalse(user.email_verified)
588
        self.assertFalse(user.is_active)
589
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 1)
590

    
591
        # hmmm, email exists; lets request a password change
592
        r = self.client.get(ui_url('local/password_reset'))
593
        self.assertEqual(r.status_code, 200)
594
        data = {'email': 'kpap@synnefo.org'}
595
        r = self.client.post(ui_url('local/password_reset'), data, follow=True)
596
        # she can't because account is not active yet
597
        self.assertContains(r, 'pending email verification')
598

    
599
        # moderation is enabled and an activation email has already been sent
600
        # so user can trigger resend of the activation email
601
        r = self.client.get(ui_url('send/activation/%d' % user.pk),
602
                            follow=True)
603
        self.assertContains(r, 'has been sent to your email address.')
604
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 2)
605

    
606
        # also she cannot login
607
        data = {'username': 'kpap@synnefo.org', 'password': 'password'}
608
        r = self.client.post(ui_url('local'), data, follow=True)
609
        self.assertContains(r, 'Resend verification')
610
        self.assertFalse(r.context['request'].user.is_authenticated())
611
        self.assertFalse('_pithos2_a' in self.client.cookies)
612

    
613
        # user sees the message and resends activation
614
        r = self.client.get(ui_url('send/activation/%d' % user.pk),
615
                            follow=True)
616
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 3)
617

    
618
        # logged in user cannot activate another account
619
        tmp_user = get_local_user("test_existing_user@synnefo.org")
620
        tmp_client = Client()
621
        tmp_client.login(username="test_existing_user@synnefo.org",
622
                         password="password")
623
        r = tmp_client.get(user.get_activation_url(), follow=True)
624
        self.assertContains(r, messages.LOGGED_IN_WARNING)
625

    
626
        # empty activation code is not allowed
627
        r = self.client.get(user.get_activation_url().split("?")[0],
628
                            follow=True)
629
        self.assertEqual(r.status_code, 403)
630

    
631
        r = self.client.get(user.get_activation_url(), follow=True)
632
        # previous code got invalidated
633
        self.assertRedirects(r, reverse('login'))
634
        self.assertContains(r, astakos_messages.INVALID_ACTIVATION_KEY)
635
        self.assertEqual(r.status_code, 200)
636

    
637
        user = AstakosUser.objects.get(pk=user.pk)
638
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 0)
639
        r = self.client.get(user.get_activation_url(), follow=True)
640
        self.assertRedirects(r, reverse('login'))
641
        # user sees that account is pending approval from admins
642
        self.assertContains(r, messages.NOTIFICATION_SENT)
643
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 1)
644

    
645
        user = AstakosUser.objects.get(email="KPAP@synnefo.org")
646
        result = backend.handle_moderation(user)
647
        backend.send_result_notifications(result, user)
648
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 4)
649
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 2)
650

    
651
        user = AstakosUser.objects.get(email="KPAP@synnefo.org")
652
        r = self.client.get(ui_url('profile'), follow=True)
653
        self.assertFalse(r.context['request'].user.is_authenticated())
654
        self.assertFalse('_pithos2_a' in self.client.cookies)
655
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 4)
656

    
657
        user = AstakosUser.objects.get(pk=user.pk)
658
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
659
                                               'password': 'password'},
660
                             follow=True)
661
        # user activated and logged in, token cookie set
662
        self.assertTrue(r.context['request'].user.is_authenticated())
663
        self.assertTrue('_pithos2_a' in self.client.cookies)
664
        cookies = self.client.cookies
665
        self.assertTrue(quote(user.auth_token) in
666
                        cookies.get('_pithos2_a').value)
667
        r = self.client.get(ui_url('logout'), follow=True)
668
        r = self.client.get(ui_url(''), follow=True)
669
        self.assertRedirects(r, ui_url('login'))
670
        # user logged out, token cookie removed
671
        self.assertFalse(r.context['request'].user.is_authenticated())
672
        self.assertFalse(self.client.cookies.get('_pithos2_a').value)
673

    
674
        #https://docs.djangoproject.com/en/dev/topics/testing/#persistent-state
675
        del self.client.cookies['_pithos2_a']
676

    
677
        # user can login
678
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
679
                                               'password': 'password'},
680
                             follow=True)
681
        self.assertTrue(r.context['request'].user.is_authenticated())
682
        self.assertTrue('_pithos2_a' in self.client.cookies)
683
        cookies = self.client.cookies
684
        self.assertTrue(quote(user.auth_token) in
685
                        cookies.get('_pithos2_a').value)
686
        self.client.get(ui_url('logout'), follow=True)
687

    
688
        # user forgot password
689
        old_pass = user.password
690
        r = self.client.get(ui_url('local/password_reset'))
691
        self.assertEqual(r.status_code, 200)
692
        r = self.client.post(ui_url('local/password_reset'),
693
                             {'email': 'kpap@synnefo.org'})
694
        self.assertEqual(r.status_code, 302)
695
        # email sent
696
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 5)
697

    
698
        # user visits change password link
699
        user = AstakosUser.objects.get(pk=user.pk)
700
        r = self.client.get(user.get_password_reset_url())
701
        r = self.client.post(user.get_password_reset_url(),
702
                             {'new_password1': 'newpass',
703
                              'new_password2': 'newpass'})
704

    
705
        user = AstakosUser.objects.get(pk=user.pk)
706
        self.assertNotEqual(old_pass, user.password)
707

    
708
        # old pass is not usable
709
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
710
                                               'password': 'password'})
711
        self.assertContains(r, 'Please enter a correct username and password')
712
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
713
                                               'password': 'newpass'},
714
                             follow=True)
715
        self.assertTrue(r.context['request'].user.is_authenticated())
716
        self.client.logout()
717

    
718
        # tests of special local backends
719
        user = AstakosUser.objects.get(pk=user.pk)
720
        user.auth_providers.filter(module='local').update(auth_backend='ldap')
721
        user.save()
722

    
723
        # non astakos local backends do not support password reset
724
        r = self.client.get(ui_url('local/password_reset'))
725
        self.assertEqual(r.status_code, 200)
726
        r = self.client.post(ui_url('local/password_reset'),
727
                             {'email': 'kpap@synnefo.org'})
728
        # she can't because account is not active yet
729
        self.assertContains(r, "Changing password is not")
730

    
731
    def test_fix_superuser(self):
732
        u = User.objects.create(username="dummy", email="email@example.org",
733
                                first_name="Super", last_name="User",
734
                                is_superuser=True)
735
        User.objects.create(username="dummy2", email="email2@example.org",
736
                            first_name="Other", last_name="User")
737
        fixed = auth_functions.fix_superusers()
738
        self.assertEqual(len(fixed), 1)
739
        fuser = fixed[0]
740
        self.assertEqual(fuser.email, fuser.username)
741

    
742

    
743
class UserActionsTests(TestCase):
744

    
745
    def test_email_validation(self):
746
        backend = activation_backends.get_backend()
747
        form = backend.get_signup_form('local')
748
        self.assertTrue(isinstance(form, forms.LocalUserCreationForm))
749
        user_data = {
750
            'email': 'kpap@synnefo.org',
751
            'first_name': 'Kostas Papas',
752
            'password1': '123',
753
            'password2': '123'
754
        }
755
        form = backend.get_signup_form(provider='local',
756
                                       initial_data=user_data)
757
        self.assertTrue(form.is_valid())
758
        user_data['email'] = 'kpap@synnefo.org.'
759
        form = backend.get_signup_form(provider='local',
760
                                       initial_data=user_data)
761
        self.assertFalse(form.is_valid())
762

    
763
    def test_email_change(self):
764
        # to test existing email validation
765
        get_local_user('existing@synnefo.org')
766

    
767
        # local user
768
        user = get_local_user('kpap@synnefo.org')
769

    
770
        # login as kpap
771
        self.client.login(username='kpap@synnefo.org', password='password')
772
        r = self.client.get(ui_url('profile'), follow=True)
773
        user = r.context['request'].user
774
        self.assertTrue(user.is_authenticated())
775

    
776
        # change email is enabled
777
        r = self.client.get(ui_url('email_change'))
778
        self.assertEqual(r.status_code, 200)
779
        self.assertFalse(user.email_change_is_pending())
780

    
781
        # invalid email format
782
        data = {'new_email_address': 'existing@synnefo.org.'}
783
        r = self.client.post(ui_url('email_change'), data)
784
        form = r.context['form']
785
        self.assertFalse(form.is_valid())
786

    
787
        # request email change to an existing email fails
788
        data = {'new_email_address': 'existing@synnefo.org'}
789
        r = self.client.post(ui_url('email_change'), data)
790

    
791
        self.assertContains(r, messages.EMAIL_USED)
792

    
793
        # proper email change
794
        data = {'new_email_address': 'kpap@gmail.com'}
795
        r = self.client.post(ui_url('email_change'), data, follow=True)
796
        self.assertRedirects(r, ui_url('profile'))
797
        self.assertContains(r, messages.EMAIL_CHANGE_REGISTERED)
798
        change1 = EmailChange.objects.get()
799

    
800
        # user sees a warning
801
        r = self.client.get(ui_url('email_change'))
802
        self.assertEqual(r.status_code, 200)
803
        self.assertContains(r, messages.PENDING_EMAIL_CHANGE_REQUEST)
804
        self.assertTrue(user.email_change_is_pending())
805

    
806
        # link was sent
807
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 0)
808
        self.assertEqual(len(get_mailbox('kpap@gmail.com')), 1)
809

    
810
        # proper email change
811
        data = {'new_email_address': 'kpap@yahoo.com'}
812
        r = self.client.post(ui_url('email_change'), data, follow=True)
813
        self.assertRedirects(r, ui_url('profile'))
814
        self.assertContains(r, messages.EMAIL_CHANGE_REGISTERED)
815
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 0)
816
        self.assertEqual(len(get_mailbox('kpap@yahoo.com')), 1)
817
        change2 = EmailChange.objects.get()
818

    
819
        r = self.client.get(change1.get_url())
820
        self.assertEquals(r.status_code, 404)
821
        self.client.logout()
822

    
823
        invalid_client = Client()
824
        r = invalid_client.post(ui_url('local?'),
825
                                {'username': 'existing@synnefo.org',
826
                                 'password': 'password'})
827
        r = invalid_client.get(change2.get_url(), follow=True)
828
        self.assertEquals(r.status_code, 403)
829

    
830
        r = self.client.post(ui_url('local?next=' + change2.get_url()),
831
                             {'username': 'kpap@synnefo.org',
832
                              'password': 'password',
833
                              'next': change2.get_url()},
834
                             follow=True)
835
        self.assertRedirects(r, ui_url('profile'))
836
        user = r.context['request'].user
837
        self.assertEquals(user.email, 'kpap@yahoo.com')
838
        self.assertEquals(user.username, 'kpap@yahoo.com')
839

    
840
        self.client.logout()
841
        r = self.client.post(ui_url('local?next=' + change2.get_url()),
842
                             {'username': 'kpap@synnefo.org',
843
                              'password': 'password',
844
                              'next': change2.get_url()},
845
                             follow=True)
846
        self.assertContains(r, "Please enter a correct username and password")
847
        self.assertEqual(user.emailchanges.count(), 0)
848

    
849
        AstakosUser.objects.all().delete()
850
        Group.objects.all().delete()
851

    
852

    
853
TEST_TARGETED_ID1 = \
854
    "https://idp.synnefo.org/idp/shibboleth!ZWxhIHJlIGVsYSByZSBlbGEgcmU="
855
TEST_TARGETED_ID2 = \
856
    "https://idp.synnefo.org/idp/shibboleth!ZGUgc2UgeGFsYXNlLi4uLi4uLg=="
857
TEST_TARGETED_ID3 = \
858
    "https://idp.synnefo.org/idp/shibboleth!"
859

    
860

    
861
class TestAuthProviderViews(TestCase):
862

    
863
    def tearDown(self):
864
        AstakosUser.objects.all().delete()
865

    
866
    @im_settings(IM_MODULES=['shibboleth'], MODERATION_ENABLED=False,
867
                 SHIBBOLETH_MIGRATE_EPPN=True)
868
    def migrate_to_remote_id(self):
869
        eppn_user = get_local_user("eppn@synnefo.org")
870
        tid_user = get_local_user("tid@synnefo.org")
871
        eppn_user.add_auth_provider('shibboleth', 'EPPN')
872
        tid_user.add_auth_provider('shibboleth', TEST_TARGETED_ID1)
873

    
874
        get_user = lambda r: r.context['request'].user
875

    
876
        client = ShibbolethClient()
877
        client.set_tokens(eppn="EPPN", remote_user=TEST_TARGETED_ID2)
878
        r = client.get(ui_url('login/shibboleth?'), follow=True)
879
        self.assertTrue(get_user(r).is_authenticated())
880
        self.assertEqual(eppn_user.get_auth_provider('shibboleth').identifier,
881
                         TEST_TARGETED_ID2)
882

    
883
        client = ShibbolethClient()
884
        client.set_tokens(eppn="EPPN", remote_user=TEST_TARGETED_ID1)
885
        r = client.get(ui_url('login/shibboleth?'), follow=True)
886
        self.assertTrue(get_user(r).is_authenticated())
887
        self.assertEqual(tid_user.get_auth_provider('shibboleth').identifier,
888
                         TEST_TARGETED_ID1)
889

    
890
    @shibboleth_settings(CREATION_GROUPS_POLICY=['academic-login'],
891
                         AUTOMODERATE_POLICY=True)
892
    @im_settings(IM_MODULES=['shibboleth', 'local'], MODERATION_ENABLED=True,
893
                 HELPDESK=(('support', 'support@synnefo.org'),),
894
                 FORCE_PROFILE_UPDATE=False)
895
    def test_user(self):
896
        Profile = AuthProviderPolicyProfile
897
        Pending = PendingThirdPartyUser
898
        User = AstakosUser
899

    
900
        auth_functions.make_user("newuser@synnefo.org")
901
        get_local_user("olduser@synnefo.org")
902
        cl_olduser = ShibbolethClient()
903
        get_local_user("olduser2@synnefo.org")
904
        ShibbolethClient()
905
        cl_newuser = ShibbolethClient()
906
        cl_newuser2 = Client()
907

    
908
        academic_group, created = Group.objects.get_or_create(
909
            name='academic-login')
910
        academic_users = academic_group.user_set
911
        assert created
912
        policy_only_academic = Profile.objects.add_policy('academic_strict',
913
                                                          'shibboleth',
914
                                                          academic_group,
915
                                                          exclusive=True,
916
                                                          login=False,
917
                                                          add=False)
918

    
919
        # new academic user
920
        self.assertFalse(academic_users.filter(email='newuser@synnefo.org'))
921
        cl_newuser.set_tokens(remote_user="newusereppn",
922
                              mail="newuser@synnefo.org", surname="Lastname")
923
        r = cl_newuser.get(ui_url('login/shibboleth?'), follow=True)
924
        initial = r.context['signup_form'].initial
925
        pending = Pending.objects.get()
926
        self.assertEqual(initial.get('last_name'), 'Lastname')
927
        self.assertEqual(initial.get('email'), 'newuser@synnefo.org')
928
        identifier = pending.third_party_identifier
929
        signup_data = {'third_party_identifier': identifier,
930
                       'first_name': 'Academic',
931
                       'third_party_token': pending.token,
932
                       'last_name': 'New User',
933
                       'provider': 'shibboleth'}
934
        r = cl_newuser.post(ui_url('signup'), signup_data)
935
        self.assertContains(r, "This field is required", )
936
        signup_data['email'] = 'olduser@synnefo.org'
937
        r = cl_newuser.post(ui_url('signup'), signup_data)
938
        self.assertContains(r, "already an account with this email", )
939
        signup_data['email'] = 'newuser@synnefo.org'
940
        r = cl_newuser.post(ui_url('signup'), signup_data, follow=True)
941
        r = cl_newuser.post(ui_url('signup'), signup_data, follow=True)
942
        self.assertEqual(r.status_code, 404)
943
        newuser = User.objects.get(email="newuser@synnefo.org")
944
        activation_link = newuser.get_activation_url()
945
        self.assertTrue(academic_users.get(email='newuser@synnefo.org'))
946

    
947
        # new non-academic user
948
        signup_data = {'first_name': 'Non Academic',
949
                       'last_name': 'New User',
950
                       'provider': 'local',
951
                       'password1': 'password',
952
                       'password2': 'password'}
953
        signup_data['email'] = 'olduser@synnefo.org'
954
        r = cl_newuser2.post(ui_url('signup'), signup_data)
955
        self.assertContains(r, 'There is already an account with this '
956
                               'email address')
957
        signup_data['email'] = 'newuser@synnefo.org'
958
        r = cl_newuser2.post(ui_url('signup/'), signup_data)
959
        self.assertFalse(academic_users.filter(email='newuser@synnefo.org'))
960
        r = self.client.get(activation_link, follow=True)
961
        self.assertEqual(r.status_code, 200)
962
        self.assertContains(r, astakos_messages.INVALID_ACTIVATION_KEY)
963
        newuser = User.objects.get(email="newuser@synnefo.org")
964
        self.assertTrue(newuser.activation_sent)
965

    
966
        # activation sent, user didn't open verification url so additional
967
        # registrations invalidate the previous signups.
968
        self.assertFalse(academic_users.filter(email='newuser@synnefo.org'))
969
        r = cl_newuser.get(ui_url('login/shibboleth?'), follow=True)
970
        pending = Pending.objects.get()
971
        identifier = pending.third_party_identifier
972
        signup_data = {'third_party_identifier': identifier,
973
                       u'first_name': 'Academic γιούνικοουντ',
974
                       'third_party_token': pending.token,
975
                       'last_name': 'New User',
976
                       'provider': 'shibboleth'}
977
        signup_data['email'] = 'newuser@synnefo.org'
978
        r = cl_newuser.post(ui_url('signup'), signup_data)
979
        self.assertEqual(r.status_code, 302)
980
        newuser = User.objects.get(email="newuser@synnefo.org")
981
        self.assertTrue(newuser.activation_sent)
982
        activation_link = newuser.get_activation_url()
983
        self.assertTrue(academic_users.get(email='newuser@synnefo.org'))
984
        r = cl_newuser.get(newuser.get_activation_url(), follow=True)
985
        self.assertRedirects(r, ui_url('landing'))
986
        helpdesk_email = astakos_settings.HELPDESK[0][1]
987
        self.assertEqual(len(get_mailbox(helpdesk_email)), 1)
988
        self.assertTrue(u'AstakosUser: Academic γιούνικοουντ' in \
989
                            get_mailbox(helpdesk_email)[0].body)
990
        newuser = User.objects.get(email="newuser@synnefo.org")
991
        self.assertEqual(newuser.is_active, True)
992
        self.assertEqual(newuser.email_verified, True)
993
        cl_newuser.logout()
994

    
995
        # cannot reactivate if suspended
996
        newuser.is_active = False
997
        newuser.save()
998
        r = cl_newuser.get(newuser.get_activation_url())
999
        newuser = User.objects.get(email="newuser@synnefo.org")
1000
        self.assertFalse(newuser.is_active)
1001

    
1002
        # release suspension
1003
        newuser.is_active = True
1004
        newuser.save()
1005

    
1006
        cl_newuser.get(ui_url('login/shibboleth?'), follow=True)
1007
        local = auth.get_provider('local', newuser)
1008
        self.assertEqual(local.get_add_policy, False)
1009
        self.assertEqual(local.get_login_policy, False)
1010
        r = cl_newuser.get(local.get_add_url, follow=True)
1011
        self.assertRedirects(r, ui_url('profile'))
1012
        self.assertContains(r, 'disabled for your')
1013

    
1014
        cl_olduser.login(username='olduser@synnefo.org', password="password")
1015
        r = cl_olduser.get(ui_url('profile'), follow=True)
1016
        self.assertEqual(r.status_code, 200)
1017
        r = cl_olduser.get(ui_url('login/shibboleth?'), follow=True)
1018
        self.assertContains(r, 'Your request is missing a unique token')
1019
        cl_olduser.set_tokens(remote_user="newusereppn")
1020
        r = cl_olduser.get(ui_url('login/shibboleth?'), follow=True)
1021
        self.assertContains(r, 'already in use')
1022
        cl_olduser.set_tokens(remote_user="oldusereppn")
1023
        r = cl_olduser.get(ui_url('login/shibboleth?'), follow=True)
1024
        self.assertContains(r, 'Academic login enabled for this account')
1025

    
1026
        user = User.objects.get(email="olduser@synnefo.org")
1027
        shib_provider = user.get_auth_provider('shibboleth', 'oldusereppn')
1028
        local_provider = user.get_auth_provider('local')
1029
        self.assertEqual(shib_provider.get_remove_policy, True)
1030
        self.assertEqual(local_provider.get_remove_policy, True)
1031

    
1032
        policy_only_academic = Profile.objects.add_policy('academic_strict2',
1033
                                                          'shibboleth',
1034
                                                          academic_group,
1035
                                                          remove=False)
1036
        user.groups.add(academic_group)
1037
        shib_provider = user.get_auth_provider('shibboleth', 'oldusereppn')
1038
        local_provider = user.get_auth_provider('local')
1039
        self.assertEqual(shib_provider.get_remove_policy, False)
1040
        self.assertEqual(local_provider.get_remove_policy, True)
1041
        self.assertEqual(local_provider.get_login_policy, False)
1042

    
1043
        cl_olduser.logout()
1044
        login_data = {'username': 'olduser@synnefo.org',
1045
                      'password': 'password'}
1046
        r = cl_olduser.post(ui_url('local'), login_data, follow=True)
1047
        self.assertContains(r, "login/shibboleth'>Academic login")
1048
        Group.objects.all().delete()
1049

    
1050

    
1051
class TestAuthProvidersAPI(TestCase):
1052
    """
1053
    Test auth_providers module API
1054
    """
1055

    
1056
    def tearDown(self):
1057
        Group.objects.all().delete()
1058

    
1059
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1060
    def test_create(self):
1061
        user = auth_functions.make_user(email="kpap@synnefo.org")
1062
        user2 = auth_functions.make_user(email="kpap2@synnefo.org")
1063

    
1064
        module = 'shibboleth'
1065
        identifier = 'SHIB_UUID'
1066
        provider_params = {
1067
            'affiliation': 'UNIVERSITY',
1068
            'info': {'age': 27}
1069
        }
1070
        provider = auth.get_provider(module, user2, identifier,
1071
                                     **provider_params)
1072
        provider.add_to_user()
1073
        provider = auth.get_provider(module, user, identifier,
1074
                                     **provider_params)
1075
        provider.add_to_user()
1076
        user.email_verified = True
1077
        user.save()
1078
        self.assertRaises(Exception, provider.add_to_user)
1079
        provider = user.get_auth_provider(module, identifier)
1080
        self.assertEqual(user.get_auth_provider(
1081
            module, identifier)._instance.info.get('age'), 27)
1082

    
1083
        module = 'local'
1084
        identifier = None
1085
        provider_params = {'auth_backend': 'ldap', 'info':
1086
                          {'office': 'A1'}}
1087
        provider = auth.get_provider(module, user, identifier,
1088
                                     **provider_params)
1089
        provider.add_to_user()
1090
        self.assertFalse(provider.get_add_policy)
1091
        self.assertRaises(Exception, provider.add_to_user)
1092

    
1093
        shib = user.get_auth_provider('shibboleth',
1094
                                      'SHIB_UUID')
1095
        self.assertTrue(shib.get_remove_policy)
1096

    
1097
        local = user.get_auth_provider('local')
1098
        self.assertTrue(local.get_remove_policy)
1099

    
1100
        local.remove_from_user()
1101
        self.assertFalse(shib.get_remove_policy)
1102
        self.assertRaises(Exception, shib.remove_from_user)
1103

    
1104
        provider = user.get_auth_providers()[0]
1105
        self.assertRaises(Exception, provider.add_to_user)
1106

    
1107
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1108
    @shibboleth_settings(ADD_GROUPS_POLICY=['group1', 'group2'],
1109
                         CREATION_GROUPS_POLICY=['group-create', 'group1',
1110
                                                 'group2'])
1111
    @localauth_settings(ADD_GROUPS_POLICY=['localgroup'],
1112
                        CREATION_GROUPS_POLICY=['localgroup-create',
1113
                                                'group-create'])
1114
    def test_add_groups(self):
1115
        user = auth_functions.make_user("kpap@synnefo.org")
1116
        provider = auth.get_provider('shibboleth', user, 'test123')
1117
        provider.add_to_user()
1118
        user = AstakosUser.objects.get()
1119
        self.assertEqual(sorted(user.groups.values_list('name', flat=True)),
1120
                         sorted([u'group1', u'group2', u'group-create']))
1121

    
1122
        local = auth.get_provider('local', user)
1123
        local.add_to_user()
1124
        provider = user.get_auth_provider('shibboleth')
1125
        self.assertEqual(provider.get_add_groups_policy, ['group1', 'group2'])
1126
        provider.remove_from_user()
1127
        user = AstakosUser.objects.get()
1128
        self.assertEqual(len(user.get_auth_providers()), 1)
1129
        self.assertEqual(sorted(user.groups.values_list('name', flat=True)),
1130
                         sorted([u'group-create', u'localgroup']))
1131

    
1132
        local = user.get_auth_provider('local')
1133
        self.assertRaises(Exception, local.remove_from_user)
1134
        provider = auth.get_provider('shibboleth', user, 'test123')
1135
        provider.add_to_user()
1136
        user = AstakosUser.objects.get()
1137
        self.assertEqual(sorted(user.groups.values_list('name', flat=True)),
1138
                         sorted([u'group-create', u'group1', u'group2',
1139
                                 u'localgroup']))
1140
        Group.objects.all().delete()
1141

    
1142
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1143
    def test_policies(self):
1144
        group_old, created = Group.objects.get_or_create(name='olduser')
1145

    
1146
        astakos_settings.MODERATION_ENABLED = True
1147
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATION_GROUPS_POLICY = \
1148
            ['academic-user']
1149
        settings.ASTAKOS_AUTH_PROVIDER_GOOGLE_ADD_GROUPS_POLICY = \
1150
            ['google-user']
1151

    
1152
        user = auth_functions.make_user("kpap@synnefo.org")
1153
        user.groups.add(group_old)
1154
        user.add_auth_provider('local')
1155

    
1156
        user2 = auth_functions.make_user("kpap2@synnefo.org")
1157
        user2.add_auth_provider('shibboleth', identifier='shibid')
1158

    
1159
        user3 = auth_functions.make_user("kpap3@synnefo.org")
1160
        user3.groups.add(group_old)
1161
        user3.add_auth_provider('local')
1162
        user3.add_auth_provider('shibboleth', identifier='1234')
1163

    
1164
        self.assertTrue(user2.groups.get(name='academic-user'))
1165
        self.assertFalse(user2.groups.filter(name='olduser').count())
1166

    
1167
        local = auth_providers.get_provider('local')
1168
        self.assertTrue(local.get_add_policy)
1169

    
1170
        academic_group = Group.objects.get(name='academic-user')
1171
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1172
                                                     academic_group,
1173
                                                     exclusive=True,
1174
                                                     add=False,
1175
                                                     login=False)
1176
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1177
                                                     academic_group,
1178
                                                     exclusive=True,
1179
                                                     login=False,
1180
                                                     add=False)
1181
        # no duplicate entry gets created
1182
        self.assertEqual(academic_group.authpolicy_profiles.count(), 1)
1183

    
1184
        self.assertEqual(user2.authpolicy_profiles.count(), 0)
1185
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1186
                                                     user2,
1187
                                                     remove=False)
1188
        self.assertEqual(user2.authpolicy_profiles.count(), 1)
1189

    
1190
        local = auth_providers.get_provider('local', user2)
1191
        google = auth_providers.get_provider('google', user2)
1192
        shibboleth = auth_providers.get_provider('shibboleth', user2)
1193
        self.assertTrue(shibboleth.get_login_policy)
1194
        self.assertFalse(shibboleth.get_remove_policy)
1195
        self.assertFalse(local.get_add_policy)
1196
        self.assertFalse(local.get_add_policy)
1197
        self.assertFalse(google.get_add_policy)
1198

    
1199
        user2.groups.remove(Group.objects.get(name='academic-user'))
1200
        self.assertTrue(local.get_add_policy)
1201
        self.assertTrue(google.get_add_policy)
1202
        user2.groups.add(Group.objects.get(name='academic-user'))
1203

    
1204
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1205
                                                     user2,
1206
                                                     exclusive=True,
1207
                                                     add=True)
1208
        self.assertTrue(local.get_add_policy)
1209
        self.assertTrue(google.get_add_policy)
1210

    
1211
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_AUTOMODERATE_POLICY = True
1212
        self.assertFalse(local.get_automoderate_policy)
1213
        self.assertFalse(google.get_automoderate_policy)
1214
        self.assertTrue(shibboleth.get_automoderate_policy)
1215

    
1216
        for s in ['SHIBBOLETH_CREATION_GROUPS_POLICY',
1217
                  'GOOGLE_ADD_GROUPS_POLICY']:
1218
            delattr(settings, 'ASTAKOS_AUTH_PROVIDER_%s' % s)
1219

    
1220
    @shibboleth_settings(CREATE_POLICY=True)
1221
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1222
    def test_create_http(self):
1223
        # this should be wrapped inside a transaction
1224
        user = auth_functions.make_user(email="test@test.com")
1225
        provider = auth_providers.get_provider('shibboleth', user,
1226
                                               'test@academia.test')
1227
        provider.add_to_user()
1228
        user.get_auth_provider('shibboleth', 'test@academia.test')
1229
        provider = auth_providers.get_provider('local', user)
1230
        provider.add_to_user()
1231
        user.get_auth_provider('local')
1232

    
1233
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATE_POLICY = False
1234
        user = auth_functions.make_user("test2@test.com")
1235
        provider = auth_providers.get_provider('shibboleth', user,
1236
                                               'test@shibboleth.com',
1237
                                               **{'info': {'name':
1238
                                                           'User Test'}})
1239
        self.assertFalse(provider.get_create_policy)
1240
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATE_POLICY = True
1241
        self.assertTrue(provider.get_create_policy)
1242
        academic = provider.add_to_user()
1243

    
1244
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1245
    @shibboleth_settings(LIMIT_POLICY=2)
1246
    def test_policies(self):
1247
        user = get_local_user('kpap@synnefo.org')
1248
        user.add_auth_provider('shibboleth', identifier='1234')
1249
        user.add_auth_provider('shibboleth', identifier='12345')
1250

    
1251
        # default limit is 1
1252
        local = user.get_auth_provider('local')
1253
        self.assertEqual(local.get_add_policy, False)
1254

    
1255
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_LIMIT_POLICY = 3
1256
        academic = user.get_auth_provider('shibboleth',
1257
                                          identifier='1234')
1258
        self.assertEqual(academic.get_add_policy, False)
1259
        newacademic = auth_providers.get_provider('shibboleth', user,
1260
                                                  identifier='123456')
1261
        self.assertEqual(newacademic.get_add_policy, True)
1262
        user.add_auth_provider('shibboleth', identifier='123456')
1263
        self.assertEqual(academic.get_add_policy, False)
1264
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_LIMIT_POLICY = 1
1265

    
1266
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1267
    @shibboleth_settings(LIMIT_POLICY=2)
1268
    def test_messages(self):
1269
        user = get_local_user('kpap@synnefo.org')
1270
        user.add_auth_provider('shibboleth', identifier='1234')
1271
        user.add_auth_provider('shibboleth', identifier='12345')
1272
        provider = auth_providers.get_provider('shibboleth')
1273
        self.assertEqual(provider.get_message('title'), 'Academic')
1274
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_TITLE = 'New title'
1275
        # regenerate messages cache
1276
        provider = auth_providers.get_provider('shibboleth')
1277
        self.assertEqual(provider.get_message('title'), 'New title')
1278
        self.assertEqual(provider.get_message('login_title'),
1279
                         'New title LOGIN')
1280
        self.assertEqual(provider.get_login_title_msg, 'New title LOGIN')
1281
        self.assertEqual(provider.get_module_icon,
1282
                         settings.MEDIA_URL + 'im/auth/icons/shibboleth.png')
1283
        self.assertEqual(provider.get_module_medium_icon,
1284
                         settings.MEDIA_URL +
1285
                         'im/auth/icons-medium/shibboleth.png')
1286

    
1287
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_TITLE = None
1288
        provider = auth_providers.get_provider('shibboleth', user, '12345')
1289
        self.assertEqual(provider.get_method_details_msg,
1290
                         'Account: 12345')
1291
        provider = auth_providers.get_provider('shibboleth', user, '1234')
1292
        self.assertEqual(provider.get_method_details_msg,
1293
                         'Account: 1234')
1294

    
1295
        provider = auth_providers.get_provider('shibboleth', user, '1234')
1296
        self.assertEqual(provider.get_not_active_msg,
1297
                         "'Academic login' is disabled.")
1298

    
1299
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1300
    @shibboleth_settings(LIMIT_POLICY=2)
1301
    def test_templates(self):
1302
        user = get_local_user('kpap@synnefo.org')
1303
        user.add_auth_provider('shibboleth', identifier='1234')
1304
        user.add_auth_provider('shibboleth', identifier='12345')
1305

    
1306
        provider = auth_providers.get_provider('shibboleth')
1307
        self.assertEqual(provider.get_template('login'),
1308
                         'im/auth/shibboleth_login.html')
1309
        provider = auth_providers.get_provider('google')
1310
        self.assertEqual(provider.get_template('login'),
1311
                         'im/auth/generic_login.html')
1312

    
1313

    
1314
class TestActivationBackend(TestCase):
1315

    
1316
    def setUp(self):
1317
        # dummy call to pass through logging middleware
1318
        self.client.get(ui_url(''))
1319

    
1320
    @im_settings(RE_USER_EMAIL_PATTERNS=['.*@synnefo.org'])
1321
    @shibboleth_settings(AUTOMODERATE_POLICY=True)
1322
    def test_policies(self):
1323
        backend = activation_backends.get_backend()
1324

    
1325
        # email matches RE_USER_EMAIL_PATTERNS
1326
        user1 = get_local_user('kpap@synnefo.org', moderated=False,
1327
                               is_active=False, email_verified=False)
1328
        backend.handle_verification(user1, user1.verification_code)
1329
        self.assertEqual(user1.accepted_policy, 'email')
1330

    
1331
        # manually moderated
1332
        user2 = get_local_user('kpap@synnefo-bad.org', moderated=False,
1333
                               is_active=False, email_verified=False)
1334

    
1335
        backend.handle_verification(user2, user2.verification_code)
1336
        self.assertEqual(user2.moderated, False)
1337
        backend.handle_moderation(user2)
1338
        self.assertEqual(user2.moderated, True)
1339
        self.assertEqual(user2.accepted_policy, 'manual')
1340

    
1341
        # autoaccept due to provider automoderate policy
1342
        user3 = get_local_user('kpap2@synnefo-bad.org', moderated=False,
1343
                               is_active=False, email_verified=False)
1344
        user3.auth_providers.all().delete()
1345
        user3.add_auth_provider('shibboleth', identifier='shib123')
1346
        backend.handle_verification(user3, user3.verification_code)
1347
        self.assertEqual(user3.moderated, True)
1348
        self.assertEqual(user3.accepted_policy, 'auth_provider_shibboleth')
1349

    
1350
    @im_settings(MODERATION_ENABLED=False,
1351
                 MANAGERS=(('Manager',
1352
                            'manager@synnefo.org'),),
1353
                 HELPDESK=(('Helpdesk',
1354
                            'helpdesk@synnefo.org'),),
1355
                 ADMINS=(('Admin', 'admin@synnefo.org'), ))
1356
    def test_without_moderation(self):
1357
        backend = activation_backends.get_backend()
1358
        form = backend.get_signup_form('local')
1359
        self.assertTrue(isinstance(form, forms.LocalUserCreationForm))
1360

    
1361
        user_data = {
1362
            'email': 'kpap@synnefo.org',
1363
            'first_name': 'Kostas Papas',
1364
            'password1': '123',
1365
            'password2': '123'
1366
        }
1367
        form = backend.get_signup_form('local', user_data)
1368
        user = form.create_user()
1369
        self.assertEqual(user.is_active, False)
1370
        self.assertEqual(user.email_verified, False)
1371

    
1372
        # step one, registration
1373
        result = backend.handle_registration(user)
1374
        user = AstakosUser.objects.get()
1375
        self.assertEqual(user.is_active, False)
1376
        self.assertEqual(user.email_verified, False)
1377
        self.assertTrue(user.verification_code)
1378
        self.assertEqual(result.status, backend.Result.PENDING_VERIFICATION)
1379
        backend.send_result_notifications(result, user)
1380
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
1381
        self.assertEqual(len(mail.outbox), 1)
1382

    
1383
        # step two, verify email (automatically
1384
        # moderates/accepts user, since moderation is disabled)
1385
        user = AstakosUser.objects.get()
1386
        valid_code = user.verification_code
1387

    
1388
        # test invalid code
1389
        result = backend.handle_verification(user, valid_code)
1390
        backend.send_result_notifications(result, user)
1391
        self.assertEqual(len(get_mailbox('manager@synnefo.org')), 1)
1392
        self.assertEqual(len(get_mailbox('helpdesk@synnefo.org')), 1)
1393
        self.assertEqual(len(get_mailbox('admin@synnefo.org')), 1)
1394
        # verification + activated + greeting = 3
1395
        self.assertEqual(len(mail.outbox), 3)
1396
        user = AstakosUser.objects.get()
1397
        self.assertEqual(user.is_active, True)
1398
        self.assertEqual(user.moderated, True)
1399
        self.assertTrue(user.moderated_at)
1400
        self.assertEqual(user.email_verified, True)
1401
        self.assertTrue(user.activation_sent)
1402

    
1403
    @im_settings(MODERATION_ENABLED=True,
1404
                 MANAGERS=(('Manager',
1405
                            'manager@synnefo.org'),),
1406
                 HELPDESK=(('Helpdesk',
1407
                            'helpdesk@synnefo.org'),),
1408
                 ADMINS=(('Admin', 'admin@synnefo.org'), ))
1409
    def test_with_moderation(self):
1410

    
1411
        backend = activation_backends.get_backend()
1412
        form = backend.get_signup_form('local')
1413
        self.assertTrue(isinstance(form, forms.LocalUserCreationForm))
1414

    
1415
        user_data = {
1416
            'email': 'kpap@synnefo.org',
1417
            'first_name': 'Kostas Papas',
1418
            'password1': '123',
1419
            'password2': '123'
1420
        }
1421
        form = backend.get_signup_form(provider='local',
1422
                                       initial_data=user_data)
1423
        user = form.create_user()
1424
        self.assertEqual(user.is_active, False)
1425
        self.assertEqual(user.email_verified, False)
1426

    
1427
        # step one, registration
1428
        result = backend.handle_registration(user)
1429
        user = AstakosUser.objects.get()
1430
        self.assertEqual(user.is_active, False)
1431
        self.assertEqual(user.email_verified, False)
1432
        self.assertTrue(user.verification_code)
1433
        self.assertEqual(result.status, backend.Result.PENDING_VERIFICATION)
1434
        backend.send_result_notifications(result, user)
1435
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
1436
        self.assertEqual(len(mail.outbox), 1)
1437

    
1438
        # step two, verifying email
1439
        user = AstakosUser.objects.get()
1440
        valid_code = user.verification_code
1441
        invalid_code = user.verification_code + 'invalid'
1442

    
1443
        # test invalid code
1444
        result = backend.handle_verification(user, invalid_code)
1445
        self.assertEqual(result.status, backend.Result.ERROR)
1446
        backend.send_result_notifications(result, user)
1447
        user = AstakosUser.objects.get()
1448
        self.assertEqual(user.is_active, False)
1449
        self.assertEqual(user.moderated, False)
1450
        self.assertEqual(user.moderated_at, None)
1451
        self.assertEqual(user.email_verified, False)
1452
        self.assertTrue(user.activation_sent)
1453

    
1454
        # test valid code
1455
        user = AstakosUser.objects.get()
1456
        result = backend.handle_verification(user, valid_code)
1457
        backend.send_result_notifications(result, user)
1458
        self.assertEqual(len(get_mailbox('manager@synnefo.org')), 1)
1459
        self.assertEqual(len(get_mailbox('helpdesk@synnefo.org')), 1)
1460
        self.assertEqual(len(get_mailbox('admin@synnefo.org')), 1)
1461
        self.assertEqual(len(mail.outbox), 2)
1462
        user = AstakosUser.objects.get()
1463
        self.assertEqual(user.moderated, False)
1464
        self.assertEqual(user.moderated_at, None)
1465
        self.assertEqual(user.email_verified, True)
1466
        self.assertTrue(user.activation_sent)
1467

    
1468
        # test code reuse
1469
        result = backend.handle_verification(user, valid_code)
1470
        self.assertEqual(result.status, backend.Result.ERROR)
1471
        user = AstakosUser.objects.get()
1472
        self.assertEqual(user.is_active, False)
1473
        self.assertEqual(user.moderated, False)
1474
        self.assertEqual(user.moderated_at, None)
1475
        self.assertEqual(user.email_verified, True)
1476
        self.assertTrue(user.activation_sent)
1477

    
1478
        # valid code on verified user
1479
        user = AstakosUser.objects.get()
1480
        valid_code = user.verification_code
1481
        result = backend.handle_verification(user, valid_code)
1482
        self.assertEqual(result.status, backend.Result.ERROR)
1483

    
1484
        # step three, moderation user
1485
        user = AstakosUser.objects.get()
1486
        result = backend.handle_moderation(user)
1487
        backend.send_result_notifications(result, user)
1488

    
1489
        user = AstakosUser.objects.get()
1490
        self.assertEqual(user.is_active, True)
1491
        self.assertEqual(user.moderated, True)
1492
        self.assertTrue(user.moderated_at)
1493
        self.assertEqual(user.email_verified, True)
1494
        self.assertTrue(user.activation_sent)
1495

    
1496

    
1497
class TestWebloginRedirect(TestCase):
1498

    
1499
    @with_settings(settings, COOKIE_DOMAIN='.astakos.synnefo.org')
1500
    def test_restricts_domains(self):
1501
        get_local_user('user1@synnefo.org')
1502

    
1503
        # next url construct helpers
1504
        weblogin = lambda nxt: reverse('weblogin') + '?next=%s' % nxt
1505
        weblogin_quoted = lambda nxt: reverse('weblogin') + '?next=%s' % \
1506
            urllib.quote_plus(nxt)
1507

    
1508
        # common cases
1509
        invalid_domain = weblogin("https://www.invaliddomain.synnefo.org")
1510
        invalid_scheme = weblogin("customscheme://localhost")
1511
        invalid_scheme_with_valid_domain = \
1512
            weblogin("http://www.invaliddomain.com")
1513
        valid_scheme = weblogin("pithos://localhost/")
1514
        # to be used in assertRedirects
1515
        valid_scheme_quoted = weblogin_quoted("pithos://localhost/")
1516

    
1517
        # not authenticated, redirects to login which contains next param with
1518
        # additional nested quoted next params
1519
        r = self.client.get(valid_scheme, follow=True)
1520
        login_redirect = reverse('login') + '?next=' + \
1521
            urllib.quote_plus("http://testserver" + valid_scheme_quoted)
1522
        self.assertRedirects(r, login_redirect)
1523

    
1524
        # authenticate client
1525
        self.client.login(username="user1@synnefo.org", password="password")
1526

    
1527
        # valid scheme
1528
        r = self.client.get(valid_scheme, follow=True)
1529
        url = r.redirect_chain[1][0]
1530
        # scheme preserved
1531
        self.assertTrue(url.startswith('pithos://localhost/'))
1532
        # redirect contains token param
1533
        params = urlparse.urlparse(url.replace('pithos', 'https'),
1534
                                   scheme='https').query
1535
        params = urlparse.parse_qs(params)
1536
        self.assertEqual(params['token'][0],
1537
                         AstakosUser.objects.get().auth_token)
1538
        # does not contain uuid
1539
        # reverted for 0.14.2 to support old pithos desktop clients
1540
        #self.assertFalse('uuid' in params)
1541

    
1542
        # invalid cases
1543
        r = self.client.get(invalid_scheme, follow=True)
1544
        self.assertEqual(r.status_code, 403)
1545

    
1546
        r = self.client.get(invalid_scheme_with_valid_domain, follow=True)
1547
        self.assertEqual(r.status_code, 403)
1548

    
1549
        r = self.client.get(invalid_domain, follow=True)
1550
        self.assertEqual(r.status_code, 403)