Change setting name
[astakos] / snf-astakos-app / astakos / im / forms.py
index d64fbd2..b3d2be1 100644 (file)
@@ -35,7 +35,8 @@ from datetime import datetime
 
 from django import forms
 from django.utils.translation import ugettext as _
-from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordResetForm
+from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, \
+    PasswordResetForm, PasswordChangeForm, SetPasswordForm
 from django.core.mail import send_mail
 from django.contrib.auth.tokens import default_token_generator
 from django.template import Context, loader
@@ -49,7 +50,8 @@ 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
+    RECAPTCHA_ENABLED, LOGGING_LEVEL, PASSWORD_RESET_EMAIL_SUBJECT, \
+    NEWPASSWD_INVALIDATE_TOKEN
 from astakos.im.widgets import DummyWidget, RecaptchaWidget
 from astakos.im.functions import send_change_email
 
@@ -87,7 +89,7 @@ class LocalUserCreationForm(UserCreationForm):
             kwargs.pop('request')
             self.ip = request.META.get('REMOTE_ADDR',
                                        request.META.get('HTTP_X_REAL_IP', None))
-        
+
         super(LocalUserCreationForm, self).__init__(*args, **kwargs)
         self.fields.keyOrder = ['email', 'first_name', 'last_name',
                                 'password1', 'password2']
@@ -97,7 +99,7 @@ class LocalUserCreationForm(UserCreationForm):
                                          'recaptcha_response_field',])
         if get_latest_terms():
             self.fields.keyOrder.append('has_signed_terms')
-            
+
         if 'has_signed_terms' in self.fields:
             # Overriding field label since we need to apply a link
             # to the terms within the label
@@ -167,7 +169,7 @@ class InvitedLocalUserCreationForm(LocalUserCreationForm):
         ro = ('email', 'username',)
         for f in ro:
             self.fields[f].widget.attrs['readonly'] = True
-        
+
 
     def save(self, commit=True):
         user = super(InvitedLocalUserCreationForm, self).save(commit=False)
@@ -183,7 +185,7 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
     class Meta:
         model = AstakosUser
         fields = ("email", "first_name", "last_name", "third_party_identifier", "has_signed_terms")
-    
+
     def __init__(self, *args, **kwargs):
         """
         Changes the order of fields, and removes the username field.
@@ -199,7 +201,7 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
         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
@@ -207,19 +209,19 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
                     % (reverse('latest_terms'), _("the terms"))
             self.fields['has_signed_terms'].label = \
                     mark_safe("I agree with %s" % terms_link_html)
-    
+
     def clean_email(self):
         email = self.cleaned_data['email']
         if not email:
             raise forms.ValidationError(_("This field is required"))
         return email
-    
+
     def clean_has_signed_terms(self):
         has_signed_terms = self.cleaned_data['has_signed_terms']
         if not has_signed_terms:
             raise forms.ValidationError(_('You have to agree with the terms'))
         return has_signed_terms
-    
+
     def save(self, commit=True):
         user = super(ThirdPartyUserCreationForm, self).save(commit=False)
         user.set_unusable_password()
@@ -244,7 +246,7 @@ class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm):
         ro = ('email',)
         for f in ro:
             self.fields[f].widget.attrs['readonly'] = True
-    
+
     def save(self, commit=True):
         user = super(InvitedThirdPartyUserCreationForm, self).save(commit=False)
         level = user.invitation.inviter.level + 1
@@ -257,7 +259,7 @@ class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm):
 
 class ShibbolethUserCreationForm(ThirdPartyUserCreationForm):
     additional_email = forms.CharField(widget=forms.HiddenInput(), label='', required = False)
-    
+
     def __init__(self, *args, **kwargs):
         super(ShibbolethUserCreationForm, self).__init__(*args, **kwargs)
         self.fields.keyOrder.append('additional_email')
@@ -265,7 +267,7 @@ class ShibbolethUserCreationForm(ThirdPartyUserCreationForm):
         name = 'email'
         field = self.fields[name]
         self.initial['additional_email'] = self.initial.get(name, field.initial)
-    
+
     def clean_email(self):
         email = self.cleaned_data['email']
         for user in AstakosUser.objects.filter(email = email):
@@ -279,30 +281,30 @@ class ShibbolethUserCreationForm(ThirdPartyUserCreationForm):
 
 class InvitedShibbolethUserCreationForm(ShibbolethUserCreationForm, InvitedThirdPartyUserCreationForm):
     pass
-    
+
 class LoginForm(AuthenticationForm):
     username = forms.EmailField(label=_("Email"))
     recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
     recaptcha_response_field = forms.CharField(widget=RecaptchaWidget, label='')
-    
+
     def __init__(self, *args, **kwargs):
         was_limited = kwargs.get('was_limited', False)
         request = kwargs.get('request', None)
         if request:
             self.ip = request.META.get('REMOTE_ADDR',
                                        request.META.get('HTTP_X_REAL_IP', None))
-        
+
         t = ('request', 'was_limited')
         for elem in t:
             if elem in kwargs.keys():
                 kwargs.pop(elem)
         super(LoginForm, self).__init__(*args, **kwargs)
-        
+
         self.fields.keyOrder = ['username', 'password']
         if was_limited and RECAPTCHA_ENABLED:
             self.fields.keyOrder.extend(['recaptcha_challenge_field',
                                          'recaptcha_response_field',])
-    
+
     def clean_recaptcha_response_field(self):
         if 'recaptcha_challenge_field' in self.cleaned_data:
             self.validate_captcha()
@@ -320,6 +322,12 @@ class LoginForm(AuthenticationForm):
         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', ''):
+            raise forms.ValidationError(_('Local login is not the current authentication method for this account.'))
+        return self.cleaned_data
+
 class ProfileForm(forms.ModelForm):
     """
     Subclass of ``ModelForm`` for permiting user to edit his/her profile.
