Skip to content

Commit fed2a04

Browse files
committed
Increased the requirements for account creation, and added a form where the secretariat can add whitelisting to make account creation possible for addresses that don't fulfil the default requirements.
- Legacy-Id: 11374
1 parent b0ddd0d commit fed2a04

6 files changed

Lines changed: 219 additions & 17 deletions

File tree

ietf/ietfauth/forms.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import debug # pyflakes:ignore
1313

1414
from ietf.person.models import Person, Email
15+
from ietf.mailinglists.models import Whitelisted
1516

1617

1718
class RegistrationForm(forms.Form):
@@ -118,3 +119,9 @@ def clean_username(self):
118119
class TestEmailForm(forms.Form):
119120
email = forms.EmailField(required=False)
120121

122+
class WhitelistForm(ModelForm):
123+
class Meta:
124+
model = Whitelisted
125+
exclude = ['by', 'time' ]
126+
127+

ietf/ietfauth/tests.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# -*- coding: utf-8 -*-
2-
import os, shutil
2+
from __future__ import unicode_literals
3+
4+
import os, shutil, time
35
from urlparse import urlsplit
46
from pyquery import PyQuery
57
from unittest import skipIf
@@ -15,6 +17,8 @@
1517
from ietf.person.models import Person, Email
1618
from ietf.group.models import Group, Role, RoleName
1719
from ietf.ietfauth.htpasswd import update_htpasswd_file
20+
from ietf.mailinglists.models import Subscribed
21+
1822
import ietf.ietfauth.views
1923

2024
if os.path.exists(settings.HTPASSWD_COMMAND):
@@ -94,7 +98,7 @@ def username_in_htpasswd_file(self, username):
9498

9599
return False
96100

97-
def test_create_account(self):
101+
def test_create_account_failure(self):
98102
make_test_data()
99103

100104
url = urlreverse(ietf.ietfauth.views.create_account)
@@ -103,12 +107,21 @@ def test_create_account(self):
103107
r = self.client.get(url)
104108
self.assertEqual(r.status_code, 200)
105109

106-
# register email
110+
# register email and verify failure
107111
email = 'new-account@example.com'
108112
empty_outbox()
109113
r = self.client.post(url, { 'email': email })
110114
self.assertEqual(r.status_code, 200)
111-
self.assertTrue("Account created" in unicontent(r))
115+
self.assertIn("Account creation failed", unicontent(r))
116+
117+
def register_and_verify(self, email):
118+
url = urlreverse(ietf.ietfauth.views.create_account)
119+
120+
# register email
121+
empty_outbox()
122+
r = self.client.post(url, { 'email': email })
123+
self.assertEqual(r.status_code, 200)
124+
self.assertIn("Account created", unicontent(r))
112125
self.assertEqual(len(outbox), 1)
113126

114127
# go to confirm page
@@ -130,6 +143,41 @@ def test_create_account(self):
130143

131144
self.assertTrue(self.username_in_htpasswd_file(email))
132145

146+
def test_create_whitelisted_account(self):
147+
email = "new-account@example.com"
148+
149+
# add whitelist entry
150+
r = self.client.post(urlreverse(django.contrib.auth.views.login), {"username":"secretary", "password":"secretary+password"})
151+
self.assertEqual(r.status_code, 302)
152+
self.assertEqual(urlsplit(r["Location"])[2], urlreverse(ietf.ietfauth.views.profile))
153+
154+
r = self.client.get(urlreverse(ietf.ietfauth.views.add_account_whitelist))
155+
self.assertEqual(r.status_code, 200)
156+
self.assertIn("Add a whitelist entry", unicontent(r))
157+
158+
r = self.client.post(urlreverse(ietf.ietfauth.views.add_account_whitelist), {"address": email})
159+
self.assertEqual(r.status_code, 200)
160+
self.assertIn("Whitelist entry creation successful", unicontent(r))
161+
162+
# log out
163+
r = self.client.get(urlreverse(django.contrib.auth.views.logout))
164+
self.assertEqual(r.status_code, 200)
165+
166+
# register and verify whitelisted email
167+
self.register_and_verify(email)
168+
169+
170+
def test_create_subscribed_account(self):
171+
# verify creation with email in subscribed list
172+
saved_delay = settings.LIST_ACCOUNT_DELAY
173+
settings.LIST_ACCOUNT_DELAY = 1
174+
email = "subscribed@example.com"
175+
s = Subscribed(address=email)
176+
s.save()
177+
time.sleep(1.1)
178+
self.register_and_verify(email)
179+
settings.LIST_ACCOUNT_DELAY = saved_delay
180+
133181
def test_profile(self):
134182
make_test_data()
135183

