Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tests.py @ 4bdd7e3d

History | View | Annotate | Download (24 kB)

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

    
34
import datetime
35

    
36
from django.test import TestCase, Client
37
from django.conf import settings
38
from django.core import mail
39

    
40
from astakos.im.target.shibboleth import Tokens as ShibbolethTokens
41
from astakos.im.models import *
42
from astakos.im import functions
43
from astakos.im import settings as astakos_settings
44

    
45
from urllib import quote
46

    
47
from astakos.im import messages
48

    
49
class ShibbolethClient(Client):
50
    """
51
    A shibboleth agnostic client.
52
    """
53
    VALID_TOKENS = filter(lambda x: not x.startswith("_"), dir(ShibbolethTokens))
54

    
55
    def __init__(self, *args, **kwargs):
56
        self.tokens = kwargs.pop('tokens', {})
57
        super(ShibbolethClient, self).__init__(*args, **kwargs)
58

    
59
    def set_tokens(self, **kwargs):
60
        for key, value in kwargs.iteritems():
61
            key = 'SHIB_%s' % key.upper()
62
            if not key in self.VALID_TOKENS:
63
                raise Exception('Invalid shibboleth token')
64

    
65
            self.tokens[key] = value
66

    
67
    def unset_tokens(self, *keys):
68
        for key in keys:
69
            key = 'SHIB_%s' % param.upper()
70
            if key in self.tokens:
71
                del self.tokens[key]
72

    
73
    def reset_tokens(self):
74
        self.tokens = {}
75

    
76
    def get_http_token(self, key):
77
        http_header = getattr(ShibbolethTokens, key)
78
        return http_header
79

    
80
    def request(self, **request):
81
        """
82
        Transform valid shibboleth tokens to http headers
83
        """
84
        for token, value in self.tokens.iteritems():
85
            request[self.get_http_token(token)] = value
86

    
87
        for param in request.keys():
88
            key = 'SHIB_%s' % param.upper()
89
            if key in self.VALID_TOKENS:
90
                request[self.get_http_token(key)] = request[param]
91
                del request[param]
92

    
93
        return super(ShibbolethClient, self).request(**request)
94

    
95

    
96
def get_local_user(username, **kwargs):
97
        try:
98
            return AstakosUser.objects.get(email=username)
99
        except:
100
            user_params = {
101
                'username': username,
102
                'email': username,
103
                'is_active': True,
104
                'activation_sent': datetime.now(),
105
                'email_verified': True,
106
                'provider': 'local'
107
            }
108
            user_params.update(kwargs)
109
            user = AstakosUser(**user_params)
110
            user.set_password(kwargs.get('password', 'password'))
111
            user.save()
112
            user.add_auth_provider('local', auth_backend='astakos')
113
            if kwargs.get('is_active', True):
114
                user.is_active = True
115
            else:
116
                user.is_active = False
117
            user.save()
118
            return user
119

    
120

    
121
def get_mailbox(email):
122
    mails = []
123
    for sent_email in mail.outbox:
124
        for recipient in sent_email.recipients():
125
            if email in recipient:
126
                mails.append(sent_email)
127
    return mails
128

    
129

    
130
class ShibbolethTests(TestCase):
131
    """
132
    Testing shibboleth authentication.
133
    """
134

    
135
    fixtures = ['groups']
136

    
137
    def setUp(self):
138
        self.client = ShibbolethClient()
139
        settings.ASTAKOS_IM_MODULES = ['local', 'shibboleth']
140
        settings.ASTAKOS_MODERATION_ENABLED = True
141

    
142
    def test_create_account(self):
143

    
144
        client = ShibbolethClient()
145

    
146
        # shibboleth views validation
147
        # eepn required
148
        r = client.get('/im/login/shibboleth?', follow=True)
149
        self.assertContains(r, messages.SHIBBOLETH_MISSING_EPPN)
150
        client.set_tokens(eppn="kpapeppn")
151

    
152
        # shibboleth user info required
153
        r = client.get('/im/login/shibboleth?', follow=True)
154
        self.assertContains(r, messages.SHIBBOLETH_MISSING_NAME)
155

    
156
        # shibboleth logged us in
157
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppn", cn="1",
158
                          ep_affiliation="Test Affiliation")
159
        r = client.get('/im/login/shibboleth?')
160
        self.assertEqual(r.status_code, 200)
161

    
162
        # astakos asks if we want to add shibboleth
163
        self.assertContains(r, "Already have an account?")
164

    
165
        # a new pending user created
