diff --git a/ChangeLog b/ChangeLog index dbfc24cf16..bc8fb0c3bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-04-25 Raymond Penners + + * Added support for differentiating e-mail handling (verification, + required) between local and social accounts: + `SOCIALACCOUNT_EMAIL_REQUIRED` and + `SOCIALACCOUNT_EMAIL_VERIFICATION`. + 2013-04-16 Raymond Penners * Version 0.10.1 released. diff --git a/README.rst b/README.rst index 2a4b8d7650..ec91856367 100644 --- a/README.rst +++ b/README.rst @@ -293,8 +293,15 @@ SOCIALACCOUNT_AVATAR_SUPPORT (= 'avatar' in settings.INSTALLED_APPS) Enable support for django-avatar. When enabled, the profile image of the user is copied locally into django-avatar at signup. +SOCIALACCOUNT_EMAIL_REQUIRED (=ACCOUNT_EMAIL_REQUIRED) + The user is required to hand over an e-mail address when signing up + using a social account. + +SOCIALACCOUNT_EMAIL_VERIFICATION (=ACCOUNT_EMAIL_VERIFICATION) + As `ACCOUNT_EMAIL_VERIFICATION`, but for social accounts. + SOCIALACCOUNT_PROVIDERS (= dict) - Dictionary containing provider specific settings. + Dictionary containing provider specific settings. Upgrading diff --git a/allauth/account/forms.py b/allauth/account/forms.py index f41bffffc7..99357f2f6f 100644 --- a/allauth/account/forms.py +++ b/allauth/account/forms.py @@ -14,7 +14,7 @@ from .models import EmailAddress from .utils import perform_login, send_email_confirmation, setup_user_email -from .app_settings import AuthenticationMethod, EmailVerificationMethod +from .app_settings import AuthenticationMethod from . import app_settings from .adapter import get_adapter @@ -120,7 +120,9 @@ def clean(self): return self.cleaned_data def login(self, request, redirect_url=None): - ret = perform_login(request, self.user, redirect_url=redirect_url) + ret = perform_login(request, self.user, + email_verification=app_settings.EMAIL_VERIFICATION, + redirect_url=redirect_url) if self.cleaned_data["remember"]: request.session.set_expiry(60 * 60 * 24 * 7 * 3) else: @@ -171,12 +173,9 @@ class BaseSignupForm(_base_signup_form_class()): _('E-mail address') })) def __init__(self, *args, **kwargs): + email_required = kwargs.pop('email_required') super(BaseSignupForm, self).__init__(*args, **kwargs) - if (app_settings.EMAIL_REQUIRED - or (app_settings.EMAIL_VERIFICATION - == EmailVerificationMethod.MANDATORY) - or (app_settings.AUTHENTICATION_METHOD - == AuthenticationMethod.EMAIL)): + if email_required: self.fields["email"].label = ugettext("E-mail") self.fields["email"].required = True else: @@ -230,6 +229,7 @@ class SignupForm(BaseSignupForm): widget = forms.HiddenInput()) def __init__(self, *args, **kwargs): + kwargs['email_required'] = app_settings.EMAIL_REQUIRED super(SignupForm, self).__init__(*args, **kwargs) current_order =self.fields.keyOrder preferred_order = self.fields.keyOrder = ["username", diff --git a/allauth/account/tests.py b/allauth/account/tests.py index 7b3206a7b1..f45db8f837 100644 --- a/allauth/account/tests.py +++ b/allauth/account/tests.py @@ -171,7 +171,7 @@ def test_username_in_blacklist(self): 'username': 'username', 'email': 'user@example.com', } - form = BaseSignupForm(data) + form = BaseSignupForm(data, email_required=True) self.assertFalse(form.is_valid()) @override_settings( @@ -182,5 +182,5 @@ def test_username_not_in_blacklist(self): 'username': 'theusername', 'email': 'user@example.com', } - form = BaseSignupForm(data) + form = BaseSignupForm(data, email_required=True) self.assertTrue(form.is_valid()) diff --git a/allauth/account/utils.py b/allauth/account/utils.py index 764c187737..63604496b1 100644 --- a/allauth/account/utils.py +++ b/allauth/account/utils.py @@ -96,13 +96,13 @@ def user_email(user, *args): # return False -def perform_login(request, user, redirect_url=None): +def perform_login(request, user, email_verification, redirect_url=None): from .models import EmailAddress # not is_active: social users are redirected to a template # local users are stopped due to form validation checking is_active assert user.is_active - if (app_settings.EMAIL_VERIFICATION == EmailVerificationMethod.MANDATORY + if (email_verification == EmailVerificationMethod.MANDATORY and not EmailAddress.objects.filter(user=user, verified=True).exists()): send_email_confirmation(request, user) @@ -125,12 +125,14 @@ def perform_login(request, user, redirect_url=None): return HttpResponseRedirect(get_login_redirect_url(request, redirect_url)) -def complete_signup(request, user, success_url, signal_kwargs={}): +def complete_signup(request, user, email_verification, success_url, signal_kwargs={}): signals.user_signed_up.send(sender=user.__class__, request=request, user=user, **signal_kwargs) - return perform_login(request, user, redirect_url=success_url) + return perform_login(request, user, + email_verification=email_verification, + redirect_url=success_url) def cleanup_email_addresses(request, addresses): diff --git a/allauth/account/views.py b/allauth/account/views.py index 82d6740015..b61ecbe330 100644 --- a/allauth/account/views.py +++ b/allauth/account/views.py @@ -122,7 +122,9 @@ def get_success_url(self): def form_valid(self, form): user = form.save(self.request) - return complete_signup(self.request, user, self.get_success_url()) + return complete_signup(self.request, user, + app_settings.EMAIL_VERIFICATION, + self.get_success_url()) def get_context_data(self, **kwargs): ret = super(SignupView, self).get_context_data(**kwargs) diff --git a/allauth/socialaccount/app_settings.py b/allauth/socialaccount/app_settings.py index 0bb247a9ab..685c8c94d9 100644 --- a/allauth/socialaccount/app_settings.py +++ b/allauth/socialaccount/app_settings.py @@ -46,6 +46,23 @@ def PROVIDERS(self): """ return self._setting("PROVIDERS", {}) + @property + def EMAIL_REQUIRED(self): + """ + The user is required to hand over an e-mail address when signing up + """ + from allauth.account import app_settings as account_settings + return self._setting("EMAIL_REQUIRED", account_settings.EMAIL_REQUIRED) + + @property + def EMAIL_VERIFICATION(self): + """ + See e-mail verification method + """ + from allauth.account import app_settings as account_settings + return self._setting("EMAIL_VERIFICATION", + account_settings.EMAIL_VERIFICATION) + @property def ADAPTER(self): return self._setting \ diff --git a/allauth/socialaccount/forms.py b/allauth/socialaccount/forms.py index 5d4dd6ef0e..ab5b2164a6 100644 --- a/allauth/socialaccount/forms.py +++ b/allauth/socialaccount/forms.py @@ -8,6 +8,8 @@ from .models import SocialAccount +from . import app_settings + class SignupForm(BaseSignupForm): def __init__(self, *args, **kwargs): @@ -18,6 +20,7 @@ def __init__(self, *args, **kwargs): 'first_name': user.first_name or '', 'last_name': user.last_name or '' } kwargs['initial'] = initial + kwargs['email_required'] = app_settings.EMAIL_REQUIRED super(SignupForm, self).__init__(*args, **kwargs) def save(self, request): diff --git a/allauth/socialaccount/helpers.py b/allauth/socialaccount/helpers.py index 0dd2a19b29..611ab592eb 100644 --- a/allauth/socialaccount/helpers.py +++ b/allauth/socialaccount/helpers.py @@ -43,7 +43,7 @@ def _process_signup(request, sociallogin): # FIXME: We redirect to signup form -- user will # see email address conflict only after posting # whereas we detected it here already. - elif account_settings.EMAIL_REQUIRED: + elif app_settings.EMAIL_REQUIRED: # Nope, email is required and we don't have it yet... auto_signup = False if not auto_signup: @@ -87,6 +87,7 @@ def _login_social_account(request, sociallogin): context_instance=RequestContext(request)) else: ret = perform_login(request, user, + email_verification=app_settings.EMAIL_VERIFICATION, redirect_url=sociallogin.get_redirect_url(request)) return ret @@ -194,6 +195,7 @@ def complete_social_signup(request, sociallogin): _copy_avatar(request, sociallogin.account.user, sociallogin.account) return complete_signup(request, sociallogin.account.user, + app_settings.EMAIL_VERIFICATION, sociallogin.get_redirect_url(request), signal_kwargs={'sociallogin': sociallogin})