ietf/ietfauth/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from django.conf.urls import patterns, url
44
from django.contrib.auth.views import login, logout
55

6+
from ietf.ietfauth.views import add_account_whitelist
7+
68
urlpatterns = patterns('ietf.ietfauth.views',
79
url(r'^$', 'index'),
810
# url(r'^login/$', 'ietf_login'),
@@ -18,4 +20,5 @@
1820
url(r'^reset/$', 'password_reset'),
1921
url(r'^reset/confirm/(?P<auth>[^/]+)/$', 'confirm_password_reset'),
2022
url(r'^confirmnewemail/(?P<auth>[^/]+)/$', 'confirm_new_email'),
23+
(r'whitelist/add/?$', add_account_whitelist),
2124
)

ietf/ietfauth/views.py

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
# Copyright The IETF Trust 2007, All Rights Reserved
3434

35+
from datetime import datetime as DateTime, timedelta as TimeDelta
36+
3537
from django.conf import settings
3638
from django.http import Http404 #, HttpResponse, HttpResponseRedirect
3739
from django.shortcuts import render, redirect, get_object_or_404
@@ -42,10 +44,14 @@
4244
from django.contrib.sites.models import Site
4345
from django.contrib.auth.models import User
4446

47+
import debug # pyflakes:ignore
48+
4549
from ietf.group.models import Role
46-
from ietf.ietfauth.forms import RegistrationForm, PasswordForm, ResetPasswordForm, TestEmailForm
50+
from ietf.ietfauth.forms import RegistrationForm, PasswordForm, ResetPasswordForm, TestEmailForm, WhitelistForm
4751
from ietf.ietfauth.forms import get_person_form, RoleEmailForm, NewEmailForm
4852
from ietf.ietfauth.htpasswd import update_htpasswd_file
53+
from ietf.ietfauth.utils import role_required
54+
from ietf.mailinglists.models import Subscribed, Whitelisted
4955
from ietf.person.models import Person, Email, Alias
5056
from ietf.utils.mail import send_mail
5157

@@ -85,20 +91,25 @@ def create_account(request):
8591
if request.method == 'POST':
8692
form = RegistrationForm(request.POST)
8793
if form.is_valid():
88-
to_email = form.cleaned_data['email']
94+
to_email = form.cleaned_data['email'] # This will be lowercase if form.is_valid()
95+
existing = Subscribed.objects.filter(address=to_email).first()
96+
ok_to_create = ( Whitelisted.objects.filter(address=to_email).exists()
97+
or existing and (existing.time + TimeDelta(seconds=settings.LIST_ACCOUNT_DELAY)) < DateTime.now() )
98+
if ok_to_create:
99+
auth = django.core.signing.dumps(to_email, salt="create_account")
89100

90-
auth = django.core.signing.dumps(to_email, salt="create_account")
91-
92-
domain = Site.objects.get_current().domain
93-
subject = 'Confirm registration at %s' % domain
94-
from_email = settings.DEFAULT_FROM_EMAIL
101+
domain = Site.objects.get_current().domain
102+
subject = 'Confirm registration at %s' % domain
103+
from_email = settings.DEFAULT_FROM_EMAIL
95104

96-
send_mail(request, to_email, from_email, subject, 'registration/creation_email.txt', {
97-
'domain': domain,
98-
'auth': auth,
99-
'username': to_email,
100-
'expire': settings.DAYS_TO_EXPIRE_REGISTRATION_LINK,
101-
})
105+
send_mail(request, to_email, from_email, subject, 'registration/creation_email.txt', {
106+
'domain': domain,
107+
'auth': auth,
108+
'username': to_email,
109+
'expire': settings.DAYS_TO_EXPIRE_REGISTRATION_LINK,
110+
})
111+
else:
112+
return render(request, 'registration/manual.html', { 'account_request_email': settings.ACCOUNT_REQUEST_EMAIL })
102113
else:
103114
form = RegistrationForm()
104115

@@ -359,3 +370,22 @@ def test_email(request):
359370
r.set_cookie("testmailcc", cookie)
360371