166
        pending_user = PendingThirdPartyUser.objects.get(
167
            third_party_identifier="kpapeppn")
168
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
169
        # keep the token for future use
170
        token = pending_user.token
171
        # from now on no shibboleth headers are sent to the server
172
        client.reset_tokens()
173

    
174
        # this is the old way, it should fail, to avoid pending user take over
175
        r = client.get('/im/shibboleth/signup/%s' % pending_user.username)
176
        self.assertEqual(r.status_code, 404)
177

    
178
        # this is the signup unique url associated with the pending user created
179
        r = client.get('/im/signup/?third_party_token=%s' % token)
180
        form = r.context['form']
181
        post_data = {'third_party_identifier': pending_user.third_party_identifier,
182
                     'first_name': 'Kostas',
183
                     'third_party_token': token,
184
                     'last_name': 'Mitroglou',
185
                     'provider': 'shibboleth'
186
                    }
187

    
188
        # invlid email
189
        post_data['email'] = 'kpap'
190
        r = client.post('/im/signup', post_data)
191
        self.assertContains(r, token)
192

    
193
        # existing email
194
        existing_user = get_local_user('test@test.com')
195
        post_data['email'] = 'test@test.com'
196
        r = client.post('/im/signup', post_data)
197
        self.assertContains(r, messages.EMAIL_USED)
198
        existing_user.delete()
199

    
200
        # and finally a valid signup
201
        post_data['email'] = 'kpap@grnet.gr'
202
        r = client.post('/im/signup', post_data)
203
        self.assertEqual(r.status_code, 200)
204

    
205
        # everything is ok in our db
206
        self.assertEqual(AstakosUser.objects.count(), 1)
207
        self.assertEqual(AstakosUserAuthProvider.objects.count(), 1)
208
        self.assertEqual(PendingThirdPartyUser.objects.count(), 0)
209

    
210
        # provider info stored
211
        provider = AstakosUserAuthProvider.objects.get(module="shibboleth")
212
        self.assertEqual(provider.affiliation, 'Test Affiliation')
213
        self.assertEqual(provider.info, {u'email': u'kpap@grnet.gr',
214
                                         u'eppn': u'kpapeppn'})
215

    
216
        # lets login (not activated yet)
217
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppn", cn="1", )
218
        r = client.get("/im/login/shibboleth?", follow=True)
219
        self.assertContains(r, "Your request is pending activation")
220
        r = client.get("/im/profile", follow=True)
221
        self.assertRedirects(r, 'http://testserver/im/?next=%2Fim%2Fprofile')
222

    
223
        # admin activates our user
224
        u = AstakosUser.objects.get(username="kpap@grnet.gr")
225
        functions.activate(u)
226
        self.assertEqual(u.is_active, True)
227

    
228
        # we see our profile
229
        r = client.get("/im/login/shibboleth?", follow=True)
230
        self.assertRedirects(r, '/im/profile')
231
        self.assertEqual(r.status_code, 200)
232

    
233
    def test_existing(self):
234
        """
235
        Test adding of third party login to an existing account
236
        """
237

    
238
        # this is our existing user
239
        existing_user = get_local_user('kpap@grnet.gr')
240

    
241
        client = ShibbolethClient()
242
        # shibboleth logged us in, notice that we use different email
243
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1", )
244
        r = client.get("/im/login/shibboleth?")
245

    
246
        # astakos asks if we want to switch a local account to shibboleth
247
        self.assertContains(r, "Already have an account?")
248

    
249
        # a new pending user created
250
        pending_user = PendingThirdPartyUser.objects.get()
251
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
252
        pending_key = pending_user.token
253
        client.reset_tokens()
254

    
255
        # we choose to add shibboleth to an our existing account
256
        # we get redirected to login page with the pending token set
257
        r = client.get('/im/login?key=%s' % pending_key)
258
        post_data = {'password': 'password',
259
                     'username': 'kpap@grnet.gr',
260
                     'key': pending_key}
261
        r = client.post('/im/local', post_data, follow=True)
262
        self.assertRedirects(r, "/im/profile")
263
        self.assertContains(r, "Your new login method has been added")
264

    
265
        self.assertTrue(existing_user.has_auth_provider('shibboleth'))
266
        self.assertTrue(existing_user.has_auth_provider('local',
267
                                                        auth_backend='astakos'))
268
        client.logout()
269

    
270
        # check that we cannot assign same third party provide twice
271
        r = client.get('/im/login?key=%s' % pending_key)
272
        post_data = {'password': 'password',
273
                     'username': 'kpap@grnet.gr',
274
                     'key': pending_key}
