@@ -112,33 +112,51 @@ def index(request):
112112# redirect_to = settings.LOGIN_REDIRECT_URL
113113# return HttpResponseRedirect(redirect_to)
114114
115+
115116def create_account (request ):
116- to_email = None
117+ new_account_email = None
117118
118- if request .method == ' POST' :
119+ if request .method == " POST" :
119120 form = RegistrationForm (request .POST )
120121 if form .is_valid ():
121- to_email = form .cleaned_data ['email' ] # This will be lowercase if form.is_valid()
122-
123- # For the IETF 113 Registration period (at least) we are lowering the barriers for account creation
124- # to the simple email round-trip check
125- send_account_creation_email (request , to_email )
126-
127- # The following is what to revert to should that lowered barrier prove problematic
128- # existing = Subscribed.objects.filter(email__iexact=to_email).first()
129- # ok_to_create = ( Allowlisted.objects.filter(email__iexact=to_email).exists()
130- # or existing and (existing.time + TimeDelta(seconds=settings.LIST_ACCOUNT_DELAY)) < DateTime.now() )
131- # if ok_to_create:
132- # send_account_creation_email(request, to_email)
133- # else:
134- # return render(request, 'registration/manual.html', { 'account_request_email': settings.ACCOUNT_REQUEST_EMAIL })
122+ new_account_email = form .cleaned_data [
123+ "email"
124+ ] # This will be lowercase if form.is_valid()
125+
126+ user = User .objects .filter (username__iexact = new_account_email )
127+ email = Email .objects .filter (address__iexact = new_account_email )
128+ if user .exists () or email .exists ():
129+ person_to_contact = user .first ().person if user else email .first ().person
130+ to_email = person_to_contact .email_address ()
131+ if to_email :
132+ send_account_creation_exists_email (request , new_account_email , to_email )
133+ else :
134+ raise ValidationError (f"Account for {{new_account_email}} exists, but cannot email it" )
135+ else :
136+ # For the IETF 113 Registration period (at least) we are lowering the
137+ # barriers for account creation to the simple email round-trip check
138+ send_account_creation_email (request , new_account_email )
139+
140+ # The following is what to revert to should that lowered barrier prove problematic
141+ # existing = Subscribed.objects.filter(email__iexact=new_account_email).first()
142+ # ok_to_create = ( Allowlisted.objects.filter(email__iexact=new_account_email).exists()
143+ # or existing and (existing.time + TimeDelta(seconds=settings.LIST_ACCOUNT_DELAY)) < DateTime.now() )
144+ # if ok_to_create:
145+ # send_account_creation_email(request, new_account_email)
146+ # else:
147+ # return render(request, 'registration/manual.html', { 'account_request_email': settings.ACCOUNT_REQUEST_EMAIL })
135148 else :
136149 form = RegistrationForm ()
137150
138- return render (request , 'registration/create.html' , {
139- 'form' : form ,
140- 'to_email' : to_email ,
141- })
151+ return render (
152+ request ,
153+ "registration/create.html" ,
154+ {
155+ "form" : form ,
156+ "to_email" : new_account_email ,
157+ },
158+ )
159+
142160
143161def send_account_creation_email (request , to_email ):
144162 auth = django .core .signing .dumps (to_email , salt = "create_account" )
@@ -153,6 +171,23 @@ def send_account_creation_email(request, to_email):
153171 })
154172
155173
174+ def send_account_creation_exists_email (request , new_account_email , to_email ):
175+ domain = Site .objects .get_current ().domain
176+ subject = "Attempted account creation at %s" % domain
177+ from_email = settings .DEFAULT_FROM_EMAIL
178+ send_mail (
179+ request ,
180+ to_email ,
181+ from_email ,
182+ subject ,
183+ "registration/creation_exists_email.txt" ,
184+ {
185+ "domain" : domain ,
186+ "username" : new_account_email ,
187+ },
188+ )
189+
190+
156191def confirm_account (request , auth ):
157192 try :
158193 email = django .core .signing .loads (auth , salt = "create_account" , max_age = settings .DAYS_TO_EXPIRE_REGISTRATION_LINK * 24 * 60 * 60 )
@@ -255,17 +290,25 @@ def profile(request):
255290 auth = django .core .signing .dumps ([person .user .username , to_email ], salt = "add_email" )
256291
257292 domain = Site .objects .get_current ().domain
258- subject = 'Confirm email address for %s' % person .name
259293 from_email = settings .DEFAULT_FROM_EMAIL
260294
261- send_mail (request , to_email , from_email , subject , 'registration/add_email_email.txt' , {
262- 'domain' : domain ,
263- 'auth' : auth ,
264- 'email' : to_email ,
265- 'person' : person ,
266- 'expire' : settings .DAYS_TO_EXPIRE_REGISTRATION_LINK ,
267- })
268-
295+ existing = Email .objects .filter (address = to_email ).first ()
296+ if existing :
297+ subject = 'Attempt to add your email address by %s' % person .name
298+ send_mail (request , to_email , from_email , subject , 'registration/add_email_exists_email.txt' , {
299+ 'domain' : domain ,
300+ 'email' : to_email ,
301+ 'person' : person ,
302+ })
303+ else :
304+ subject = 'Confirm email address for %s' % person .name
305+ send_mail (request , to_email , from_email , subject , 'registration/add_email_email.txt' , {
306+ 'domain' : domain ,
307+ 'auth' : auth ,
308+ 'email' : to_email ,
309+ 'person' : person ,
310+ 'expire' : settings .DAYS_TO_EXPIRE_REGISTRATION_LINK ,
311+ })
269312
270313 for r in roles :
271314 e = r .email_form .cleaned_data ["email" ]
@@ -417,14 +460,10 @@ def password_reset(request):
417460 # The form validation checks that a matching User exists. Add the person__isnull check
418461 # because the OneToOne field does not gracefully handle checks for user.person is Null.
419462 # If we don't get a User here, we know it's because there's no related Person.
463+ # We still report that the action succeeded, so we're not leaking the existence of user
464+ # email addresses.
420465 user = User .objects .filter (username__iexact = submitted_username , person__isnull = False ).first ()
421- if not (user and user .person .email_set .filter (active = True ).exists ()):
422- form .add_error (
423- 'username' ,
424- 'No known active email addresses are associated with this account. '
425- 'Please contact the secretariat for assistance.' ,
426- )
427- else :
466+ if user and user .person .email_set .filter (active = True ).exists ():
428467 data = {
429468 'username' : user .username ,
430469 'password' : user .password and user .password [- 4 :],
@@ -445,7 +484,7 @@ def password_reset(request):
445484 'username' : submitted_username ,
446485 'expire' : settings .MINUTES_TO_EXPIRE_RESET_PASSWORD_LINK ,
447486 })
448- success = True
487+ success = True
449488 else :
450489 form = ResetPasswordForm ()
451490 return render (request , 'registration/password_reset.html' , {
0 commit comments