Customize third party signup form fields 0.11
authorSofia Papagiannaki <papagian@gmail.com>
Fri, 16 Nov 2012 14:34:23 +0000 (16:34 +0200)
committerSofia Papagiannaki <papagian@gmail.com>
Fri, 16 Nov 2012 14:34:23 +0000 (16:34 +0200)
Refs: #3041

snf-astakos-app/README
snf-astakos-app/astakos/im/activation_backends.py
snf-astakos-app/astakos/im/forms.py
snf-astakos-app/astakos/im/migrations/0015_auto__add_pendingthirdpartyuser__add_unique_pendingthirdpartyuser_prov.py [moved from snf-astakos-app/astakos/im/migrations/0015_auto__add_pendingthirdpartyuser.py with 92% similarity]
snf-astakos-app/astakos/im/models.py
snf-astakos-app/astakos/im/settings.py
snf-astakos-app/astakos/im/target/shibboleth.py
snf-astakos-app/astakos/im/views.py
snf-astakos-app/conf/20-snf-astakos-app-settings.conf

index 617ea32..11aa53e 100644 (file)
@@ -91,6 +91,8 @@ ASTAKOS_EMAIL_CHANGE_EMAIL_SUBJECT          'Email change on %s alpha2 testing'
 ASTAKOS_PASSWORD_RESET_EMAIL_SUBJECT        'Password reset on %s alpha2 testing' % SITENAME                                Password change email subject
 ASTAKOS_NEWPASSWD_INVALIDATE_TOKEN          True                                                                            Enforce token renewal on password change/reset. If set to False, user can optionally decide
                                                                                                                             whether to renew the token or not.
+ASTAKOS_ENABLE_LOCAL_ACCOUNT_MIGRATION      True                                                                            Permit local account migration to third party account
+ASTAKOS_THIRDPARTY_ACC_ADDITIONAL_FIELDS    {'first_name':None, 'last_name':None}                                           The additional user fields appearing during the second step of third party account creation  
 =========================================== =============================================================================   ===========================================================================================
 
 Administrator functions
index 71b0abe..7f6b5ae 100644 (file)
@@ -101,11 +101,11 @@ class ActivationBackend(object):
                 initial_data = request.POST
         return globals()[formclass](initial_data, instance=instance, request=request)
     
-    def handle_activation(self, user, \
-                          activation_template_name='im/activation_email.txt', \
-                          greeting_template_name='im/welcome_email.txt', \
-                          admin_email_template_name='im/admin_notification.txt', \
-                          switch_accounts_email_template_name='im/switch_accounts_email.txt'):
+    def handle_activation(
+        self, user, activation_template_name='im/activation_email.txt',
+        greeting_template_name='im/welcome_email.txt',
+        admin_email_template_name='im/admin_notification.txt'
+    ):
         """
         If the user is already active returns immediately.
         If the user is not active and there is another account associated with
@@ -120,9 +120,6 @@ class ActivationBackend(object):
         try:
             if user.is_active:
                 return RegistationCompleted()
-            if user.conflicting_email():
-                send_verification(user, switch_accounts_email_template_name)
-                return SwitchAccountsVerificationSent(user.email)
             
             if self._is_preaccepted(user):
                 if user.email_verified:
@@ -231,14 +228,6 @@ class VerificationSent(ActivationResult):
         message = _('Verification sent.')
         super(VerificationSent, self).__init__(message)
 
-class SwitchAccountsVerificationSent(ActivationResult):
-    def __init__(self, email):
-        message = _('This email is already associated with another \
-                    local account. To change this account to a shibboleth \
-                    one follow the link in the verification email sent \
-                    to %s. Otherwise just ignore it.' % email)
-        super(SwitchAccountsVerificationSent, self).__init__(message)
-
 class NotificationSent(ActivationResult):
     def __init__(self):
         message = _('Your request for an account was successfully received and is now pending \
index 28c76a5..3e498db 100644 (file)
@@ -46,8 +46,12 @@ from django.utils.functional import lazy
 from django.utils.safestring import mark_safe
 from django.contrib import messages
 from django.utils.encoding import smart_str
+from django.forms.models import fields_for_model
 
-from astakos.im.models import AstakosUser, Invitation, get_latest_terms, EmailChange
+from astakos.im.models import (
+    AstakosUser, Invitation, get_latest_terms,
+    EmailChange, PendingThirdPartyUser
+)
 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,
@@ -189,7 +193,7 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
     )
     class Meta:
         model = AstakosUser
-        fields = ("email", "first_name", "last_name", "third_party_identifier", "has_signed_terms")
+        fields = ['email', 'third_party_identifier']
 
     def __init__(self, *args, **kwargs):
         """
@@ -202,7 +206,7 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
         latest_terms = get_latest_terms()
         if latest_terms:
             self._meta.fields.append('has_signed_terms')
-                
+        
         super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
         
         if latest_terms:
@@ -215,7 +219,17 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
                     % (reverse('latest_terms'), _("the terms"))
             self.fields['has_signed_terms'].label = \
                     mark_safe("I agree with %s" % terms_link_html)
