diff --git a/ietf/registration/forms.py b/ietf/ietfauth/forms.py similarity index 82% rename from ietf/registration/forms.py rename to ietf/ietfauth/forms.py index 1bb2d7626..245783b11 100644 --- a/ietf/registration/forms.py +++ b/ietf/ietfauth/forms.py @@ -5,7 +5,6 @@ import hashlib from django import forms from django.conf import settings from django.contrib.auth.models import User -from django.contrib.auth.forms import PasswordResetForm from django.contrib.sites.models import Site from django.utils.translation import ugettext, ugettext_lazy as _ @@ -35,10 +34,10 @@ class RegistrationForm(forms.Form): 'today': today, 'realm': self.realm, 'auth': auth, - 'to_email': to_email, + 'username': to_email, 'expire': settings.DAYS_TO_EXPIRE_REGISTRATION_LINK, } - send_mail(None, to_email, from_email, subject, 'registration/register_email.txt', context) + send_mail(None, to_email, from_email, subject, 'registration/creation_email.txt', context) def clean_email(self): email = self.cleaned_data.get('email', '') @@ -49,26 +48,29 @@ class RegistrationForm(forms.Form): return email -class RecoverPasswordForm(PasswordResetForm): +class RecoverPasswordForm(RegistrationForm): realm = 'IETF' - def save(self): + def send_email(self): domain = Site.objects.get_current().domain subject = 'Password recovery at %s' % domain from_email = settings.DEFAULT_FROM_EMAIL today = datetime.date.today().strftime('%Y%m%d') - for user in self.users_cache: - to_email = self.cleaned_data["email"] - recovery_hash = hashlib.md5('%s%s%s%s%s' % (settings.SECRET_KEY, today, user.username, user.password, self.realm)).hexdigest() - context = {'domain': domain, - 'username': user.username, - 'recovery_hash': recovery_hash, - 'today': today, - 'realm': self.realm, - 'expire': settings.DAYS_TO_EXPIRE_RECOVER_LINK, - } - send_mail(None, to_email, from_email, subject, 'registration/password_recovery_email.txt', context) + to_email = self.cleaned_data["email"] + auth = hashlib.md5('%s%s%s%s' % (settings.SECRET_KEY, today, to_email, self.realm)).hexdigest() + context = {'domain': domain, + 'today': today, + 'realm': self.realm, + 'auth': auth, + 'username': to_email, + 'expire': settings.DAYS_TO_EXPIRE_REGISTRATION_LINK, + } + send_mail(None, to_email, from_email, subject, 'registration/password_reset_email.txt', context) + + def clean_email(self): + email = self.cleaned_data.get('email', '') + return email class PasswordForm(forms.Form): diff --git a/ietf/ietfauth/urls.py b/ietf/ietfauth/urls.py index daf665c36..caa14f52d 100644 --- a/ietf/ietfauth/urls.py +++ b/ietf/ietfauth/urls.py @@ -1,11 +1,20 @@ # Copyright The IETF Trust 2007, 2009, All Rights Reserved -from django.conf.urls.defaults import patterns +from django.conf.urls.defaults import patterns, url from ietf.ietfauth import views urlpatterns = patterns('', + (r'^$', views.index, None, 'account_index'), (r'^login/$', views.ietf_login), (r'^loggedin/$', views.ietf_loggedin), (r'^profile/$', views.profile), # (r'^login/(?P[a-z0-9.@]+)/(?P.+)$', views.url_login), ) + +urlpatterns += patterns('ietf.ietfauth.views', + url(r'^create/$', 'create_account', name='create_account'), + url(r'^confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[\w]+)/(?P[a-f0-9]+)/$', 'confirm_account', name='confirm_account'), + url(r'^reset/$', 'password_reset_view', name='password_reset'), + url(r'^reset/confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[\w]+)/(?P[a-f0-9]+)/$', 'confirm_password_reset', name='confirm_password_reset'), + url(r'^ajax/check_username/$', 'ajax_check_username', name='ajax_check_username'), +) diff --git a/ietf/ietfauth/views.py b/ietf/ietfauth/views.py index 5750d23cc..f8e2749a3 100644 --- a/ietf/ietfauth/views.py +++ b/ietf/ietfauth/views.py @@ -32,15 +32,27 @@ # Copyright The IETF Trust 2007, All Rights Reserved -from django.template import RequestContext -from django.shortcuts import render_to_response -from django.contrib.auth.decorators import login_required -from django.http import HttpResponseRedirect, HttpResponse -from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login -from django.contrib.auth.models import User +import datetime +import hashlib + from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from django.http import HttpResponseRedirect, HttpResponse, Http404 +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.utils import simplejson from django.utils.http import urlquote +from ietf.ietfauth.forms import (RegistrationForm, PasswordForm, + RecoverPasswordForm) + + +def index(request): + return render_to_response('registration/index.html', context_instance=RequestContext(request)) + + def url_login(request, user, passwd): user = authenticate(username=user, password=passwd) redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '') @@ -48,7 +60,8 @@ def url_login(request, user, passwd): if user.is_active: login(request, user) return HttpResponseRedirect('/accounts/loggedin/?%s=%s' % (REDIRECT_FIELD_NAME, urlquote(redirect_to))) - return HttpResponse("Not authenticated?", status=500) + return HttpResponse("Not authenticated?", status=500) + def ietf_login(request): if not request.user.is_authenticated(): @@ -58,6 +71,7 @@ def ietf_login(request): request.session.set_test_cookie() return HttpResponseRedirect('/accounts/loggedin/?%s=%s' % (REDIRECT_FIELD_NAME, urlquote(redirect_to))) + def ietf_loggedin(request): if not request.session.test_cookie_worked(): return HttpResponse("You need to enable cookies") @@ -66,13 +80,14 @@ def ietf_loggedin(request): if not redirect_to or '//' in redirect_to or ' ' in redirect_to: redirect_to = settings.LOGIN_REDIRECT_URL return HttpResponseRedirect(redirect_to) - + + @login_required def profile(request): if settings.USE_DB_REDESIGN_PROXY_CLASSES: from person.models import Person from group.models import Role - + roles = [] person = None try: @@ -80,10 +95,87 @@ def profile(request): roles = Role.objects.filter(email__person=person).distinct() except Person.DoesNotExist: pass - + return render_to_response('registration/profileREDESIGN.html', dict(roles=roles, person=person), context_instance=RequestContext(request)) - + return render_to_response('registration/profile.html', context_instance=RequestContext(request)) + + +def create_account(request): + success = False + if request.method == 'POST': + form = RegistrationForm(request.POST) + if form.is_valid(): + form.save() + success = True + else: + form = RegistrationForm() + return render_to_response('registration/create.html', + {'form': form, + 'success': success}, + context_instance=RequestContext(request)) + + +def confirm_account(request, username, date, realm, registration_hash): + valid = hashlib.md5('%s%s%s%s' % (settings.SECRET_KEY, date, username, realm)).hexdigest() == registration_hash + if not valid: + raise Http404 + request_date = datetime.date(int(date[:4]), int(date[4:6]), int(date[6:])) + if datetime.date.today() > (request_date + datetime.timedelta(days=settings.DAYS_TO_EXPIRE_REGISTRATION_LINK)): + raise Http404 + success = False + if request.method == 'POST': + form = PasswordForm(request.POST, username=username) + if form.is_valid(): + form.save() + success = True + else: + form = PasswordForm(username=username) + return render_to_response('registration/confirm.html', + {'form': form, 'email': username, 'success': success}, + context_instance=RequestContext(request)) + + +def password_reset_view(request): + success = False + if request.method == 'POST': + form = RecoverPasswordForm(request.POST) + if form.is_valid(): + form.save() + success = True + else: + form = RecoverPasswordForm() + return render_to_response('registration/password_reset.html', + {'form': form, + 'success': success}, + context_instance=RequestContext(request)) + + +def confirm_password_reset(request, username, date, realm, reset_hash): + valid = hashlib.md5('%s%s%s%s' % (settings.SECRET_KEY, date, username, realm)).hexdigest() == reset_hash + if not valid: + raise Http404 + success = False + if request.method == 'POST': + form = PasswordForm(request.POST, update_user=True, username=username) + if form.is_valid(): + form.save() + success = True + else: + form = PasswordForm(username=username) + return render_to_response('registration/change_password.html', + {'form': form, + 'success': success, + 'username': username}, + context_instance=RequestContext(request)) + + +def ajax_check_username(request): + username = request.GET.get('username', '') + error = False + if User.objects.filter(username=username).count(): + error = 'This email is already in use' + return HttpResponse(simplejson.dumps({'error': error}), mimetype='text/plain') diff --git a/ietf/registration/__init__.py b/ietf/registration/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ietf/registration/urls.py b/ietf/registration/urls.py deleted file mode 100644 index 7eba5e2d5..000000000 --- a/ietf/registration/urls.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.conf.urls.defaults import patterns, url - - -urlpatterns = patterns('ietf.registration.views', - url(r'^$', 'register_view', name='register_view'), - url(r'^confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[\w]+)/(?P[a-f0-9]+)/$', 'confirm_register_view', name='confirm_register_view'), - url(r'^password_recovery/$', 'password_recovery_view', name='password_recovery_view'), - url(r'^password_recovery/confirm/(?P[\w.@+-]+)/(?P[\d]+)/(?P[\w]+)/(?P[a-f0-9]+)/$', 'confirm_password_recovery', name='confirm_password_recovery'), - url(r'^ajax/check_username/$', 'ajax_check_username', name='ajax_check_username'), -) diff --git a/ietf/registration/views.py b/ietf/registration/views.py deleted file mode 100644 index d0c35417b..000000000 --- a/ietf/registration/views.py +++ /dev/null @@ -1,91 +0,0 @@ -import datetime -import hashlib - -from django.conf import settings -from django.contrib.auth.models import User -from django.http import HttpResponse, Http404 -from django.shortcuts import get_object_or_404, render_to_response -from django.template import RequestContext -from django.utils import simplejson -from django.utils.translation import ugettext as _ - -from ietf.registration.forms import (RegistrationForm, PasswordForm, - RecoverPasswordForm) - - -def register_view(request): - success = False - if request.method == 'POST': - form = RegistrationForm(request.POST) - if form.is_valid(): - form.save() - success = True - else: - form = RegistrationForm() - return render_to_response('registration/register.html', - {'form': form, - 'success': success}, - context_instance=RequestContext(request)) - - -def confirm_register_view(request, username, date, realm, registration_hash): - valid = hashlib.md5('%s%s%s%s' % (settings.SECRET_KEY, date, username, realm)).hexdigest() == registration_hash - if not valid: - raise Http404 - request_date = datetime.date(int(date[:4]), int(date[4:6]), int(date[6:])) - if datetime.date.today() > (request_date + datetime.timedelta(days=settings.DAYS_TO_EXPIRE_REGISTRATION_LINK)): - raise Http404 - success = False - if request.method == 'POST': - form = PasswordForm(request.POST, username=username) - if form.is_valid(): - form.save() - success = True - else: - form = PasswordForm(username=username) - return render_to_response('registration/confirm_register.html', - {'form': form, 'email': username, 'success': success}, - context_instance=RequestContext(request)) - - -def password_recovery_view(request): - success = False - if request.method == 'POST': - form = RecoverPasswordForm(request.POST) - if form.is_valid(): - form.save() - success = True - else: - form = RecoverPasswordForm() - return render_to_response('registration/password_recovery.html', - {'form': form, - 'success': success}, - context_instance=RequestContext(request)) - - -def confirm_password_recovery(request, username, date, realm, recovery_hash): - user = get_object_or_404(User, username=username) - valid = hashlib.md5('%s%s%s%s%s' % (settings.SECRET_KEY, date, user.username, user.password, realm)).hexdigest() == recovery_hash - if not valid: - raise Http404 - success = False - if request.method == 'POST': - form = PasswordForm(request.POST, update_user=True, username=user.username) - if form.is_valid(): - user = form.save() - success = True - else: - form = PasswordForm(username=user.username) - return render_to_response('registration/change_password.html', - {'form': form, - 'success': success, - 'username': user.username}, - context_instance=RequestContext(request)) - - -def ajax_check_username(request): - username = request.GET.get('username', '') - error = False - if User.objects.filter(username=username).count(): - error = _('This email is already in use') - return HttpResponse(simplejson.dumps({'error': error}), mimetype='text/plain') diff --git a/ietf/templates/base_leftmenu.html b/ietf/templates/base_leftmenu.html index 0ea082206..012b94ac4 100644 --- a/ietf/templates/base_leftmenu.html +++ b/ietf/templates/base_leftmenu.html @@ -35,6 +35,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. {% load wg_menu %} {% load ietf_filters community_tags %}
    +
  • Accounts
  • +
  • New Account
  • {% if user|in_group:"Area_Director" %}
  • AD Dashboard
  • My Documents
  • diff --git a/ietf/templates/registration/confirm_register.html b/ietf/templates/registration/confirm.html similarity index 62% rename from ietf/templates/registration/confirm_register.html rename to ietf/templates/registration/confirm.html index e78f4ccfe..8baf0e9dc 100644 --- a/ietf/templates/registration/confirm_register.html +++ b/ietf/templates/registration/confirm.html @@ -6,16 +6,16 @@

    Confirm registration

    {% if success %} -

    Your email {{ email }} has been registered using the password you have select.

    +

    Your account with login name '{{ email }}' has been created, using the password you have select.

    Now you can sign in

    {% else %} -

    Hello, the registration for {{ email }} is almost complete. Please, select a password.

    +

    In order to complete the setup of your account with login name '{{ email }}', please, set a password:

    {{ form }}
    - +
    {% endif %} diff --git a/ietf/templates/registration/register.html b/ietf/templates/registration/create.html similarity index 70% rename from ietf/templates/registration/register.html rename to ietf/templates/registration/create.html index c37a3746f..97f1de812 100644 --- a/ietf/templates/registration/register.html +++ b/ietf/templates/registration/create.html @@ -1,6 +1,6 @@ {% extends "registration/base.html" %} -{% block title %}Register{% endblock %} +{% block title %}Account Creation{% endblock %} {% block scripts %} {{ block.super }} @@ -35,23 +35,30 @@ {% block content %}
    -

    Register

    +

    Account Creation

    {% if success %} -

    Your registration request has been received successfully. We have sent you an email with instructions on how to finish the registration process.

    -

    Thank you.

    +

    Your account creation request has been received successfully.
    + We have sent you an email with instructions on how to complete the process.

    +

    Best regards, +
    +
    +

    + The datatracker login manager service
    + (for the IETF Secretariat) +

    {% else %}
    -

    Please enter your email addres in order to register a new account.

    +

    Please enter your email addres in order to create a new account.

    {{ form }}
    - +

    -I'm already registered but I forgot my password. Please, help me recover my password. +I'm already registered but I forgot my password. Please, help me recover my password.

    {% endif %}
    diff --git a/ietf/templates/registration/register_email.txt b/ietf/templates/registration/creation_email.txt similarity index 73% rename from ietf/templates/registration/register_email.txt rename to ietf/templates/registration/creation_email.txt index 9b4663a30..3f46d197f 100644 --- a/ietf/templates/registration/register_email.txt +++ b/ietf/templates/registration/creation_email.txt @@ -2,7 +2,7 @@ Hello, In order to complete your registration on {{ domain }}, please follow this link or copy it and paste it in your web browser: -http://{{ domain }}{% url confirm_register_view to_email today realm auth %} +http://{{ domain }}{% url confirm_account username today realm auth %} This link will expire in {{ expire }} days. diff --git a/ietf/templates/registration/index.html b/ietf/templates/registration/index.html new file mode 100644 index 000000000..f3e8e6344 --- /dev/null +++ b/ietf/templates/registration/index.html @@ -0,0 +1,23 @@ +{% extends "registration/base.html" %} + +{% block title %}Account Management{% endblock %} + +{% block content %} +
    +

    Account Management

    + +

    + You can: +

    +

    + +
    +{% endblock %} diff --git a/ietf/templates/registration/password_recovery.html b/ietf/templates/registration/password_recovery.html deleted file mode 100644 index c327cad62..000000000 --- a/ietf/templates/registration/password_recovery.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "registration/base.html" %} - -{% block title %}Password recovery{% endblock %} - -{% block content %} -
    -

    Password recovery

    -{% if success %} -

    Your password recovery request has been received successfully. We have sent you an email with instructions on how to change your password.

    -

    Thank you.

    -{% else %} -
    - - {{ form }} -
    -
    - -
    -
    -{% endif %} -
    -{% endblock %} diff --git a/ietf/templates/registration/password_recovery_email.txt b/ietf/templates/registration/password_recovery_email.txt deleted file mode 100644 index 471fbacb9..000000000 --- a/ietf/templates/registration/password_recovery_email.txt +++ /dev/null @@ -1,13 +0,0 @@ -Hello, - -We have received a password recovery request at {{ domain }}. In order to change the password for the user with username {{ username }} please follow or paste and copy in your browser the follwoing link: - -http://{{ domain }}{% url confirm_password_recovery username today realm recovery_hash %} - -This link will expire in {{ expire }} days. - -If you didn't request a password recovery you can ignore this email, your credentials have been left untouched. - -Best, - -Your {{ domain }} team. diff --git a/ietf/templates/registration/password_reset.html b/ietf/templates/registration/password_reset.html new file mode 100644 index 000000000..bd86f1652 --- /dev/null +++ b/ietf/templates/registration/password_reset.html @@ -0,0 +1,30 @@ +{% extends "registration/base.html" %} + +{% block title %}Password Reset Request{% endblock %} + +{% block content %} +
    +

    Password Reset Request

    +{% if success %} +

    Your password reset request has been received successfully.
    + We have sent you an email with instructions on how to set a new password.

    +

    Best regards, +
    +
    +

    + The datatracker login manager service
    + (for the IETF Secretariat) +
    +

    +{% else %} +
    + + {{ form }} +
    +
    + +
    +
    +{% endif %} +
    +{% endblock %} diff --git a/ietf/templates/registration/password_reset_email.txt b/ietf/templates/registration/password_reset_email.txt new file mode 100644 index 000000000..5ba3a8c71 --- /dev/null +++ b/ietf/templates/registration/password_reset_email.txt @@ -0,0 +1,20 @@ +{% autoescape off %} +Hello, + +We have received a password reset request for {{ username }} +at {{ domain }}. In order to change the password for the +{{ username }} account, please go to the following link and +follow the instructions there: + + http://{{ domain }}{% url confirm_password_reset username today realm auth %} + +This link will expire in {{ expire }} days. + +If you have not request a password reset you can ignore this email, your +credentials have been left untouched. + +Best regards, + + The datatracker login manager service + (for the IETF Secretariat) +{% endautoescape %} diff --git a/ietf/urls.py b/ietf/urls.py index af0a56f71..d3aa516e6 100644 --- a/ietf/urls.py +++ b/ietf/urls.py @@ -58,7 +58,6 @@ urlpatterns = patterns('', (r'^accounts/', include('ietf.ietfauth.urls')), (r'^doc/', include('ietf.idrfc.urls')), (r'^wg/', include('ietf.wginfo.urls')), - (r'^registration/', include('ietf.registration.urls')), (r'^community/', include('ietf.community.urls')), (r'^$', 'ietf.idrfc.views.main'),