Commit dbad3ada authored by Kostas Papadimitriou's avatar Kostas Papadimitriou
Browse files

Additional multiple auth methods fixes and tests

parent 21e63dc7
......@@ -596,13 +596,25 @@ class AstakosUser(User):
else:
return auth_providers.get_provider(provider).is_available_for_login()
def can_add_provider(self, provider, **kwargs):
def can_add_auth_provider(self, provider, **kwargs):
provider_settings = auth_providers.get_provider(provider)
if not provider_settings.is_available_for_login():
return False
if self.has_auth_provider(provider) and \
provider_settings.one_per_user:
return False
if 'identifier' in kwargs:
try:
# provider with specified params already exist
existing_user = AstakosUser.objects.get_auth_provider_user(provider,
**kwargs)
except AstakosUser.DoesNotExist:
return True
else:
return False
return True
def can_remove_auth_provider(self, provider):
......@@ -618,7 +630,10 @@ class AstakosUser(User):
**kwargs).count())
def add_auth_provider(self, provider, **kwargs):
self.auth_providers.create(module=provider, active=True, **kwargs)
if self.can_add_auth_provider(provider, **kwargs):
self.auth_providers.create(module=provider, active=True, **kwargs)
else:
raise Exception('Cannot add provider')
def add_pending_auth_provider(self, pending):
"""
......@@ -665,7 +680,7 @@ class AstakosUser(User):
"""
providers = []
for module, provider_settings in auth_providers.PROVIDERS.iteritems():
if self.can_add_provider(module):
if self.can_add_auth_provider(module):
providers.append(provider_settings(self))
return providers
......@@ -722,6 +737,9 @@ class AstakosUserAuthProvider(models.Model):
self.user.save()
return ret
def __repr__(self):
return '<AstakosUserAuthProvider %s:%s>' % (self.module, self.identifier)
class Membership(models.Model):
person = models.ForeignKey(AstakosUser)
......
......@@ -44,7 +44,8 @@ from django.contrib.auth.decorators import login_required
from astakos.im.util import prepare_response, get_query
from astakos.im.views import requires_anonymous, signed_terms_required
from astakos.im.models import PendingThirdPartyUser
from astakos.im.forms import LoginForm, ExtendedPasswordChangeForm
from astakos.im.forms import LoginForm, ExtendedPasswordChangeForm, \
ExtendedSetPasswordForm
from astakos.im.settings import (RATELIMIT_RETRIES_ALLOWED,
ENABLE_LOCAL_ACCOUNT_MIGRATION)
import astakos.im.messages as astakos_messages
......@@ -156,3 +157,4 @@ def password_change(request, template_name='registration/password_change_form.ht
return render_to_response(template_name, {
'form': form,
}, context_instance=RequestContext(request))
......@@ -71,7 +71,6 @@ class Tokens:
@requires_auth_provider('local', login=True)
@require_http_methods(["GET", "POST"])
@requires_anonymous
def login(
request,
template='im/third_party_check_local.html',
......@@ -108,8 +107,13 @@ def login(
# automatically add eppn provider to user
user = request.user
user.add_provider('shibboleth', identifier=eppn)
return HttpResponseRedirect('edit_profile')
if not request.user.can_add_auth_provider('shibboleth',
identifier=eppn):
messages.error(request, 'Account already exists.')
return HttpResponseRedirect(reverse('edit_profile'))
user.add_auth_provider('shibboleth', identifier=eppn)
return HttpResponseRedirect(reverse('edit_profile'))
try:
# astakos user exists ?
......
......@@ -269,7 +269,62 @@ class ShibbolethTests(TestCase):
r = client.get("/im/login/shibboleth?", follow=True)
self.assertFalse(r.context['request'].user.is_authenticated())
user2 = get_local_user('kpap@grnet.gr')
# lets remove local password
user = AstakosUser.objects.get(username="kpap@grnet.gr",
email="kpap@grnet.gr")
provider_pk = user.auth_providers.get(module='local').pk
provider_shib_pk = user.auth_providers.get(module='shibboleth').pk
client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
r = client.get("/im/login/shibboleth?", follow=True)
client.reset_tokens()
r = client.get("/im/remove_auth_provider/%d" % provider_pk)
self.assertEqual(user.auth_providers.count(), 1)
r = client.get("/im/remove_auth_provider/%d" % provider_pk)
self.assertEqual(r.status_code, 404)
r = client.get("/im/remove_auth_provider/%d" % provider_shib_pk)
self.assertEqual(r.status_code, 403)
self.client.logout()
post_data = {'password': 'password',
'username': 'kpap@grnet.gr'}
r = self.client.post('/im/local', post_data, follow=True)
self.assertFalse(r.context['request'].user.is_authenticated())
r = client.get("/im/password_change", follow=True)
r = client.post("/im/password_change", {'new_password1':'111',
'new_password2': '111'},
follow=True)
user = r.context['request'].user
self.assertTrue(user.has_auth_provider('local'))
self.assertTrue(user.has_auth_provider('shibboleth'))
self.assertTrue(user.check_password('111'))
self.assertTrue(user.has_usable_password())
self.client.logout()
post_data = {'password': '111',
'username': 'kpap@grnet.gr'}
r = self.client.post('/im/local', post_data, follow=True)
self.assertTrue(r.context['request'].user.is_authenticated())
client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn", cn="1")
r = client.get("/im/login/shibboleth?", follow=True)
r = client.get("/im/login/shibboleth?", follow=True)
user = AstakosUser.objects.get(username="kpap@grnet.gr",
email="kpap@grnet.gr")
user2 = get_local_user('another@grnet.gr')
user2.add_auth_provider('shibboleth', identifier='existingeppn')
self.assertEqual(user.auth_providers.count(), 2) # local and 1 shibboleth
client.set_tokens(mail="kpap_second@shibboleth.gr", eppn="kpapeppn2", cn="1")
r = client.get("/im/login/shibboleth?", follow=True)
self.assertEqual(user.auth_providers.count(), 3) # local and 2 shibboleth
client.set_tokens(mail="kpap_second@shibboleth.gr", eppn="kpapeppn2", cn="1")
r = client.get("/im/login/shibboleth?", follow=True)
client.set_tokens(mail="kpap_second@shibboleth.gr", eppn="existingeppn", cn="1")
r = client.get("/im/login/shibboleth?", follow=True)
self.assertContains(r, 'Account already exists')
class LocalUserTests(TestCase):
......
......@@ -65,7 +65,7 @@ from astakos.im.activation_backends import get_backend, SimpleBackend
from astakos.im.models import (AstakosUser, ApprovalTerms, AstakosGroup,
EmailChange, GroupKind, Membership,
RESOURCE_SEPARATOR)
RESOURCE_SEPARATOR, AstakosUserAuthProvider)
from astakos.im.util import get_context, prepare_response, get_query, restrict_next
from astakos.im.forms import (LoginForm, InvitationForm, ProfileForm,
FeedbackForm, SignApprovalTermsForm,
......@@ -1406,14 +1406,19 @@ def timeline(request):
timeline_body=timeline_body)
return data
# TODO: action only on POST and user should confirm the removal
@require_http_methods(["GET", "POST"])
@login_required
@signed_terms_required
def remove_auth_provider(request, pk):
provider = request.user.auth_providers.get(pk=pk)
try:
provider = request.user.auth_providers.get(pk=pk)
except AstakosUserAuthProvider.DoesNotExist:
raise Http404
if provider.can_remove():
provider.delete()
return HttpResponseRedirect(reverse('edit_profile'))
else:
messages.error(_('Authentication method cannot be removed'))
return HttpResponseRedirect(reverse('edit_profile'))
raise PermissionDenied
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment