parent
0e829f975d
commit
05929b2272
0
ietf/registration/__init__.py
Normal file
0
ietf/registration/__init__.py
Normal file
114
ietf/registration/forms.py
Normal file
114
ietf/registration/forms.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import datetime
|
||||
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 _
|
||||
|
||||
from ietf.utils.mail import send_mail
|
||||
from redesign.person.models import Person, Email
|
||||
|
||||
|
||||
class RegistrationForm(forms.Form):
|
||||
|
||||
email = forms.EmailField(label="Your email")
|
||||
realm = 'IETF'
|
||||
expire = 3
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.send_email()
|
||||
return True
|
||||
|
||||
def send_email(self):
|
||||
domain = Site.objects.get_current().domain
|
||||
subject = ugettext(u'Confirm registration at %s') % domain
|
||||
from_email = settings.DEFAULT_FROM_EMAIL
|
||||
to_email = self.cleaned_data['email']
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
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,
|
||||
'to_email': to_email,
|
||||
'expire': settings.DAYS_TO_EXPIRE_REGISTRATION_LINK,
|
||||
}
|
||||
send_mail(None, to_email, from_email, subject, 'registration/register_email.txt', context)
|
||||
|
||||
def clean_email(self):
|
||||
email = self.cleaned_data.get('email', '')
|
||||
if not email:
|
||||
return email
|
||||
if User.objects.filter(username=email).count():
|
||||
raise forms.ValidationError(_('Email already in use'))
|
||||
return email
|
||||
|
||||
|
||||
class RecoverPasswordForm(PasswordResetForm):
|
||||
|
||||
realm = 'IETF'
|
||||
|
||||
def save(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)
|
||||
|
||||
|
||||
class PasswordForm(forms.Form):
|
||||
|
||||
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
|
||||
password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput,
|
||||
help_text=_("Enter the same password as above, for verification."))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.username = kwargs.pop('username')
|
||||
self.update_user = kwargs.pop('update_user', False)
|
||||
super(PasswordForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean_password2(self):
|
||||
password1 = self.cleaned_data.get("password1", "")
|
||||
password2 = self.cleaned_data["password2"]
|
||||
if password1 != password2:
|
||||
raise forms.ValidationError(_("The two password fields didn't match."))
|
||||
return password2
|
||||
|
||||
def get_password(self):
|
||||
return self.cleaned_data.get('password1')
|
||||
|
||||
def create_user(self):
|
||||
user = User.objects.create(username=self.username,
|
||||
email=self.username)
|
||||
person = Person.objects.create(user=user,
|
||||
name=self.username,
|
||||
ascii=self.username)
|
||||
Email.objects.create(person=person,
|
||||
address=self.username)
|
||||
return user
|
||||
|
||||
def get_user(self):
|
||||
return User.objects.get(username=self.username)
|
||||
|
||||
def save(self):
|
||||
if self.update_user:
|
||||
user = self.get_user()
|
||||
else:
|
||||
user = self.create_user()
|
||||
user.set_password(self.get_password())
|
||||
user.save()
|
||||
return user
|
10
ietf/registration/urls.py
Normal file
10
ietf/registration/urls.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
|
||||
urlpatterns = patterns('ietf.registration.views',
|
||||
url(r'^$', 'register_view', name='register_view'),
|
||||
url(r'^confirm/(?P<username>[\w.@+-]+)/(?P<date>[\d]+)/(?P<realm>[\w]+)/(?P<registration_hash>[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<username>[\w.@+-]+)/(?P<date>[\d]+)/(?P<realm>[\w]+)/(?P<recovery_hash>[a-f0-9]+)/$', 'confirm_password_recovery', name='confirm_password_recovery'),
|
||||
url(r'^ajax/check_username/$', 'ajax_check_username', name='ajax_check_username'),
|
||||
)
|
93
ietf/registration/views.py
Normal file
93
ietf/registration/views.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
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()
|
||||
# TODO: Add the user in the htdigest file
|
||||
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()
|
||||
# TODO: Update the user in the htdigest file
|
||||
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')
|
|
@ -195,6 +195,10 @@ LIAISON_UNIVERSAL_FROM = 'Liaison Statement Management Tool <lsmt@' + IETF_DOMAI
|
|||
LIAISON_ATTACH_PATH = '/a/www/ietf-datatracker/documents/LIAISON/'
|
||||
LIAISON_ATTACH_URL = '/documents/LIAISON/'
|
||||
|
||||
# Registration configuration
|
||||
DAYS_TO_EXPIRE_REGISTRATION_LINK = 3
|
||||
DAYS_TO_EXPIRE_RECOVER_LINK = 3
|
||||
|
||||
# DB redesign
|
||||
USE_DB_REDESIGN_PROXY_CLASSES = True
|
||||
|
||||
|
|
6
ietf/templates/registration/base.html
Normal file
6
ietf/templates/registration/base.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block morecss %}
|
||||
table.register-form ul.errorlist{ list-style-type: none; color: red; padding: 0px; margin: 0px; }
|
||||
table.register-form p { margin-top: 0px; }
|
||||
{% endblock %}
|
23
ietf/templates/registration/change_password.html
Normal file
23
ietf/templates/registration/change_password.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "registration/base.html" %}
|
||||
|
||||
{% block title %}Change password{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="change_password_page">
|
||||
<h1>Change password</h1>
|
||||
{% if success %}
|
||||
<p>Your password has been updated.</p>
|
||||
<p>Now you can <a href="{% url ietfauth.views.ietf_login %}">sign in</a></p>
|
||||
{% else %}
|
||||
<p>Hello, you can select a new password below for your user {{ username }}.</p>
|
||||
<form action="" method="POST">
|
||||
<table class="register-form">
|
||||
{{ form }}
|
||||
</table>
|
||||
<div class="submit_row">
|
||||
<input type="submit" value="Change password" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
23
ietf/templates/registration/confirm_register.html
Normal file
23
ietf/templates/registration/confirm_register.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "registration/base.html" %}
|
||||
|
||||
{% block title %}Confirm registration{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="confirm_register_page">
|
||||
<h1>Confirm registration</h1>
|
||||
{% if success %}
|
||||
<p>Your email {{ email }} has been registered using the password you have select.</p>
|
||||
<p>Now you can <a href="{% url ietfauth.views.ietf_login %}">sign in</a></p>
|
||||
{% else %}
|
||||
<p>Hello, the registration for {{ email }} is almost complete. Please, select a password.</p>
|
||||
<form action="" method="POST">
|
||||
<table class="register-form">
|
||||
{{ form }}
|
||||
</table>
|
||||
<div class="submit_row">
|
||||
<input type="submit" value="Register" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
22
ietf/templates/registration/password_recovery.html
Normal file
22
ietf/templates/registration/password_recovery.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "registration/base.html" %}
|
||||
|
||||
{% block title %}Password recovery{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="register_page">
|
||||
<h1>Password recovery</h1>
|
||||
{% if success %}
|
||||
<p>Your password recovery request has been received successfully. We have sent you an email with instructions on how to change your password.</p>
|
||||
<p>Thank you.</p>
|
||||
{% else %}
|
||||
<form action="" method="POST">
|
||||
<table class="register-form">
|
||||
{{ form }}
|
||||
</table>
|
||||
<div class="submit_row">
|
||||
<input type="submit" value="Recover my password" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
13
ietf/templates/registration/password_recovery_email.txt
Normal file
13
ietf/templates/registration/password_recovery_email.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
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.
|
58
ietf/templates/registration/register.html
Normal file
58
ietf/templates/registration/register.html
Normal file
|
@ -0,0 +1,58 @@
|
|||
{% extends "registration/base.html" %}
|
||||
|
||||
{% block title %}Register{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ block.super }}
|
||||
|
||||
(function($) {
|
||||
var checkUsername = function() {
|
||||
var field = $(this);
|
||||
var url = $("#check_user_name_url").val();
|
||||
var error = field.next('.username-error');
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: {username: field.val()},
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
if (response.error) {
|
||||
error.text(response.error);
|
||||
error.show();
|
||||
} else {
|
||||
error.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#id_email').after(' <span class="username-error" style="display: none;"></span>');
|
||||
$('#id_email').keyup(checkUsername).blur(checkUsername);
|
||||
});
|
||||
})(jQuery);
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="register_page">
|
||||
<h1>Register</h1>
|
||||
{% if success %}
|
||||
<p>Your registration request has been received successfully. We have sent you an email with instructions on how to finish the registration process.</p>
|
||||
<p>Thank you.</p>
|
||||
{% else %}
|
||||
<form action="" method="POST">
|
||||
<p>Please enter your email addres in order to register a new account.</p>
|
||||
<table class="register-form">
|
||||
{{ form }}
|
||||
</table>
|
||||
<div class="submit_row">
|
||||
<input type="hidden" id="check_user_name_url" value="{% url ajax_check_username %}" />
|
||||
<input type="submit" value="Register" />
|
||||
</div>
|
||||
</form>
|
||||
<p class="recover_password_description">
|
||||
I'm already registered but I forgot my password. <a href="{% url password_recovery_view %}">Please, help me recover my password.</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
11
ietf/templates/registration/register_email.txt
Normal file
11
ietf/templates/registration/register_email.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
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 %}
|
||||
|
||||
This link will expire in {{ expire }} days.
|
||||
|
||||
Best,
|
||||
|
||||
Your {{ domain }} team.
|
|
@ -58,6 +58,7 @@ 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'^$', 'ietf.idrfc.views.main'),
|
||||
('^admin/', include(admin.site.urls)),
|
||||
|
|
Loading…
Reference in a new issue