From 212db8241a5b7414a407aa38cc34bc1068a22c54 Mon Sep 17 00:00:00 2001 From: Serghei MIHAI Date: Wed, 27 Aug 2014 10:49:33 +0200 Subject: [PATCH 1/2] django-registration dependency removed with, however, some concepts taken from it --- authentic2/app_settings.py | 8 +- authentic2/registration_backend/__init__.py | 59 ----------- .../registration_backend/default/__init__.py | 0 authentic2/registration_backend/default/forms.py | 83 +++++++++++++++ authentic2/registration_backend/default/models.py | 73 ++++++++++++++ authentic2/registration_backend/default/views.py | 58 +++++++++++ authentic2/registration_backend/forms.py | 90 ++--------------- authentic2/registration_backend/models.py | 56 +++++++++++ authentic2/registration_backend/urls.py | 34 +++---- authentic2/registration_backend/views.py | 112 ++++++++------------- authentic2/utils.py | 5 + requirements.txt | 1 - setup.py | 1 - 13 files changed, 342 insertions(+), 238 deletions(-) create mode 100644 authentic2/registration_backend/default/__init__.py create mode 100644 authentic2/registration_backend/default/forms.py create mode 100644 authentic2/registration_backend/default/models.py create mode 100644 authentic2/registration_backend/default/views.py create mode 100644 authentic2/registration_backend/models.py diff --git a/authentic2/app_settings.py b/authentic2/app_settings.py index c2c4bc5..2a45596 100644 --- a/authentic2/app_settings.py +++ b/authentic2/app_settings.py @@ -88,11 +88,13 @@ default_settings = dict( 'See http://www.openssl.org/docs/apps/verify.html#item__CApath'), A2_REGISTRATION_URLCONF = Setting(default='authentic2.registration_backend.urls', definition='Root urlconf for the /accounts endpoints'), - A2_REGISTRATION_FORM_CLASS = Setting(default='authentic2.registration_backend.forms.RegistrationForm', + A2_REGISTRATION_BACKEND = Setting(default='default', + definition='Backend for user\'s registration'), + A2_REGISTRATION_FORM_CLASS = Setting(default='authentic2.registration_backend.default.forms.RegistrationForm', definition='Default registration form'), - A2_REGISTRATION_SET_PASSWORD_FORM_CLASS = Setting(default='authentic2.registration_backend.forms.SetPasswordForm', + A2_REGISTRATION_SET_PASSWORD_FORM_CLASS = Setting(default='authentic2.registration_backend.default.forms.SetPasswordForm', definition='Default set password form'), - A2_REGISTRATION_CHANGE_PASSWORD_FORM_CLASS = Setting(default='authentic2.registration_backend.forms.PasswordChangeForm', + A2_REGISTRATION_CHANGE_PASSWORD_FORM_CLASS = Setting(default='authentic2.registration_backend.default.forms.PasswordChangeForm', definition='Default change password form'), A2_REGISTRATION_CAN_DELETE_ACCOUNT = Setting(default=True, definition='Can user self delete their account and all their data'), diff --git a/authentic2/registration_backend/__init__.py b/authentic2/registration_backend/__init__.py index 777e572..8b13789 100644 --- a/authentic2/registration_backend/__init__.py +++ b/authentic2/registration_backend/__init__.py @@ -1,60 +1 @@ -from django.conf import settings -from django.template.loader import render_to_string -from registration.models import RegistrationProfile - -def send_activation_email(self, site): - """ - Send an activation email to the user associated with this - ``RegistrationProfile``. - - The activation email will make use of two templates: - - ``registration/activation_email_subject.txt`` - This template will be used for the subject line of the - email. Because it is used as the subject line of an email, - this template's output **must** be only a single line of - text; output longer than one line will be forcibly joined - into only a single line. - - ``registration/activation_email.txt`` - This template will be used for the body of the email. - - These templates will each receive the following context - variables: - - ``user`` - The new user account - - ``activation_key`` - The activation key for the new account. - - ``expiration_days`` - The number of days remaining during which the account may - be activated. - - ``site`` - An object representing the site on which the user - registered; depending on whether ``django.contrib.sites`` - is installed, this may be an instance of either - ``django.contrib.sites.models.Site`` (if the sites - application is installed) or - ``django.contrib.sites.models.RequestSite`` (if - not). Consult the documentation for the Django sites - framework for details regarding these objects' interfaces. - - """ - ctx_dict = {'activation_key': self.activation_key, - 'user': self.user, - 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS, - 'site': site} - subject = render_to_string('registration/activation_email_subject.txt', - ctx_dict) - # Email subject *must not* contain newlines - subject = ''.join(subject.splitlines()) - - message = render_to_string('registration/activation_email.txt', - ctx_dict) - - self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) -RegistrationProfile.send_activation_email = send_activation_email diff --git a/authentic2/registration_backend/default/__init__.py b/authentic2/registration_backend/default/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentic2/registration_backend/default/forms.py b/authentic2/registration_backend/default/forms.py new file mode 100644 index 0000000..bf76f61 --- /dev/null +++ b/authentic2/registration_backend/default/forms.py @@ -0,0 +1,83 @@ +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +from django.utils.datastructures import SortedDict +from django.db.models import FieldDoesNotExist + +from authentic2 import app_settings, compat, forms, utils, validators +from ..forms import RegistrationForm as BaseRegistrationForm, SetPasswordForm, PasswordChangeForm + +class RegistrationForm(forms.UserAttributeFormMixin, BaseRegistrationForm): + + def __init__(self, *args, **kwargs): + """ + Inject required fields in registration form + """ + super(RegistrationForm, self).__init__(*args, **kwargs) + User = compat.get_user_model() + insert_idx = 0 + field_names = compat.get_registration_fields() + required_fields = set(compat.get_required_fields()) + for field_name in field_names: + if field_name not in self.fields: + try: + model_field = User._meta.get_field(field_name) + except FieldDoesNotExist: + pass + else: + kwargs = {} + if hasattr(model_field, 'validators'): + kwargs['validators'] = model_field.validators + field = model_field.formfield(**kwargs) + self.fields.insert(insert_idx, field_name, field) + insert_idx += 1 + for field_name in self.fields: + if field_name in required_fields: + self.fields[field_name].required = True + # reorder fields obeying A2_REGISTRATION_FIELDS + new_fields = SortedDict() + for field_name in utils.field_names(app_settings.A2_REGISTRATION_FIELDS): + if field_name in self.fields: + new_fields[field_name] = self.fields[field_name] + for field_name in self.fields: + if field_name not in new_fields: + new_fields[field_name] = self.fields[field_name] + # override titles + for field in app_settings.A2_REGISTRATION_FIELDS: + if isinstance(field, (list, tuple)): + if len(field) > 1: + self.fields[field[0]].label = field[1] + + self.fields = new_fields + if 'username' in self.fields: + self.fields['username'].regex = app_settings.A2_REGISTRATION_FORM_USERNAME_REGEX + self.fields['username'].help_text = app_settings.A2_REGISTRATION_FORM_USERNAME_HELP_TEXT + self.fields['username'].label = app_settings.A2_REGISTRATION_FORM_USERNAME_LABEL + + def clean_username(self): + """ + Validate that the username is alphanumeric and is not already + in use. + """ + User = compat.get_user_model() + username = self.cleaned_data['username'] + if app_settings.A2_REGISTRATION_REALM: + if '@' in username: + raise ValidationError(_('The character @ is forbidden in usernames.')) + username = u'{0}@{1}'.format(username, app_settings.A2_REGISTRATION_REALM) + self.cleaned_data['username'] = username + existing = User.objects.filter(username__iexact=self.cleaned_data['username']) + if existing.exists(): + raise ValidationError(_("A user with that username already exists.")) + else: + return self.cleaned_data['username'] + + def clean_email(self): + """ + Verify if email is unique + """ + User = compat.get_user_model() + if app_settings.A2_REGISTRATION_EMAIL_IS_UNIQUE: + if User.objects.filter(email__iexact=self.cleaned_data['email']): + raise ValidationError(_('This email address is already in ' + 'use. Please supply a different email address.')) + return self.cleaned_data['email'] diff --git a/authentic2/registration_backend/default/models.py b/authentic2/registration_backend/default/models.py new file mode 100644 index 0000000..da45839 --- /dev/null +++ b/authentic2/registration_backend/default/models.py @@ -0,0 +1,73 @@ +from django.utils.translation import ugettext_lazy as _ +from django.contrib.sites.models import RequestSite +from django.contrib.sites.models import Site +from django.contrib.auth.models import BaseUserManager, Group +from django.db import models + +from authentic2 import app_settings, compat, models as a2_models + +from ..models import RegistrationProfile as BaseRegistrationProfile +from ..models import ACTIVATION_KEY_RE + +User = compat.get_user_model() + +class RegistrationProfile(BaseRegistrationProfile, models.Model): + user = models.ForeignKey(User, unique=True, related_name='profile') + activation_key = models.CharField(_(u'User\'s activation key'), + max_length=64, db_index=True) + + def activate_user(self, activation_key): + if ACTIVATION_KEY_RE.search(activation_key): + try: + self = RegistrationProfile.objects.get(activation_key=activation_key) + if not self.activation_key_expired(): + self.user.is_active = True + self.user.save() + self.activation_key = self.model.ACTIVATED + self.save() + return self.user + except self.DoesNotExist: + return False + return False + + def create_profile(self, user, site): + self.user = user + self.activation_key = self.activation_token + self.save() + self.send_activation_email(site) + + def create_inactive_user(self, request, **cleaned_data): + User = compat.get_user_model() + if Site._meta.installed: + site = Site.objects.get_current() + else: + site = RequestSite(request) + user_fields = {} + for field in compat.get_registration_fields(): + # save User model fields + try: + User._meta.get_field(field) + except models.FieldDoesNotExist: + continue + if field.startswith('password'): + continue + user_fields[field] = cleaned_data[field] + if field == 'email': + user_fields[field] = BaseUserManager.normalize_email(user_fields[field]) + + new_user = User(is_active=False, **user_fields) + new_user.clean() + new_user.set_password(cleaned_data['password1']) + new_user.save() + attributes = a2_models.Attribute.objects.filter( + asked_on_registration=True) + if attributes: + for attribute in attributes: + attribute.set_value(new_user, cleaned_data[attribute.name]) + if app_settings.A2_REGISTRATION_GROUPS: + groups = [] + for name in app_settings.A2_REGISTRATION_GROUPS: + group, created = Group.objects.get_or_create(name=name) + groups.append(group) + new_user.groups = groups + return new_user, site diff --git a/authentic2/registration_backend/default/views.py b/authentic2/registration_backend/default/views.py new file mode 100644 index 0000000..7a2870b --- /dev/null +++ b/authentic2/registration_backend/default/views.py @@ -0,0 +1,58 @@ +import logging + +from django.shortcuts import redirect, render +from django.utils.translation import ugettext as _ +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.auth import views as auth_views +from django.conf import settings + +from authentic2 import app_settings, models + +from ..views import RegistrationView as BaseRegistrationView +from ..views import ActivationView as BaseActivationView +from .models import RegistrationProfile +from .forms import RegistrationForm + +logger = logging.getLogger(__name__) + +class RegistrationView(BaseRegistrationView): + + form_class = RegistrationForm + + def register(self, request, **cleaned_data): + profile = RegistrationProfile() + new_user = profile.create_user(request, **cleaned_data) + return new_user + +register = RegistrationView.as_view() + +class ActivationView(BaseActivationView): + def activate(self, request, activation_key): + profile = RegistrationProfile() + return profile.activate_user(activation_key) + +activate = ActivationView.as_view() + + +@login_required +def delete(request, next_url='/'): + next_url = request.build_absolute_uri(request.META.get('HTTP_REFERER') or next_url) + if not app_settings.A2_REGISTRATION_CAN_DELETE_ACCOUNT: + return redirect(next_url) + if request.method == 'POST': + if 'submit' in request.POST: + models.DeletedUser.objects.delete_user(request.user) + logger.info(u'deletion of account %s requested' % request.user) + messages.info(request, _('Your account has been scheduled for deletion. You cannot use it anymore.')) + return redirect('auth_logout') + else: + return redirect(next_url) + return render(request, 'registration/delete_account.html') + +password_change = auth_views.password_change +password_change_done = auth_views.password_change_done +password_reset = auth_views.password_reset +password_reset_confirm = auth_views.password_reset_confirm +password_reset_complete = auth_views.password_reset_complete +password_reset_done = auth_views.password_reset_done diff --git a/authentic2/registration_backend/forms.py b/authentic2/registration_backend/forms.py index 965825a..75abf1b 100644 --- a/authentic2/registration_backend/forms.py +++ b/authentic2/registration_backend/forms.py @@ -1,15 +1,11 @@ -from django.core.exceptions import ValidationError -from django.utils.translation import ugettext_lazy as _ from django.forms import Form, CharField, PasswordInput -from django.utils.datastructures import SortedDict -from django.db.models import FieldDoesNotExist - -from django.contrib.auth import forms as auth_forms +from django.utils.translation import ugettext_lazy as _ -from .. import app_settings, compat, forms, utils, validators +from django.contrib.auth import forms +from authentic2 import validators -class RegistrationForm(forms.UserAttributeFormMixin, Form): +class RegistrationForm(Form): error_css_class = 'form-field-error' required_css_class = 'form-field-required' @@ -17,79 +13,11 @@ class RegistrationForm(forms.UserAttributeFormMixin, Form): validators=[validators.validate_password]) password2 = CharField(widget=PasswordInput, label=_("Password (again)")) - def __init__(self, *args, **kwargs): - """ - Inject required fields in registration form - """ - super(RegistrationForm, self).__init__(*args, **kwargs) - User = compat.get_user_model() - insert_idx = 0 - field_names = compat.get_registration_fields() - required_fields = set(compat.get_required_fields()) - for field_name in field_names: - if field_name not in self.fields: - try: - model_field = User._meta.get_field(field_name) - except FieldDoesNotExist: - pass - else: - kwargs = {} - if hasattr(model_field, 'validators'): - kwargs['validators'] = model_field.validators - field = model_field.formfield(**kwargs) - self.fields.insert(insert_idx, field_name, field) - insert_idx += 1 - for field_name in self.fields: - if field_name in required_fields: - self.fields[field_name].required = True - # reorder fields obeying A2_REGISTRATION_FIELDS - new_fields = SortedDict() - for field_name in utils.field_names(app_settings.A2_REGISTRATION_FIELDS): - if field_name in self.fields: - new_fields[field_name] = self.fields[field_name] - for field_name in self.fields: - if field_name not in new_fields: - new_fields[field_name] = self.fields[field_name] - # override titles - for field in app_settings.A2_REGISTRATION_FIELDS: - if isinstance(field, (list, tuple)): - if len(field) > 1: - self.fields[field[0]].label = field[1] - - self.fields = new_fields - if 'username' in self.fields: - self.fields['username'].regex = app_settings.A2_REGISTRATION_FORM_USERNAME_REGEX - self.fields['username'].help_text = app_settings.A2_REGISTRATION_FORM_USERNAME_HELP_TEXT - self.fields['username'].label = app_settings.A2_REGISTRATION_FORM_USERNAME_LABEL - def clean_username(self): - """ - Validate that the username is alphanumeric and is not already - in use. - """ - User = compat.get_user_model() - username = self.cleaned_data['username'] - if app_settings.A2_REGISTRATION_REALM: - if '@' in username: - raise ValidationError(_('The character @ is forbidden in usernames.')) - username = u'{0}@{1}'.format(username, app_settings.A2_REGISTRATION_REALM) - self.cleaned_data['username'] = username - existing = User.objects.filter(username__iexact=self.cleaned_data['username']) - if existing.exists(): - raise ValidationError(_("A user with that username already exists.")) - else: - return self.cleaned_data['username'] + raise NotImplementedError def clean_email(self): - """ - Verify if email is unique - """ - User = compat.get_user_model() - if app_settings.A2_REGISTRATION_EMAIL_IS_UNIQUE: - if User.objects.filter(email__iexact=self.cleaned_data['email']): - raise ValidationError(_('This email address is already in ' - 'use. Please supply a different email address.')) - return self.cleaned_data['email'] + raise NotImplementedError def clean(self): """ @@ -103,14 +31,12 @@ class RegistrationForm(forms.UserAttributeFormMixin, Form): raise ValidationError(_("The two password fields didn't match.")) return self.cleaned_data -class SetPasswordForm(auth_forms.SetPasswordForm): +class SetPasswordForm(forms.SetPasswordForm): new_password1 = CharField(label=_("New password"), widget=PasswordInput, validators=[validators.validate_password]) -class PasswordChangeForm(auth_forms.PasswordChangeForm): +class PasswordChangeForm(forms.PasswordChangeForm): new_password1 = CharField(label=_("New password"), widget=PasswordInput, validators=[validators.validate_password]) - - diff --git a/authentic2/registration_backend/models.py b/authentic2/registration_backend/models.py new file mode 100644 index 0000000..c894a87 --- /dev/null +++ b/authentic2/registration_backend/models.py @@ -0,0 +1,56 @@ +import hashlib +import random +import re +from datetime import datetime, timedelta + +from django.conf import settings +from django.template.loader import render_to_string +from django.core.mail import send_mail + +ACTIVATION_KEY_RE = re.compile('^[a-f0-9]{40}$') + +class RegistrationProfile(object): + ACTIVATED = 'ACTIVATED' + + def __unicode__(self): + return u"Registration information for %s" % self.user + + @property + def activation_token(self): + salt = hashlib.sha1(str(random.random())).hexdigest()[:5] + now = datetime.now().isoformat() + activation_key = hashlib.sha1(salt+now).hexdigest() + return activation_key + + def create_profile(self, user, site): + raise NotImplementedError + + def create_inactive_user(self, request, **cleaned_data): + raise NotImplementedError + + def create_user(self, *args, **kwargs): + user, site = self.create_inactive_user(*args, **kwargs) + self.create_profile(user, site) + return user + + def activate_user(self, activation_key): + raise NotImplementedError + + def activation_key_expired(self): + expiration_date = timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS) + return self.activation_key == self.ACTIVATED or \ + (self.user.date_joined + expiration_date <= datetime.now()) + activation_key_expired.boolean = True + + def send_activation_email(self, site): + ctx_dict = {'activation_key': self.activation_key, + 'user': self.user, + 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS, + 'site': site} + subject = render_to_string('registration/activation_email_subject.txt', + ctx_dict) + subject = ''.join(subject.splitlines()) + message = render_to_string('registration/activation_email.txt', + ctx_dict) + send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, + [self.user.email], fail_silently=True) diff --git a/authentic2/registration_backend/urls.py b/authentic2/registration_backend/urls.py index f5754e1..28d9743 100644 --- a/authentic2/registration_backend/urls.py +++ b/authentic2/registration_backend/urls.py @@ -1,28 +1,18 @@ from django.conf.urls import patterns from django.conf.urls import url -from django.utils.importlib import import_module -from django.contrib.auth import views as auth_views from django.views.generic.base import TemplateView - from .. import app_settings - -from registration.backends.default.views import ActivationView - - -def get_form_class(form_class): - module, form_class = form_class.rsplit('.', 1) - module = import_module(module) - return getattr(module, form_class) - +from ..utils import get_form_class SET_PASSWORD_FORM_CLASS = get_form_class( app_settings.A2_REGISTRATION_SET_PASSWORD_FORM_CLASS) CHANGE_PASSWORD_FORM_CLASS = get_form_class( app_settings.A2_REGISTRATION_CHANGE_PASSWORD_FORM_CLASS) +REGISTRATION_BACKEND = app_settings.A2_REGISTRATION_BACKEND -urlpatterns = patterns('authentic2.registration_backend.views', +urlpatterns = patterns('authentic2.registration_backend.%s.views' % REGISTRATION_BACKEND, url(r'^activate/complete/$', TemplateView.as_view(template_name='registration/activation_complete.html'), name='registration_activation_complete'), @@ -31,7 +21,7 @@ urlpatterns = patterns('authentic2.registration_backend.views', # that way it can return a sensible "invalid key" message instead of a # confusing 404. url(r'^activate/(?P\w+)/$', - ActivationView.as_view(), + 'activate', name='registration_activate'), url(r'^register/$', 'register', @@ -43,24 +33,26 @@ urlpatterns = patterns('authentic2.registration_backend.views', TemplateView.as_view(template_name='registration/registration_closed.html'), name='registration_disallowed'), url(r'^password/change/$', - auth_views.password_change, - {'password_change_form': CHANGE_PASSWORD_FORM_CLASS}, + 'password_change', + {'password_change_form': CHANGE_PASSWORD_FORM_CLASS, + 'post_change_redirect': 'done'}, name='auth_password_change'), url(r'^password/change/done/$', - auth_views.password_change_done, + 'password_change_done', name='auth_password_change_done'), url(r'^password/reset/$', - auth_views.password_reset, + 'password_reset', + {'post_reset_redirect': 'done'}, name='auth_password_reset'), url(r'^password/reset/confirm/(?P[0-9A-Za-z]+)-(?P.+)/$', - auth_views.password_reset_confirm, + 'password_reset_confirm', {'set_password_form': SET_PASSWORD_FORM_CLASS}, name='auth_password_reset_confirm'), url(r'^password/reset/complete/$', - auth_views.password_reset_complete, + 'password_reset_complete', name='auth_password_reset_complete'), url(r'^password/reset/done/$', - auth_views.password_reset_done, + 'password_reset_done', name='auth_password_reset_done'), url(r'^delete/$', 'delete', diff --git a/authentic2/registration_backend/views.py b/authentic2/registration_backend/views.py index 3602e9a..9f203bb 100644 --- a/authentic2/registration_backend/views.py +++ b/authentic2/registration_backend/views.py @@ -1,97 +1,67 @@ import logging - from django.shortcuts import redirect, render from django.utils.translation import ugettext as _ from django.contrib import messages from django.contrib.auth.decorators import login_required -from django.contrib.sites.models import RequestSite -from django.contrib.sites.models import Site -from django.contrib.auth.models import BaseUserManager, Group from django.conf import settings -from django.db.models import FieldDoesNotExist +from django.views.generic.edit import FormView +from django.views.generic.base import TemplateView +from django.shortcuts import redirect +from .. import models, app_settings, compat -from registration.views import RegistrationView as BaseRegistrationView -from registration.models import RegistrationProfile -from registration import signals +logger = logging.getLogger(__name__) -from .. import models, app_settings, compat -from . import urls +class RegistrationView(FormView): -logger = logging.getLogger(__name__) + disallowed_url = 'registration_disallowed' + template_name = 'registration/registration_form.html' + def dispatch(self, request, *args, **kwargs): + if not self.registration_allowed(request): + return redirect(self.disallowed_url) + return super(RegistrationView, self).dispatch(request, *args, **kwargs) -class RegistrationView(BaseRegistrationView): - form_class = urls.get_form_class(app_settings.A2_REGISTRATION_FORM_CLASS) + def post(self, request, *args, **kwargs): + form_class = self.get_form_class() + form = self.get_form(form_class) + if form.is_valid(): + return self.form_valid(request, form) + else: + return self.form_invalid(form) def register(self, request, **cleaned_data): - User = compat.get_user_model() - if Site._meta.installed: - site = Site.objects.get_current() - else: - site = RequestSite(request) - user_fields = {} - for field in compat.get_registration_fields(): - # save User model fields - try: - User._meta.get_field(field) - except FieldDoesNotExist: - continue - if field.startswith('password'): - continue - user_fields[field] = cleaned_data[field] - if field == 'email': - user_fields[field] = BaseUserManager.normalize_email(user_fields[field]) - new_user = User(is_active=False, **user_fields) - new_user.clean() - new_user.set_password(cleaned_data['password1']) - new_user.save() - attributes = models.Attribute.objects.filter( - asked_on_registration=True) - if attributes: - for attribute in attributes: - attribute.set_value(new_user, cleaned_data[attribute.name]) - if app_settings.A2_REGISTRATION_GROUPS: - groups = [] - for name in app_settings.A2_REGISTRATION_GROUPS: - group, created = Group.objects.get_or_create(name=name) - groups.append(group) - new_user.groups = groups - registration_profile = RegistrationProfile.objects.create_profile(new_user) - registration_profile.send_activation_email(site) - - signals.user_registered.send(sender=self.__class__, - user=new_user, - request=request) - return new_user + raise NotImplementedError def registration_allowed(self, request): - """ - Indicate whether account registration is currently permitted, - based on the value of the setting ``REGISTRATION_OPEN``. This - is determined as follows: - - * If ``REGISTRATION_OPEN`` is not specified in settings, or is - set to ``True``, registration is permitted. - - * If ``REGISTRATION_OPEN`` is both specified and set to - ``False``, registration is not permitted. - - """ return getattr(settings, 'REGISTRATION_OPEN', True) - def get_success_url(self, request, user): - """ - Return the name of the URL to redirect to after successful - user registration. - - """ - return ('registration_complete', (), {}) + def get_success_url(self): + return ('registration_complete') + + def form_valid(self, request, form): + self.register(request, **form.cleaned_data) + return redirect(self.get_success_url()) register = RegistrationView.as_view() +class ActivationView(TemplateView): + http_method_names = ['get'] + template_name = 'registration/activate.html' + + def get(self, request, *args, **kwargs): + activated_user = self.activate(request, *args, **kwargs) + if activated_user: + return redirect(self.get_success_url()) + + def activate(self, request, *args, **kwargs): + raise NotImplementedError + + def get_success_url(self): + return ('registration_activation_complete') + @login_required def delete(request, next_url='/'): diff --git a/authentic2/utils.py b/authentic2/utils.py index 6678ab2..115ca3b 100644 --- a/authentic2/utils.py +++ b/authentic2/utils.py @@ -206,3 +206,8 @@ def field_names(list_of_field_name_and_titles): yield t else: yield t[0] + +def get_form_class(form_class): + module, form_class = form_class.rsplit('.', 1) + module = import_module(module) + return getattr(module, form_class) diff --git a/requirements.txt b/requirements.txt index 466ed1c..8720c59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,6 @@ Django<1.6 south>=0.8.4,<0.9 requests django-model-utils -django-registration>=1 django-debug-toolbar>=1.2,<1.3 --allow-external django-admin-tools --allow-unverified django-admin-tools diff --git a/setup.py b/setup.py index 23d3202..c446349 100755 --- a/setup.py +++ b/setup.py @@ -117,7 +117,6 @@ setup(name="authentic2", 'south>=0.8.4,<0.9', 'requests', 'django-model-utils', - 'django-registration>=1', 'django-admin-tools>=0.5.1', 'django-debug-toolbar>=1.2,<1.3', 'dnspython', -- 2.1.0