def authenticate(self, username=None, password=None):
#If username is an email address, then try to pull it up
if email_re.search(username):
- try:
- user = AstakosUser.objects.get(email=username, is_active=True)
- except AstakosUser.DoesNotExist:
+ users = AstakosUser.objects.filter(email=username)
+ if not users:
return None
+ for user in users:
+ if user.check_password(password):
+ return user
else:
#We have a non-email address username we
#should try username
from django.utils.encoding import smart_str
from astakos.im.models import AstakosUser, Invitation, get_latest_terms, EmailChange
-from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, \
- BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, \
- RECAPTCHA_ENABLED, LOGGING_LEVEL, PASSWORD_RESET_EMAIL_SUBJECT, \
- NEWPASSWD_INVALIDATE_TOKEN
+from astakos.im.settings import (INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL,
+ BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL,
+ RECAPTCHA_ENABLED, LOGGING_LEVEL, PASSWORD_RESET_EMAIL_SUBJECT,
+ NEWPASSWD_INVALIDATE_TOKEN, THIRDPARTY_ACC_ADDITIONAL_FIELDS
+)
from astakos.im.widgets import DummyWidget, RecaptchaWidget
from astakos.im.functions import send_change_email
return user
class ThirdPartyUserCreationForm(forms.ModelForm):
+ third_party_identifier = forms.CharField(
+ widget=forms.HiddenInput(),
+ label=''
+ )
class Meta:
model = AstakosUser
fields = ("email", "first_name", "last_name", "third_party_identifier", "has_signed_terms")
self.request = kwargs.get('request', None)
if self.request:
kwargs.pop('request')
+
+ latest_terms = get_latest_terms()
+ if latest_terms:
+ self._meta.fields.append('has_signed_terms')
+
super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
- self.fields.keyOrder = ['email', 'first_name', 'last_name', 'third_party_identifier']
- if get_latest_terms():
+
+ if latest_terms:
self.fields.keyOrder.append('has_signed_terms')
- #set readonly form fields
- ro = ["third_party_identifier"]
- for f in ro:
- self.fields[f].widget.attrs['readonly'] = True
-
+
if 'has_signed_terms' in self.fields:
# Overriding field label since we need to apply a link
# to the terms within the label
def __init__(self, *args, **kwargs):
super(ShibbolethUserCreationForm, self).__init__(*args, **kwargs)
- self.fields.keyOrder.append('additional_email')
# copy email value to additional_mail in case user will change it
name = 'email'
field = self.fields[name]
self.initial['additional_email'] = self.initial.get(name, field.initial)
-
+ self.initial['email'] = None
+
def clean_email(self):
email = self.cleaned_data['email']
for user in AstakosUser.objects.filter(email = email):
if user.provider == 'shibboleth':
- raise forms.ValidationError(_("This email is already associated with another shibboleth account."))
- elif not user.is_active:
- raise forms.ValidationError(_("This email is already associated with an inactive account. \
- You need to wait to be activated before being able to switch to a shibboleth account."))
+ raise forms.ValidationError(_(
+ "This email is already associated with another shibboleth \
+ account."
+ )
+ )
+ else:
+ raise forms.ValidationError(_("This email is already used"))
super(ShibbolethUserCreationForm, self).clean_email()
return email
check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
if not check.is_valid:
raise forms.ValidationError(_('You have not entered the correct words'))
-
+
def clean(self):
super(LoginForm, self).clean()
if self.user_cache and self.user_cache.provider not in ('local', ''):
send_helpdesk_notification(user, helpdesk_email_template_name)
send_greeting(user, email_template_name)
-def switch_account_to_shibboleth(user, local_user, greeting_template_name='im/welcome_email.txt'):
- if not user or not isinstance(user, AstakosUser):
- return
-
- if not local_user or not isinstance(user, AstakosUser):
- return
-
- if not user.provider == 'shibboleth':
- return
-
- user.delete()
- local_user.provider = 'shibboleth'
- local_user.third_party_identifier = user.third_party_identifier
- local_user.save()
- send_greeting(local_user, greeting_template_name)
- return local_user
-
def invite(invitation, inviter, email_template_name='im/welcome_email.txt'):
"""
Send an invitation email and upon success reduces inviter's invitation by one.
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model 'PendingThirdPartyUser'
+ db.create_table('im_pendingthirdpartyuser', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('third_party_identifier', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
+ ('provider', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
+ ('email', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)),
+ ('first_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
+ ('last_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
+ ('affiliation', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
+ ('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=30)),
+ ))
+ db.send_create_signal('im', ['PendingThirdPartyUser'])
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'PendingThirdPartyUser'
+ db.delete_table('im_pendingthirdpartyuser')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'im.additionalmail': {
+ 'Meta': {'object_name': 'AdditionalMail'},
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"})
+ },
+ 'im.approvalterms': {
+ 'Meta': {'object_name': 'ApprovalTerms'},
+ 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 15, 13, 7, 38, 626139)', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'im.astakosuser': {
+ 'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", 'object_name': 'AstakosUser', '_ormbases': ['auth.User']},
+ 'activation_sent': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'date_signed_terms': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'email_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'has_credits': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'has_signed_terms': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'invitations': ('django.db.models.fields.IntegerField', [], {'default': '100'}),
+ 'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
+ 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
+ },
+ 'im.emailchange': {
+ 'Meta': {'object_name': 'EmailChange'},
+ 'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'new_email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ 'requested_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 15, 13, 7, 38, 627944)'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emailchange_user'", 'unique': 'True', 'to': "orm['im.AstakosUser']"})
+ },
+ 'im.invitation': {
+ 'Meta': {'object_name': 'Invitation'},
+ 'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
+ 'consumed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.AstakosUser']"}),
+ 'is_consumed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ },
+ 'im.pendingthirdpartyuser': {
+ 'Meta': {'object_name': 'PendingThirdPartyUser'},
+ 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'im.service': {
+ 'Meta': {'object_name': 'Service'},
+ 'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+ 'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'icon': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'url': ('django.db.models.fields.FilePathField', [], {'max_length': '100'})
+ }
+ }
+
+ complete_apps = ['im']
from time import asctime
from datetime import datetime, timedelta
from base64 import b64encode
-from urlparse import urlparse, urlunparse
+from urlparse import urlparse
from random import randint
from django.db import models, IntegrityError
owner = models.ForeignKey(AstakosUser)
email = models.EmailField()
+class PendingThirdPartyUser(models.Model):
+ """
+ Model for registring successful third party user authentications
+ """
+ third_party_identifier = models.CharField('Third-party identifier', max_length=255, null=True, blank=True)
+ provider = models.CharField('Provider', max_length=255, blank=True)
+ email = models.EmailField(_('e-mail address'), blank=True)
+ first_name = models.CharField(_('first name'), max_length=30, blank=True)
+ last_name = models.CharField(_('last name'), max_length=30, blank=True)
+ affiliation = models.CharField('Affiliation', max_length=255, blank=True)
+ username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))
+
+ @property
+ def realname(self):
+ return '%s %s' %(self.first_name, self.last_name)
+
+ @realname.setter
+ def realname(self, value):
+ parts = value.split(' ')
+ if len(parts) == 2:
+ self.first_name = parts[0]
+ self.last_name = parts[1]
+ else:
+ self.last_name = parts[0]
+
+ def save(self, **kwargs):
+ if not self.id:
+ # set username
+ while not self.username:
+ username = uuid.uuid4().hex[:30]
+ try:
+ AstakosUser.objects.get(username = username)
+ except AstakosUser.DoesNotExist, e:
+ self.username = username
+ super(PendingThirdPartyUser, self).save(**kwargs)
+
def create_astakos_user(u):
try:
AstakosUser.objects.get(user_ptr=u.pk)
'Password reset on %s alpha2 testing' % SITENAME)
# Enforce token renewal on password change/reset
-NEWPASSWD_INVALIDATE_TOKEN = getattr(settings, 'ASTAKOS_NEWPASSWD_INVALIDATE_TOKEN', True)
\ No newline at end of file
+NEWPASSWD_INVALIDATE_TOKEN = getattr(settings, 'ASTAKOS_NEWPASSWD_INVALIDATE_TOKEN', True)
+
+# Permit local account migration
+ENABLE_LOCAL_ACCOUNT_MIGRATION = getattr(settings, 'ASTAKOS_ENABLE_LOCAL_ACCOUNT_MIGRATION', True)
+
+# A dictionary describing the user fields appearing during the second step of third party account creation
+from django import forms
+THIRDPARTY_ACC_ADDITIONAL_FIELDS = getattr(settings, 'ASTAKOS_THIRDPARTY_ACC_ADDITIONAL_FIELDS', {
+ 'first_name':None,
+ 'last_name':None,
+})
\ No newline at end of file
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
+from django.core.urlresolvers import reverse
from astakos.im.util import prepare_response, get_query
from astakos.im.views import requires_anonymous
-from astakos.im.models import AstakosUser
+from astakos.im.models import AstakosUser, PendingThirdPartyUser
from astakos.im.forms import LoginForm
from astakos.im.settings import RATELIMIT_RETRIES_ALLOWED
+from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION
from ratelimit.decorators import ratelimit
was_limited = getattr(request, 'limited', False)
form = LoginForm(data=request.POST, was_limited=was_limited, request=request)
next = get_query(request).get('next', '')
+ username = get_query(request).get('key')
+
if not form.is_valid():
- return render_to_response(on_failure,
- {'login_form':form,
- 'next':next},
- context_instance=RequestContext(request))
+ return render_to_response(
+ on_failure,
+ {'login_form':form,
+ 'next':next,
+ 'key':username},
+ context_instance=RequestContext(request)
+ )
# get the user from the cash
user = form.user_cache
if not user:
message = _('Cannot authenticate account')
elif not user.is_active:
- message = _('Inactive account')
+ if user.sent_activation:
+ message = _('Your request is pending activation')
+ else:
+ message = _('You have not followed the activation link')
if message:
messages.add_message(request, messages.ERROR, message)
return render_to_response(on_failure,
{'form':form},
context_instance=RequestContext(request))
- return prepare_response(request, user, next)
+ # hook for switching account to use third party authentication
+ if ENABLE_LOCAL_ACCOUNT_MIGRATION and username:
+ try:
+ new = PendingThirdPartyUser.objects.get(
+ username=username)
+ except:
+ messages.error(
+ request,
+ _('Account failed to switch to %(provider)s' % locals())
+ )
+ return render_to_response(
+ on_failure,
+ {'login_form':form,
+ 'next':next},
+ context_instance=RequestContext(request)
+ )
+ else:
+ user.provider = new.provider
+ user.third_party_identifier = new.third_party_identifier
+ user.save()
+ new.delete()
+ messages.success(
+ request,
+ _('Account successfully switched to %(provider)s' % user.__dict__)
+ )
+ return prepare_response(request, user, next)
\ No newline at end of file
from django.contrib import messages
from django.template import RequestContext
from django.views.decorators.http import require_http_methods
+from django.db.models import Q
+from django.core.exceptions import ValidationError
+from django.http import HttpResponseRedirect
+from django.core.urlresolvers import reverse
+from urlparse import urlunsplit, urlsplit
+from django.utils.http import urlencode
from astakos.im.util import prepare_response, get_context, get_invitation
from astakos.im.views import requires_anonymous, render_response
-from astakos.im.settings import DEFAULT_USER_LEVEL
-from astakos.im.models import AstakosUser, Invitation, AdditionalMail
+from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL
+
+from astakos.im.models import AstakosUser, PendingThirdPartyUser
from astakos.im.forms import LoginForm
from astakos.im.activation_backends import get_backend, SimpleBackend
+import logging
+
+logger = logging.getLogger(__name__)
+
class Tokens:
# these are mapped by the Shibboleth SP software
SHIB_EPPN = "HTTP_EPPN" # eduPersonPrincipalName
@require_http_methods(["GET", "POST"])
@requires_anonymous
-def login(request, backend=None, on_login_template='im/login.html', on_creation_template='im/third_party_registration.html', extra_context={}):
+def login(
+ request,
+ on_login_template='im/login.html',
+ on_signup_template='im/third_party_check_local.html',
+ extra_context=None):
+ extra_context = extra_context or {}
+
tokens = request.META
try:
return HttpResponseBadRequest("Missing user name in request")
affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '')
- email = tokens.get(Tokens.SHIB_MAIL, None)
-
+ email = tokens.get(Tokens.SHIB_MAIL, '')
+
try:
- user = AstakosUser.objects.get(provider='shibboleth', third_party_identifier=eppn)
+ user = AstakosUser.objects.get(
+ provider='shibboleth',
+ third_party_identifier=eppn
+ )
if user.is_active:
return prepare_response(request,
user,
login_form = LoginForm(request=request),
context_instance=RequestContext(request))
except AstakosUser.DoesNotExist, e:
- user = AstakosUser(third_party_identifier=eppn, realname=realname,
- affiliation=affiliation, provider='shibboleth',
- email=email)
+ # First time
+ try:
+ user, created = PendingThirdPartyUser.objects.get_or_create(
+ third_party_identifier=eppn,
+ provider='shibboleth',
+ defaults=dict(
+ realname=realname,
+ affiliation=affiliation,
+ email=email
+ )
+ )
+ user.save()
+ except BaseException, e:
+ logger.exception(e)
+ template = on_login_template
+ extra_context['login_form'] = LoginForm(request=request)
+ messages.error(request, _('Something went wrong.'))
+ else:
+ if not ENABLE_LOCAL_ACCOUNT_MIGRATION:
+ url = reverse(
+ 'astakos.im.target.shibboleth.signup'
+ )
+ parts = list(urlsplit(url))
+ parts[3] = urlencode({'key': user.username})
+ url = urlunsplit(parts)
+ return HttpResponseRedirect(url)
+ else:
+ template = on_signup_template
+ extra_context['key'] = user.username
+
+ extra_context['provider']='shibboleth'
+ return render_response(
+ template,
+ context_instance=get_context(request, extra_context)
+ )
+
+@require_http_methods(["GET"])
+@requires_anonymous
+def signup(request,
+ backend=None,
+ on_creation_template='im/third_party_registration.html',
+ extra_context=None
+):
+ extra_context = extra_context or {}
+ username = request.GET.get('key')
+ if not username:
+ return HttpResponseBadRequest(_('Missing key parameter.'))
+ try:
+ pending = PendingThirdPartyUser.objects.get(username=username)
+ except BaseException, e:
+ logger.exception(e)
+ return HttpResponseBadRequest(_('Invalid key.'))
+ else:
+ d = pending.__dict__
+ d.pop('_state', None)
+ d.pop('id', None)
+ user = AstakosUser(**d)
try:
- if not backend:
- backend = get_backend(request)
- form = backend.get_signup_form(provider='shibboleth', instance=user)
- except Exception, e:
- form = SimpleBackend(request).get_signup_form(provider='shibboleth', instance=user)
- messages.add_message(request, messages.ERROR, e)
- return render_response(on_creation_template,
- signup_form = form,
- provider = 'shibboleth',
- context_instance=get_context(request, extra_context))
+ backend = backend or get_backend(request)
+ except ImproperlyConfigured, e:
+ messages.error(request, e)
+ else:
+ extra_context['form'] = backend.get_signup_form(
+ provider='shibboleth',
+ instance=user
+ )
+ extra_context['provider']='shibboleth'
+ return render_response(
+ on_creation_template,
+ context_instance=get_context(request, extra_context)
+ )
\ No newline at end of file
{% include "im/form_render.html" %}
{% endwith %}
<input type="hidden" name="next" value="{{ next }}">
+
+ {% if key %}
+ <input type="hidden" name="key" value="{{key}}">
+ {% else %}
+ {% if request.GET.key %}
+ <input type="hidden" name="key" value="{{request.GET.key}}">
+ {% endif %}
+ {% endif %}
+
<div class="form-row submit clearfix">
-
- <input type="submit" class="submit altcol" value="SUBMIT" />
+ <input type="submit" class="submit altcol" value="SUBMIT" />
<a class="extra-link" href="{% url django.contrib.auth.views.password_reset %}">Forgot your password?</a>
</div>
</form>
--- /dev/null
+{% extends 'im/base_two_cols.html' %}
+
+{% block page.title %}
+ Signup
+{% endblock %}
+
+{% block body.left %}
+ <img class="pic" src="{{ IM_STATIC_URL }}images/pictures/accounts_3.png" />
+{% comment %}{% include "im/services_description.html" %}{% endcomment %}
+{% endblock body.left %}
+
+{% block body.right %}
+ {% if "local" in im_modules %}
+ <div class="form-stacked">
+ <h2><span>Already have an account?</span></h2>
+ <a href="{% url astakos.im.views.index %}?key={{key}}">YES</a>
+ <a href="{% url astakos.im.target.shibboleth.signup %}?key={{key}}">NO</a>
+ </div>
+ {% endif %}
+{% endblock %}
\ No newline at end of file
<div class="form-stacked">
<form action="{% url astakos.im.views.signup %}" method="post"
class="innerlabels signup">{% csrf_token %}
- <h2><span>Provide an email address to complete the registration:</span></h2>
+ <h2><span>SIGN UP</span></h2>
<input type="hidden" name="next" value="{{ next }}">
<input type="hidden" name="code" value="{{ code }}">
<input type="hidden" name="provider" value={{ provider|default:"local" }}>
- {% with signup_form as form %}
{% include "im/form_render.html" %}
- {% endwith %}
<div class="form-row submit">
<input type="submit" class="submit altcol" value="SUBMIT" />
</div>
if 'shibboleth' in IM_MODULES:
urlpatterns += patterns('astakos.im.target',
- url(r'^login/shibboleth/?$', 'shibboleth.login')
+ url(r'^login/shibboleth/?$', 'shibboleth.login'),
+ url(r'^login/shibboleth/signup/?$', 'shibboleth.signup')
)
if 'twitter' in IM_MODULES:
from django.db.utils import IntegrityError
from django.contrib.auth.views import password_change
from django.core.exceptions import ValidationError
-from django.db.models import Q
from django.views.decorators.http import require_http_methods
from astakos.im.models import AstakosUser, Invitation, ApprovalTerms
from astakos.im.activation_backends import get_backend, SimpleBackend
from astakos.im.util import get_context, prepare_response, set_cookie, get_query
from astakos.im.forms import *
-from astakos.im.functions import send_greeting, send_feedback, SendMailError, \
- invite as invite_func, logout as auth_logout, activate as activate_func, switch_account_to_shibboleth
-from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, LOGOUT_NEXT, LOGGING_LEVEL
+from astakos.im.functions import (send_greeting, send_feedback, SendMailError,
+ invite as invite_func, logout as auth_logout, activate as activate_func
+)
+from astakos.im.settings import (DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL,
+ COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, LOGOUT_NEXT, LOGGING_LEVEL
+)
logger = logging.getLogger(__name__)
template_name = login_template_name
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('astakos.im.views.edit_profile'))
- return render_response(template_name,
- login_form = LoginForm(request=request),
- context_instance = get_context(request, extra_context))
+
+ return render_response(
+ template_name,
+ login_form = LoginForm(request=request),
+ context_instance = get_context(request, extra_context)
+ )
@require_http_methods(["GET", "POST"])
@login_required
return index(request)
try:
- local_user = AstakosUser.objects.get(~Q(id = user.id), email=user.email, is_active=True)
- except AstakosUser.DoesNotExist:
- try:
- activate_func(user, greeting_email_template_name, helpdesk_email_template_name, verify_email=True)
- response = prepare_response(request, user, next, renew=True)
- transaction.commit()
- return response
- except SendMailError, e:
- message = e.message
- messages.add_message(request, messages.ERROR, message)
- transaction.rollback()
- return index(request)
- except BaseException, e:
- status = messages.ERROR
- message = _('Something went wrong.')
- messages.add_message(request, messages.ERROR, message)
- logger.exception(e)
- transaction.rollback()
- return index(request)
- else:
- try:
- user = switch_account_to_shibboleth(user, local_user, greeting_email_template_name)
- response = prepare_response(request, user, next, renew=True)
- transaction.commit()
- return response
- except SendMailError, e:
- message = e.message
- messages.add_message(request, messages.ERROR, message)
- transaction.rollback()
- return index(request)
- except BaseException, e:
- status = messages.ERROR
- message = _('Something went wrong.')
- messages.add_message(request, messages.ERROR, message)
- logger.exception(e)
- transaction.rollback()
- return index(request)
+ activate_func(user, greeting_email_template_name, helpdesk_email_template_name, verify_email=True)
+ response = prepare_response(request, user, next, renew=True)
+ transaction.commit()
+ return response
+ except SendMailError, e:
+ message = e.message
+ messages.add_message(request, messages.ERROR, message)
+ transaction.rollback()
+ return index(request)
+ except BaseException, e:
+ status = messages.ERROR
+ message = _('Something went wrong.')
+ messages.add_message(request, messages.ERROR, message)
+ logger.exception(e)
+ transaction.rollback()
+ return index(request)
@require_http_methods(["GET", "POST"])
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context={}):