Anonymous committed e2727de

Fixed a possible incoherence when two or more users attempt a registration with the same username, reduced expiration time

Comments (0)

Files changed (3)


 # -*- coding: utf-8 -*-
 """Main Controller"""
+from _sqlite3 import IntegrityError
 from tg import TGController
 from tg import expose, flash, require, url, lurl, request, redirect, validate, config, predicates
         hooks = config['hooks'].get('registration.before_activation', [])
         for func in hooks:
             func(reg, u)
-        DBSession.add(u)
+        try:
+            DBSession.add(u)
+        except IntegrityError:
+            flash(_('Registration not found or already activated'))
+            return redirect(self.mount_point)
         reg.user = u
         reg.password = '******'


         super(UniqueUserValidator, self).validate_python(value, state)
         if re.match("^[a-zA-Z0-9_-]*[a-zA-Z_-][a-zA-Z0-9_-]*$", value):
             user = DBSession.query(app_model.User).filter_by(user_name=value).first()
+            if not user:
+                user = DBSession.query(Registration).filter_by(user_name=value).first()
  1. Alessandro Molina

    Should probably check that in you already performed a change that removed exactly that line to fix an issue with registration collisions.

    What's the expected behavior? It is probably correct that it doesn't checked collisions for Registrations to prevent users from blocking other from registering. The first that activates the registration link should win and "activate" should be in charge of making sure there are not collisions (through a forced flush and check for IntegrityError as stated on the previous comment).

             if user:
                 raise Invalid(_('Username already in use.'), value, state)
         super(UniqueEmailValidator, self).validate_python(value, state)
         if re.match("^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$", value):
             user = DBSession.query(app_model.User).filter_by(email_address=value).first()
+            if not user:
+                user = DBSession.query(Registration).filter_by(email_address=value).first()
             if user:
                 raise Invalid(_('Email address has already been taken'), value, state)


     def clear_expired(cls):
         expired = DBSession.query(cls).filter_by(activated=None)\
-                                      .filter(Registration.time<
+                                      .filter(Registration.time<
     def get_inactive(cls, code):