Revision e5966bd9

b/snf-astakos-app/astakos/im/auth_backends.py
47 47
    """
48 48
    def authenticate(self, email=None, auth_token=None):
49 49
        try:
50
            user = AstakosUser.objects.get(email__iexact=email, is_active=True)
51
            if user.auth_token == auth_token:
52
                return user
50
            user = AstakosUser.objects.get_by_identifier(email, is_active=True,
51
                                                        auth_token=auth_token)
52
            return user
53 53
        except AstakosUser.DoesNotExist:
54 54
            return None
55 55
        else:
......
72 72
    """
73 73
    def authenticate(self, username=None, password=None):
74 74
        # First check whether a user having this email exists
75
        users = AstakosUser.objects.filter(email__iexact=username)
76
        for user in users:
75
        try:
76
            user = AstakosUser.objects.get_by_identifier(username,
77
                                                         is_active=True)
77 78
            if  user.check_password(password):
78 79
                return user
79
        
80
        # Since no user has been found by email try with the username
81
        try:
82
            user = AstakosUser.objects.get(username=username)
83 80
        except AstakosUser.DoesNotExist:
84 81
            return None
85
        
82

  
86 83
        if user.check_password(password):
87 84
            return user
88 85
        else:
b/snf-astakos-app/astakos/im/forms.py
82 82
)
83 83

  
84 84
class StoreUserMixin(object):
85

  
85 86
    @transaction.commit_on_success
86 87
    def store_user(self, user, request):
87 88
        user.save()
......
141 142
                mark_safe("I agree with %s" % terms_link_html)
142 143

  
143 144
    def clean_email(self):
144
        email = self.cleaned_data['email'].lower()
145
        email = self.cleaned_data['email']
145 146
        if not email:
146 147
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
147 148
        if reserved_email(email):
......
260 261
                    mark_safe("I agree with %s" % terms_link_html)
261 262

  
262 263
    def clean_email(self):
263
        email = self.cleaned_data['email'].lower()
264
        email = self.cleaned_data['email']
264 265
        if not email:
265 266
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
266 267
        if reserved_email(email):
......
385 386
        username = self.cleaned_data.get('username')
386 387

  
387 388
        try:
388
            user = AstakosUser.objects.get(email=username)
389
            user = AstakosUser.objects.get_by_identifier(username)
389 390
            if not user.has_auth_provider('local'):
390 391
                provider = auth_providers.get_provider('local')
391 392
                raise forms.ValidationError(
b/snf-astakos-app/astakos/im/models.py
324 324
    def get_by_email(self, email):
325 325
        return self.get(email=email)
326 326

  
327
    def get_by_identifier(self, email_or_username, **kwargs):
328
        try:
329
            return self.get(email__iexact=email_or_username, **kwargs)
330
        except AstakosUser.DoesNotExist:
331
            return self.get(username__iexact=email_or_username, **kwargs)
332

  
333
    def user_exists(self, email_or_username, **kwargs):
334
        qemail = Q(email__iexact=email_or_username)
335
        qusername = Q(username__iexact=email_or_username)
336
        return self.filter(qemail | qusername).exists()
337

  
338

  
327 339
class AstakosUser(User):
328 340
    """
329 341
    Extends ``django.contrib.auth.models.User`` by defining additional fields.
......
501 513

  
502 514
        if not self.id:
503 515
            # set username
504
            self.username = self.email
516
            self.username = self.email.lower()
505 517

  
506 518
        self.validate_unique_email_isactive()
507 519

  
b/snf-astakos-app/astakos/im/tests.py
41 41
from astakos.im.models import *
42 42
from astakos.im import functions
43 43
from astakos.im import settings as astakos_settings
44
from astakos.im import forms
44 45

  
45 46
from urllib import quote
46 47

  
......
156 157
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = False
157 158

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

  
202 204
        # and finally a valid signup
203 205
        post_data['email'] = 'kpap@grnet.gr'
204
        r = client.post('/im/signup', post_data)
205
        self.assertEqual(r.status_code, 200)
206
        r = client.post('/im/signup', post_data, follow=True)
207
        self.assertContains(r, messages.NOTIFICATION_SENT)
206 208

  
207 209
        # everything is ok in our db
208 210
        self.assertEqual(AstakosUser.objects.count(), 1)
......
213 215
        provider = AstakosUserAuthProvider.objects.get(module="shibboleth")
214 216
        self.assertEqual(provider.affiliation, 'Test Affiliation')
215 217
        self.assertEqual(provider.info, {u'email': u'kpap@grnet.gr',
216
                                         u'eppn': u'kpapeppn'})
218
                                         u'eppn': u'kpapeppn',
219
                                         u'name': u'Kostas Papadimitriou'})
217 220

  
218 221
        # lets login (not activated yet)
219
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppn", cn="1", )
222
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppn",
223
                          cn="Kostas Papadimitriou", )
220 224
        r = client.get("/im/login/shibboleth?", follow=True)
221 225
        self.assertContains(r, messages.ACCOUNT_PENDING_MODERATION)
222 226
        r = client.get("/im/profile", follow=True)
......
242 246

  
243 247
        client = ShibbolethClient()
244 248
        # shibboleth logged us in, notice that we use different email
245
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1", )
249
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
250
                          cn="Kostas Papadimitriou", )
246 251
        r = client.get("/im/login/shibboleth?")
247 252

  
248 253
        # astakos asks if we want to switch a local account to shibboleth
......
262 267
                     'key': pending_key}
263 268
        r = client.post('/im/local', post_data, follow=True)
264 269
        self.assertRedirects(r, "/im/profile")
265
        self.assertContains(r, "Your new login method has been added")
270
        self.assertContains(r, messages.AUTH_PROVIDER_ADDED)
266 271

  
267 272
        self.assertTrue(existing_user.has_auth_provider('shibboleth'))
268 273
        self.assertTrue(existing_user.has_auth_provider('local',
......
280 285
        client.logout()
281 286

  
282 287
        # look Ma, i can login with both my shibboleth and local account
283
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
288
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
289
                          cn="Kostas Papadimitriou")
284 290
        r = client.get("/im/login/shibboleth?", follow=True)
285 291
        self.assertTrue(r.context['request'].user.is_authenticated())
286 292
        self.assertTrue(r.context['request'].user.email == "kpap@grnet.gr")
......
303 309
        self.assertEqual(r.status_code, 200)
304 310

  
305 311
        # cannot add the same eppn
306
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn", cn="1", )
312
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn",
313
                          cn="Kostas Papadimitriou", )
307 314
        r = client.get("/im/login/shibboleth?", follow=True)
308 315
        self.assertRedirects(r, '/im/profile')
309 316
        self.assertTrue(r.status_code, 200)
......
311 318

  
312 319
        # but can add additional eppn
313 320
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn2",
314
                          cn="1", ep_affiliation="affil2")
321
                          cn="Kostas Papadimitriou", ep_affiliation="affil2")
315 322
        r = client.get("/im/login/shibboleth?", follow=True)
316 323
        new_provider = existing_user.auth_providers.get(identifier="kpapeppn2")
317 324
        self.assertRedirects(r, '/im/profile')
......
322 329
        client.reset_tokens()
323 330

  
324 331
        # cannot login with another eppn
325
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppninvalid", cn="1")
332
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppninvalid",
333
                          cn="Kostas Papadimitriou")
326 334
        r = client.get("/im/login/shibboleth?", follow=True)
327 335
        self.assertFalse(r.context['request'].user.is_authenticated())
328 336

  
......
334 342
                                                         identifier='kpapeppn')
335 343
        remove_shibbo2_url = user.get_provider_remove_url('shibboleth',
336 344
                                                         identifier='kpapeppn2')
337
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
345
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
346
                          cn="Kostas Papadimtriou")
338 347
        r = client.get("/im/login/shibboleth?", follow=True)
339 348
        client.reset_tokens()
340 349

  
......
380 389
        user2 = get_local_user('another@grnet.gr')
381 390
        user2.add_auth_provider('shibboleth', identifier='existingeppn')
382 391
        # login
383
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
392
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
393
                          cn="Kostas Papadimitriou")
384 394
        r = client.get("/im/login/shibboleth?", follow=True)
385 395
        # try to assign existing shibboleth identifier of another user
386
        client.set_tokens(mail="kpap_second@shibboleth.gr", eppn="existingeppn", cn="1")
396
        client.set_tokens(mail="kpap_second@shibboleth.gr", eppn="existingeppn",
397
                          cn="Kostas Papadimitriou")
387 398
        r = client.get("/im/login/shibboleth?", follow=True)
388
        self.assertContains(r, 'Account already exists')
399
        self.assertContains(r, messages.AUTH_PROVIDER_ADD_FAILED)
400
        self.assertContains(r, messages.AUTH_PROVIDER_ADD_EXISTS)
389 401

  
390 402

  
391 403
class LocalUserTests(TestCase):
......
422 434
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 1)
423 435
        astakos_settings.MODERATION_ENABLED = True
424 436

  
437
    def test_email_case(self):
438
        data = {
439
          'email': 'kPap@grnet.gr',
440
          'password1': '1234',
441
          'password2': '1234'
442
        }
443

  
444
        form = forms.LocalUserCreationForm(data)
445
        self.assertTrue(form.is_valid())
446
        user = form.save()
447
        form.store_user(user, {})
448

  
449
        u = AstakosUser.objects.get(pk=1)
450
        self.assertEqual(u.email, 'kPap@grnet.gr')
451
        self.assertEqual(u.username, 'kpap@grnet.gr')
452
        u.is_active = True
453
        u.email_verified = True
454
        u.save()
455

  
456
        data = {'username': 'kpap@grnet.gr', 'password': '1234'}
457
        login = forms.LoginForm(data=data)
458
        self.assertTrue(login.is_valid())
459

  
460
        data = {'username': 'KpaP@grnet.gr', 'password': '1234'}
461
        login = forms.LoginForm(data=data)
462
        self.assertTrue(login.is_valid())
463

  
464
        data = {
465
          'email': 'kpap@grnet.gr',
466
          'password1': '1234',
467
          'password2': '1234'
468
        }
469
        form = forms.LocalUserCreationForm(data)
470
        self.assertFalse(form.is_valid())
471

  
425 472
    def test_local_provider(self):
426 473
        # enable moderation
427 474
        astakos_settings.MODERATION_ENABLED = True
......
494 541
        self.assertContains(r, "doesn't have an associated user account")
495 542
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
496 543
                                                 'password': 'password'})
497
        print r
498 544
        self.assertContains(r, messages.ACCOUNT_PENDING_ACTIVATION)
499 545
        self.assertContains(r, 'Resend activation')
500 546
        self.assertFalse(r.context['request'].user.is_authenticated())
b/snf-astakos-app/astakos/im/util.py
107 107
    """
108 108
    Return url if having the supplied ``domain`` (if present) or one of the ``allowed_schemes``.
109 109
    Otherwise return None.
110
    
110

  
111 111
    >>> print restrict_next('/im/feedback', '.okeanos.grnet.gr')
112 112
    /im/feedback
113 113
    >>> print restrict_next('pithos.okeanos.grnet.gr/im/feedback', '.okeanos.grnet.gr')
......
168 168
        try:
169 169
            user.save()
170 170
        except ValidationError, e:
171
            return HttpResponseBadRequest(e) 
172
    
171
            return HttpResponseBadRequest(e)
172

  
173 173
    next = restrict_next(next, domain=COOKIE_DOMAIN)
174
    
174

  
175 175
    if FORCE_PROFILE_UPDATE and not user.is_verified and not user.is_superuser:
176 176
        params = ''
177 177
        if next:
......
187 187

  
188 188
    if not next:
189 189
        next = reverse('astakos.im.views.index')
190
        
190

  
191 191
    response['Location'] = next
192 192
    response.status_code = 302
193 193
    return response
......
209 209

  
210 210

  
211 211
def reserved_email(email):
212
    return AstakosUser.objects.filter(email__iexact=email).count() > 0 or \
213
        AstakosUser.objects.filter(username__iexact=email).count() > 0
212
    return AstakosUser.objects.user_exists(email)
214 213

  
215 214

  
216 215
def get_query(request):

Also available in: Unified diff