@ -21,7 +21,6 @@ from synapse.api.errors import (
AuthError , Codes , SynapseError , RegistrationError , InvalidCaptchaError
AuthError , Codes , SynapseError , RegistrationError , InvalidCaptchaError
)
)
from . _base import BaseHandler
from . _base import BaseHandler
import synapse . util . stringutils as stringutils
from synapse . util . async import run_on_reactor
from synapse . util . async import run_on_reactor
from synapse . http . client import CaptchaServerHttpClient
from synapse . http . client import CaptchaServerHttpClient
@ -45,6 +44,8 @@ class RegistrationHandler(BaseHandler):
self . distributor . declare ( " registered_user " )
self . distributor . declare ( " registered_user " )
self . captcha_client = CaptchaServerHttpClient ( hs )
self . captcha_client = CaptchaServerHttpClient ( hs )
self . _next_generated_user_id = None
@defer . inlineCallbacks
@defer . inlineCallbacks
def check_username ( self , localpart , guest_access_token = None ) :
def check_username ( self , localpart , guest_access_token = None ) :
yield run_on_reactor ( )
yield run_on_reactor ( )
@ -91,7 +92,7 @@ class RegistrationHandler(BaseHandler):
Args :
Args :
localpart : The local part of the user ID to register . If None ,
localpart : The local part of the user ID to register . If None ,
one will be randomly generated .
one will be generated .
password ( str ) : The password to assign to this user so they can
password ( str ) : The password to assign to this user so they can
login again . This can be None which means they cannot login again
login again . This can be None which means they cannot login again
via a password ( e . g . the user is an application service user ) .
via a password ( e . g . the user is an application service user ) .
@ -108,6 +109,18 @@ class RegistrationHandler(BaseHandler):
if localpart :
if localpart :
yield self . check_username ( localpart , guest_access_token = guest_access_token )
yield self . check_username ( localpart , guest_access_token = guest_access_token )
was_guest = guest_access_token is not None
if not was_guest :
try :
int ( localpart )
raise RegistrationError (
400 ,
" Numeric user IDs are reserved for guest users. "
)
except ValueError :
pass
user = UserID ( localpart , self . hs . hostname )
user = UserID ( localpart , self . hs . hostname )
user_id = user . to_string ( )
user_id = user . to_string ( )
@ -118,40 +131,36 @@ class RegistrationHandler(BaseHandler):
user_id = user_id ,
user_id = user_id ,
token = token ,
token = token ,
password_hash = password_hash ,
password_hash = password_hash ,
was_guest = guest_access_token is not None ,
was_guest = was_guest ,
make_guest = make_guest ,
make_guest = make_guest ,
)
)
yield registered_user ( self . distributor , user )
yield registered_user ( self . distributor , user )
else :
else :
# autogen a random user ID
# autogen a sequential user ID
attempts = 0
attempts = 0
user_id = None
token = None
token = None
while not user_id :
user = None
while not user :
localpart = yield self . _generate_user_id ( attempts > 0 )
user = UserID ( localpart , self . hs . hostname )
user_id = user . to_string ( )
yield self . check_user_id_is_valid ( user_id )
if generate_token :
token = self . auth_handler ( ) . generate_access_token ( user_id )
try :
try :
localpart = self . _generate_user_id ( )
user = UserID ( localpart , self . hs . hostname )
user_id = user . to_string ( )
yield self . check_user_id_is_valid ( user_id )
if generate_token :
token = self . auth_handler ( ) . generate_access_token ( user_id )
yield self . store . register (
yield self . store . register (
user_id = user_id ,
user_id = user_id ,
token = token ,
token = token ,
password_hash = password_hash ,
password_hash = password_hash ,
make_guest = make_guest
make_guest = make_guest
)
)
yield registered_user ( self . distributor , user )
except SynapseError :
except SynapseError :
# if user id is taken, just generate another
# if user id is taken, just generate another
user_id = None
user_id = None
token = None
token = None
attempts + = 1
attempts + = 1
if attempts > 5 :
yield registered_user ( self . distributor , user )
raise RegistrationError (
500 , " Cannot generate user ID. " )
# We used to generate default identicons here, but nowadays
# We used to generate default identicons here, but nowadays
# we want clients to generate their own as part of their branding
# we want clients to generate their own as part of their branding
@ -283,8 +292,16 @@ class RegistrationHandler(BaseHandler):
errcode = Codes . EXCLUSIVE
errcode = Codes . EXCLUSIVE
)
)
def _generate_user_id ( self ) :
@defer . inlineCallbacks
return " - " + stringutils . random_string ( 18 )
def _generate_user_id ( self , reseed = False ) :
if reseed or self . _next_generated_user_id is None :
self . _next_generated_user_id = (
yield self . store . find_next_generated_user_id_localpart ( )
)
id = self . _next_generated_user_id
self . _next_generated_user_id + = 1
defer . returnValue ( str ( id ) )
@defer . inlineCallbacks
@defer . inlineCallbacks
def _validate_captcha ( self , ip_addr , private_key , challenge , response ) :
def _validate_captcha ( self , ip_addr , private_key , challenge , response ) :