-
+        
+        default = fields_for_model(
+            self._meta.model,
+            THIRDPARTY_ACC_ADDITIONAL_FIELDS.keys()
+        )
+        for fname, field in THIRDPARTY_ACC_ADDITIONAL_FIELDS.iteritems():
+            if field:
+                self.fields[fname] = field
+            self.fields.setdefault(fname, default.get(fname))
+            self.initial[fname] = getattr(self.instance, fname, None)
+    
     def clean_email(self):
         email = self.cleaned_data['email']
         if not email:
@@ -287,6 +301,19 @@ class ShibbolethUserCreationForm(ThirdPartyUserCreationForm):
                 raise forms.ValidationError(_("This email is already used"))
         super(ShibbolethUserCreationForm, self).clean_email()
         return email
+    
+    def save(self, commit=True):
+        user = super(ShibbolethUserCreationForm, self).save(commit=False)
+        try:
+            p = PendingThirdPartyUser.objects.get(
+                provider=user.provider,
+                third_party_identifier=user.third_party_identifier
+            )
+        except:
+            pass
+        else:
+            p.delete()
+        return user
 
 class InvitedShibbolethUserCreationForm(ShibbolethUserCreationForm, InvitedThirdPartyUserCreationForm):
     pass
@@ -13,7 +13,7 @@ class Migration(SchemaMigration):
             ('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)),
+            ('email', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, 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)),
@@ -21,9 +21,15 @@ class Migration(SchemaMigration):
         ))
         db.send_create_signal('im', ['PendingThirdPartyUser'])
 
+        # Adding unique constraint on 'PendingThirdPartyUser', fields ['provider', 'third_party_identifier']
+        db.create_unique('im_pendingthirdpartyuser', ['provider', 'third_party_identifier'])
+
 
     def backwards(self, orm):
         
+        # Removing unique constraint on 'PendingThirdPartyUser', fields ['provider', 'third_party_identifier']
+        db.delete_unique('im_pendingthirdpartyuser', ['provider', 'third_party_identifier'])
+
         # Deleting model 'PendingThirdPartyUser'
         db.delete_table('im_pendingthirdpartyuser')
 
@@ -73,7 +79,7 @@ class Migration(SchemaMigration):
         },
         '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'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 16, 11, 52, 33, 987227)', 'db_index': 'True'}),
             'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
             'location': ('django.db.models.fields.CharField', [], {'max_length': '255'})
         },
@@ -101,7 +107,7 @@ class Migration(SchemaMigration):
             '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)'}),
+            'requested_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 16, 11, 52, 33, 988935)'}),
             'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emailchange_user'", 'unique': 'True', 'to': "orm['im.AstakosUser']"})
         },
         'im.invitation': {
@@ -116,9 +122,9 @@ class Migration(SchemaMigration):
             'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
         },
         'im.pendingthirdpartyuser': {
-            'Meta': {'object_name': 'PendingThirdPartyUser'},
+            'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", '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'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', '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'}),
index 3600810..7099b0c 100644 (file)
@@ -380,11 +380,14 @@ class PendingThirdPartyUser(models.Model):
     """
     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)
+    email = models.EmailField(_('e-mail address'), blank=True, null=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"))
+    
+    class Meta:
+        unique_together = ("provider", "third_party_identifier")
 
     @property
     def realname(self):
index e674108..2e035c3 100644 (file)
@@ -124,7 +124,7 @@ NEWPASSWD_INVALIDATE_TOKEN = getattr(settings, 'ASTAKOS_NEWPASSWD_INVALIDATE_TOK
 # 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
+# A dictionary describing the additional 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,
index 955c7e3..8c88669 100644 (file)
@@ -72,7 +72,8 @@ def login(
     request,
     on_login_template='im/login.html',
     on_signup_template='im/third_party_check_local.html',
-    extra_context=None):
+    extra_context=None
+):
     extra_context = extra_context or {}
 
     tokens = request.META
@@ -149,10 +150,11 @@ def login(
 
 @require_http_methods(["GET"])
 @requires_anonymous
-def signup(request,
-           backend=None,
-           on_creation_template='im/third_party_registration.html',
-           extra_context=None
+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')
index 684be53..86e54a1 100644 (file)
@@ -356,6 +356,7 @@ def signup(request, template_name='im/signup.html', on_success='im/signup_comple
                 message = e.message
                 messages.add_message(request, status, message)
             except BaseException, e:
+                logger.exception(e)
                 status = messages.ERROR
                 message = _('Something went wrong.')
                 messages.add_message(request, status, message)
index b0f2291..b26cd58 100644 (file)
 #ASTAKOS_PASSWORD_RESET_EMAIL_SUBJECT = '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 additional user fields appearing during the second step of third party account creation
+# THIRDPARTY_ACC_ADDITIONAL_FIELDS = getattr(settings, 'ASTAKOS_THIRDPARTY_ACC_ADDITIONAL_FIELDS', {
+#     'first_name':None,
+#     'last_name':None,
+# })
\ No newline at end of file