275
        r = self.client.post('/im/local', post_data, follow=True)
276
        self.assertContains(r, "Failed to assign new login method")
277
        self.client.logout()
278
        client.logout()
279

    
280
        # look Ma, i can login with both my shibboleth and local account
281
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
282
        r = client.get("/im/login/shibboleth?", follow=True)
283
        self.assertTrue(r.context['request'].user.is_authenticated())
284
        self.assertTrue(r.context['request'].user.email == "kpap@grnet.gr")
285
        self.assertRedirects(r, '/im/profile')
286
        self.assertEqual(r.status_code, 200)
287
        client.logout()
288
        client.reset_tokens()
289

    
290
        # logged out
291
        r = client.get("/im/profile", follow=True)
292
        self.assertFalse(r.context['request'].user.is_authenticated())
293

    
294
        # login with local account also works
295
        post_data = {'password': 'password',
296
                     'username': 'kpap@grnet.gr'}
297
        r = self.client.post('/im/local', post_data, follow=True)
298
        self.assertTrue(r.context['request'].user.is_authenticated())
299
        self.assertTrue(r.context['request'].user.email == "kpap@grnet.gr")
300
        self.assertRedirects(r, '/im/profile')
301
        self.assertEqual(r.status_code, 200)
302

    
303
        # cannot add the same eppn
304
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn", cn="1", )
305
        r = client.get("/im/login/shibboleth?", follow=True)
306
        self.assertRedirects(r, '/im/profile')
307
        self.assertTrue(r.status_code, 200)
308
        self.assertEquals(existing_user.auth_providers.count(), 2)
309

    
310
        # but can add additional eppn
311
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn2",
312
                          cn="1", ep_affiliation="affil2")
313
        r = client.get("/im/login/shibboleth?", follow=True)
314
        new_provider = existing_user.auth_providers.get(identifier="kpapeppn2")
315
        self.assertRedirects(r, '/im/profile')
316
        self.assertTrue(r.status_code, 200)
317
        self.assertEquals(existing_user.auth_providers.count(), 3)
318
        self.assertEqual(new_provider.affiliation, 'affil2')
319
        client.logout()
320
        client.reset_tokens()
321

    
322
        # cannot login with another eppn
323
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppninvalid", cn="1")
324
        r = client.get("/im/login/shibboleth?", follow=True)
325
        self.assertFalse(r.context['request'].user.is_authenticated())
326

    
327
        # lets remove local password
328
        user = AstakosUser.objects.get(username="kpap@grnet.gr",
329
                                       email="kpap@grnet.gr")
330
        remove_local_url = user.get_provider_remove_url('local')
331
        remove_shibbo_url = user.get_provider_remove_url('shibboleth',
332
                                                         identifier='kpapeppn')
333
        remove_shibbo2_url = user.get_provider_remove_url('shibboleth',
334
                                                         identifier='kpapeppn2')
335
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
336
        r = client.get("/im/login/shibboleth?", follow=True)
337
        client.reset_tokens()
338

    
339
        # TODO: this view should use POST
340
        r = client.get(remove_local_url)
341
        # 2 providers left
342
        self.assertEqual(user.auth_providers.count(), 2)
343
        r = client.get(remove_shibbo2_url)
344
        # 1 provider left
345
        self.assertEqual(user.auth_providers.count(), 1)
346
        # cannot remove last provider
347
        r = client.get(remove_shibbo_url)
348
        self.assertEqual(r.status_code, 403)
349
        self.client.logout()
350

    
351
        # cannot login using local credentials (notice we use another client)
352
        post_data = {'password': 'password',
353
                     'username': 'kpap@grnet.gr'}
354
        r = self.client.post('/im/local', post_data, follow=True)
355
        self.assertFalse(r.context['request'].user.is_authenticated())
356

    
357
        # we can reenable the local provider by setting a password
358
        r = client.get("/im/password_change", follow=True)
359
        r = client.post("/im/password_change", {'new_password1':'111',
360
                                                'new_password2': '111'},
361
                        follow=True)
362
        user = r.context['request'].user
363
        self.assertTrue(user.has_auth_provider('local'))
364
        self.assertTrue(user.has_auth_provider('shibboleth'))
365
        self.assertTrue(user.check_password('111'))
366
        self.assertTrue(user.has_usable_password())
367
        self.client.logout()
368

    
369
        # now we can login
370
        post_data = {'password': '111',
371
                     'username': 'kpap@grnet.gr'}
372
        r = self.client.post('/im/local', post_data, follow=True)
373
        self.assertTrue(r.context['request'].user.is_authenticated())
374

    
375
        client.reset_tokens()
376

    
377
        # we cannot take over another shibboleth identifier
378
        user2 = get_local_user('another@grnet.gr')
379
        user2.add_auth_provider('shibboleth', identifier='existingeppn')
380
        # login
381
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
382
        r = client.get("/im/login/shibboleth?", follow=True)
383
        # try to assign existing shibboleth identifier of another user
384
        client.set_tokens(mail="kpap_second@shibboleth.gr", eppn="existingeppn", cn="1")
385
        r = client.get("/im/login/shibboleth?", follow=True)
386
        self.assertContains(r, 'Account already exists')
387

    
388

    
389
class LocalUserTests(TestCase):
390

    
391
    fixtures = ['groups']
392

    
393
    def setUp(self):
394
        from django.conf import settings
395
        settings.ADMINS = (('admin', 'support@cloud.grnet.gr'),)
396
        settings.SERVER_EMAIL = 'no-reply@grnet.gr'
397

    
398
    def test_no_moderation(self):
399
        # disable moderation
400
        astakos_settings.MODERATION_ENABLED = False
401

    
402
        # create a new user
403
        r = self.client.get("/im/signup")
404
        self.assertEqual(r.status_code, 200)
405
        data = {'email':'kpap@grnet.gr', 'password1':'password',
406
                'password2':'password', 'first_name': 'Kostas',
407
                'last_name': 'Mitroglou', 'provider': 'local'}
408
        r = self.client.post("/im/signup", data)
409

    
410
        # user created
411
        self.assertEqual(AstakosUser.objects.count(), 1)
412
        user = AstakosUser.objects.get(username="kpap@grnet.gr",
413
                                       email="kpap@grnet.gr")
414
        self.assertEqual(user.username, 'kpap@grnet.gr')
415
        self.assertEqual(user.has_auth_provider('local'), True)
416
        self.assertFalse(user.is_active)
417

    
418
        # user (but not admin) gets notified
419
        self.assertEqual(len(get_mailbox('support@cloud.grnet.gr')), 0)
420
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 1)
421
        astakos_settings.MODERATION_ENABLED = True
422

    
423
    def test_local_provider(self):
424
        # enable moderation
425
        astakos_settings.MODERATION_ENABLED = True
426

    
427
        # create a user
428
        r = self.client.get("/im/signup")
429
        self.assertEqual(r.status_code, 200)
430
        data = {'email':'kpap@grnet.gr', 'password1':'password',
431
                'password2':'password', 'first_name': 'Kostas',
432
                'last_name': 'Mitroglou', 'provider': 'local'}
433
        r = self.client.post("/im/signup", data)
434

    
435
        # user created
436
        self.assertEqual(AstakosUser.objects.count(), 1)
437
        user = AstakosUser.objects.get(username="kpap@grnet.gr",
438
                                       email="kpap@grnet.gr")
439
        self.assertEqual(user.username, 'kpap@grnet.gr')
440
        self.assertEqual(user.has_auth_provider('local'), True)
441
        self.assertFalse(user.is_active) # not activated
442
        self.assertFalse(user.email_verified) # not verified
443
        self.assertFalse(user.activation_sent) # activation automatically sent
444

    
445
        # admin gets notified and activates the user from the command line
446
        self.assertEqual(len(get_mailbox('support@cloud.grnet.gr')), 1)
447
        functions.send_activation(user)
448

    
449
        # user activation fields updated and user gets notified via email
450
        user = AstakosUser.objects.get(pk=user.pk)
451
        self.assertTrue(user.activation_sent)
452
        self.assertFalse(user.email_verified)
453
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 1)
454

    
455
        # user forgot she got registered and tries to submit registration
456
        # form. Notice the upper case in email
457
        data = {'email':'KPAP@grnet.gr', 'password1':'password',
458
                'password2':'password', 'first_name': 'Kostas',
459
                'last_name': 'Mitroglou', 'provider': 'local'}
460
        r = self.client.post("/im/signup", data)
461
        self.assertContains(r, messages.EMAIL_USED)
462

    
463
        # hmmm, email exists; lets get the password
464
        r = self.client.get('/im/local/password_reset')
465
        self.assertEqual(r.status_code, 200)
466
        r = self.client.post('/im/local/password_reset', {'email':
467
                                                          'kpap@grnet.gr'})
468
        # she can't because account is not active yet
469
        self.assertContains(r, "doesn't have an associated user account")
470

    
471
        # moderation is enabled so no automatic activation can be send
