@ -17,7 +17,7 @@
from twisted . internet import defer
from synapse . types import UserID
from synapse . api . errors import SynapseError , RegistrationError
from synapse . api . errors import SynapseError , RegistrationError , InvalidCaptchaError
from . _base import BaseHandler
import synapse . util . stringutils as stringutils
from synapse . http . client import PlainHttpClient
@ -38,7 +38,7 @@ class RegistrationHandler(BaseHandler):
self . distributor . declare ( " registered_user " )
@defer . inlineCallbacks
def register ( self , localpart = None , password = None , threepidCreds = None ) :
def register ( self , localpart = None , password = None , threepidCreds = None , captcha_info = { } ) :
""" Registers a new client on the server.
Args :
@ -51,6 +51,19 @@ class RegistrationHandler(BaseHandler):
Raises :
RegistrationError if there was a problem registering .
"""
if captcha_info :
captcha_response = yield self . _validate_captcha (
captcha_info [ " ip " ] ,
captcha_info [ " private_key " ] ,
captcha_info [ " challenge " ] ,
captcha_info [ " response " ]
)
if not captcha_response [ " valid " ] :
raise InvalidCaptchaError (
error_url = captcha_response [ " error_url " ]
)
else :
logger . info ( " Valid captcha entered from %s " , captcha_info [ " ip " ] )
if threepidCreds :
for c in threepidCreds :
@ -153,5 +166,37 @@ class RegistrationHandler(BaseHandler):
)
defer . returnValue ( data )
@defer . inlineCallbacks
def _validate_captcha ( self , ip_addr , private_key , challenge , response ) :
""" Validates the captcha provided.
Returns :
dict : Containing ' valid ' ( bool ) and ' error_url ' ( str ) if invalid .
"""
response = yield self . _submit_captcha ( ip_addr , private_key , challenge , response )
# parse Google's response. Lovely format..
lines = response . split ( ' \n ' )
json = {
" valid " : lines [ 0 ] == ' true ' ,
" error_url " : " http://www.google.com/recaptcha/api/challenge?error= %s " % lines [ 1 ]
}
defer . returnValue ( json )
@defer . inlineCallbacks
def _submit_captcha ( self , ip_addr , private_key , challenge , response ) :
client = PlainHttpClient ( self . hs )
data = yield client . post_urlencoded_get_raw (
" www.google.com:80 " ,
" /recaptcha/api/verify " ,
accept_partial = True , # twisted dislikes google's response, no content length.
args = {
' privatekey ' : private_key ,
' remoteip ' : ip_addr ,
' challenge ' : challenge ,
' response ' : response
}
)
defer . returnValue ( data )