361372
return r
373+
374+
@role_required('Secretariat')
375+
def add_account_whitelist(request):
376+
success = False
377+
if request.method == 'POST':
378+
form = WhitelistForm(request.POST)
379+
if form.is_valid():
380+
address = form.cleaned_data['address']
381+
entry = Whitelisted(address=address, by=request.user.person)
382+
entry.save()
383+
success = True
384+
else:
385+
form = WhitelistForm()
386+
387+
return render(request, 'ietfauth/whitelist_form.html', {
388+
'form': form,
389+
'success': success,
390+
})
391+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{% extends "base.html" %}
2+
{# Copyright The IETF Trust 2016, All Rights Reserved #}
3+
{% load origin %}
4+
5+
{% load bootstrap3 %}
6+
7+
{% block title %}Set up test email address{% endblock %}
8+
9+
{% block content %}
10+
{% origin %}
11+
{% if success %}
12+
<h1>Whitelist entry creation successful</h1>
13+
14+
<p>
15+
16+
Please ask the requestor to try the
17+
<a href="{% url 'ietf.ietfauth.views.create_account'%}">account creation form</a>
18+
again, with the whitelisted email address.
19+
20+
</p>
21+
22+
{% else %}
23+
<h1>Add a whitelist entry for account creation.</h1>
24+
25+
<p>
26+
When an email request comes in for assistance with account creation
27+
because the automated account creation has failed, you can add the
28+
address to an account creation whitelist here.
29+
</p>
30+
<p>
31+
Before you do so, please complete the following 3 verification steps:
32+
<ol>
33+
<li>
34+
35+
Has the person provided relevant information in his request, or has he simply
36+
copied the text from the account creation failure message? All genuine (non-spam)
37+
account creation requests seen between 2009 and 2016 for tools.ietf.org has
38+
contained a reasonable request message, rather than just copy-pasting the account
39+
creation failure message. If there's no proper request message, step 2 below can
40+
be performed to make sure the request is bogus, but if that also fails, no further
41+
effort should be needed.
42+
43+
</li>
44+
<li>
45+
46+
Google for the person's name within the ietf site: "Jane Doe site:ietf.org". If
47+
found, and the email address matches an address used in drafts or discussions,
48+
things are fine, and it's OK to add the address to the whitelist using this form,
49+
and ask the person to please try the <a href="{% url
50+
'ietf.ietfauth.views.create_account' %}">account creation form</a> again.
51+
52+
</li>
53+
<li>
54+
55+
<p>
56+
57+
If google finds no trace of the person being an ietf participant, he or she could
58+
still be somebody who is just getting involved in IETF work. A datatracker account
59+
is probably not necessary, but in case this is a legitimate request, please email
60+
the person and ask:
61+
62+
</p>
63+
<blockquote>
64+
"Which wgs do you require a password for?"
65+
</blockquote>
66+
67+
<p>
68+
69+
This is a bit of a trick question, because it is very unlikely that somebody who
70+
isn't involved in IETF work will give a reasonable response, while almost any answer
71+
from somebody who is doing IETF work will show that they have some clue.
72+
73+
</p>
74+
<p>
75+
76+
If the answer to this question shows clue, then add the address to the whitelist
77+
using this form, and ask the person to please try the <a href="{% url
78+
'ietf.ietfauth.views.create_account' %}"> account creation form</a> again.
79+
80+
</p>
81+
</li>
82+
</ol>
83+
</p>
84+
<form role-"form" method="post">
85+
{% csrf_token %}
86+
{% bootstrap_form form %}
87+
88+
{% buttons %}
89+
<button class="btn btn-primary" type="submit">Add address to account creation whitelist</button>
90+
{% endbuttons %}
91+
</form>
92+
{% endif %}
93+
{% endblock %}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% extends "base.html" %}
2+
{# Copyright The IETF Trust 2015, All Rights Reserved #}
3+
{% load origin %}
4+
5+
{% load bootstrap3 %}
6+
7+
{% block title %}Complete account creation{% endblock %}
8+
9+
{% block content %}
10+
{% origin %}
11+
12+
<h1>Account creation failed</h1>
13+
14+
<p>
15+
Manual intervention is needed to enable account creation for you.
16+
Please send an email to {{ account_request_email }}
17+
and explain 1) the situation and 2) your need for an account,
18+
in order to receive further assistance.
19+
</p>
20+
21+
{% endblock %}

0 commit comments

Comments
 (0)