472
        r = self.client.get('/im/send/activation/%d' % user.pk)
473
        self.assertEqual(r.status_code, 403)
474
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 1)
475

    
476
        # also she cannot login
477
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
478
                                                 'password': 'password'})
479
        self.assertContains(r, 'You have not followed the activation link')
480
        self.assertNotContains(r, 'Resend activation')
481
        self.assertFalse(r.context['request'].user.is_authenticated())
482
        self.assertFalse('_pithos2_a' in self.client.cookies)
483

    
484
        # same with disabled moderation
485
        astakos_settings.MODERATION_ENABLED = False
486
        r = self.client.post('/im/local/password_reset', {'email':
487
                                                          'kpap@grnet.gr'})
488
        self.assertContains(r, "doesn't have an associated user account")
489
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
490
                                                 'password': 'password'})
491
        self.assertContains(r, 'You have not followed the activation link')
492
        self.assertContains(r, 'Resend activation')
493
        self.assertFalse(r.context['request'].user.is_authenticated())
494
        self.assertFalse('_pithos2_a' in self.client.cookies)
495

    
496
        # user sees the message and resends activation
497
        r = self.client.get('/im/send/activation/%d' % user.pk)
498
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 2)
499

    
500
        # switch back moderation setting
501
        astakos_settings.MODERATION_ENABLED = True
502
        r = self.client.get(user.get_activation_url(), follow=True)
503
        self.assertRedirects(r, "/im/profile")
504
        self.assertContains(r, "kpap@grnet.gr")
505
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 3)
506

    
507
        user = AstakosUser.objects.get(pk=user.pk)
508
        # user activated and logged in, token cookie set
509
        self.assertTrue(r.context['request'].user.is_authenticated())
510
        self.assertTrue('_pithos2_a' in self.client.cookies)
511
        cookies = self.client.cookies
512
        self.assertTrue(quote(user.auth_token) in cookies.get('_pithos2_a').value)
513
        r = self.client.get('/im/logout', follow=True)
514
        r = self.client.get('/im/')
515
        # user logged out, token cookie removed
516
        self.assertFalse(r.context['request'].user.is_authenticated())
517
        self.assertFalse(self.client.cookies.get('_pithos2_a').value)
518
        # https://docs.djangoproject.com/en/dev/topics/testing/#persistent-state
519
        del self.client.cookies['_pithos2_a']
520

    
521
        # user can login
522
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
523
                                           'password': 'password'},
524
                                          follow=True)
525
        self.assertTrue(r.context['request'].user.is_authenticated())
526
        self.assertTrue('_pithos2_a' in self.client.cookies)
527
        cookies = self.client.cookies
528
        self.assertTrue(quote(user.auth_token) in cookies.get('_pithos2_a').value)
529
        self.client.get('/im/logout', follow=True)
530

    
531
        # user forgot password
532
        old_pass = user.password
533
        r = self.client.get('/im/local/password_reset')
534
        self.assertEqual(r.status_code, 200)
535
        r = self.client.post('/im/local/password_reset', {'email':
536
                                                          'kpap@grnet.gr'})
537
        self.assertEqual(r.status_code, 302)
538
        # email sent
539
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 4)
540

    
541
        # user visits change password link
542
        r = self.client.get(user.get_password_reset_url())
543
        r = self.client.post(user.get_password_reset_url(),
544
                            {'new_password1':'newpass',
545
                             'new_password2':'newpass'})
546

    
547
        user = AstakosUser.objects.get(pk=user.pk)
548
        self.assertNotEqual(old_pass, user.password)
549

    
550
        # old pass is not usable
551
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
552
                                           'password': 'password'})
553
        self.assertContains(r, messages.ACCOUNT_AUTHENTICATION_FAILED)
554
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
555
                                           'password': 'newpass'},
556
                                           follow=True)
557
        self.assertTrue(r.context['request'].user.is_authenticated())
558
        self.client.logout()
559

    
560
        # tests of special local backends
561
        user = AstakosUser.objects.get(pk=user.pk)
562
        user.auth_providers.filter(module='local').update(auth_backend='ldap')
563
        user.save()
564

    
565
        # non astakos local backends do not support password reset
566
        r = self.client.get('/im/local/password_reset')
567
        self.assertEqual(r.status_code, 200)
568
        r = self.client.post('/im/local/password_reset', {'email':
569
                                                          'kpap@grnet.gr'})
570
        # she can't because account is not active yet
571
        self.assertContains(r, "Password change for this account is not"
572
                                " supported")
573