@@ -385,7 +393,7 @@ class ExtendedPasswordResetForm(PasswordResetForm):
         except AstakosUser.DoesNotExist, e:
             raise forms.ValidationError(_('That e-mail address doesn\'t have an associated user account. Are you sure you\'ve registered?'))
         return email
-    
+
     def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
              use_https=False, token_generator=default_token_generator, request=None):
         """
@@ -406,20 +414,20 @@ class ExtendedPasswordResetForm(PasswordResetForm):
                 'support': DEFAULT_CONTACT_EMAIL
             }
             from_email = DEFAULT_FROM_EMAIL
-            send_mail(_("Password reset on %s alpha2 testing") % SITENAME,
+            send_mail(_(PASSWORD_RESET_EMAIL_SUBJECT),
                 t.render(Context(c)), from_email, [user.email])
 
 class EmailChangeForm(forms.ModelForm):
     class Meta:
         model = EmailChange
         fields = ('new_email_address',)
-            
+
     def clean_new_email_address(self):
         addr = self.cleaned_data['new_email_address']
         if AstakosUser.objects.filter(email__iexact=addr):
             raise forms.ValidationError(_(u'This email address is already in use. Please supply a different email address.'))
         return addr
-    
+
     def save(self, email_template_name, request, commit=True):
         ec = super(EmailChangeForm, self).save(commit=False)
         ec.user = request.user
@@ -445,14 +453,14 @@ class SignApprovalTermsForm(forms.ModelForm):
 
 class InvitationForm(forms.ModelForm):
     username = forms.EmailField(label=_("Email"))
-    
+
     def __init__(self, *args, **kwargs):
         super(InvitationForm, self).__init__(*args, **kwargs)
-    
+
     class Meta:
         model = Invitation
         fields = ('username', 'realname')
-    
+
     def clean_username(self):
         username = self.cleaned_data['username']
         try:
@@ -461,3 +469,50 @@ class InvitationForm(forms.ModelForm):
         except Invitation.DoesNotExist:
             pass
         return username
+
+class ExtendedPasswordChangeForm(PasswordChangeForm):
+    """
+    Extends PasswordChangeForm by enabling user
+    to optionally renew also the token.
+    """
+    if not NEWPASSWD_INVALIDATE_TOKEN:
+        renew = forms.BooleanField(label='Renew token', required=False,
+                                   initial=True,
+                                   help_text='Unsetting this may result in security risk.')
+
+    def __init__(self, user, *args, **kwargs):
+        super(ExtendedPasswordChangeForm, self).__init__(user, *args, **kwargs)
+
+    def save(self, commit=True):
+        user = super(ExtendedPasswordChangeForm, self).save(commit=False)
+        if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
+            user.renew_token()
+        if commit:
+            user.save()
+        return user
+
+class ExtendedSetPasswordForm(SetPasswordForm):
+    """
+    Extends SetPasswordForm by enabling user
+    to optionally renew also the token.
+    """
+    if not NEWPASSWD_INVALIDATE_TOKEN:
+        renew = forms.BooleanField(label='Renew token', required=False,
+                                   initial=True,
+                                   help_text='Unsetting this may result in security risk.')
+    
+    def __init__(self, user, *args, **kwargs):
+        super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs)
+    
+    def save(self, commit=True):
+        user = super(ExtendedSetPasswordForm, self).save(commit=False)
+        if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
+            try:
+                user = AstakosUser.objects.get(id=user.id)
+            except AstakosUser.DoesNotExist:
+                pass
+            else:
+                user.renew_token()
+        if commit:
+            user.save()
+        return user
\ No newline at end of file