core, plugin XEP-0077: in-band registration fix and move:

in-band was partially in core for historical reason, it has been moved to XEP-0077, and fixed. It is still incomplete, but should work for basic accounts creation.
This commit is contained in:
Goffi 2017-03-08 20:59:31 +01:00
commit d1ba64c780

View file

@ -23,10 +23,11 @@ from sat.core import exceptions
from sat.core.log import getLogger
log = getLogger(__name__)
from twisted.words.protocols.jabber import jid
from twisted.words.protocols.jabber.xmlstream import IQ
from twisted.words.protocols.jabber import xmlstream
from twisted.internet import defer, reactor
from sat.tools import xml_tools
from wokkel import data_form, compat
from wokkel import data_form
NS_REG = 'jabber:iq:register'
@ -40,18 +41,60 @@ PLUGIN_INFO = {
C.PI_DESCRIPTION: _("""Implementation of in-band registration""")
}
# FIXME: this implementation is incomplete
class RegisteringAuthenticator(xmlstream.ConnectAuthenticator):
# FIXME: request IQ is not send to check available fields, while XEP recommand to use it
# FIXME: doesn't handle data form or oob
def __init__(self, jid_, password, email=None):
xmlstream.ConnectAuthenticator.__init__(self, jid_.host)
self.jid = jid_
self.password = password
self.email = email
self.registered = defer.Deferred()
log.debug(_(u"Registration asked for {jid}").format(
jid = jid_))
def connectionMade(self):
log.debug(_(u"Connection made with {server}".format(server=self.jid.host)))
self.xmlstream.otherEntity = jid.JID(self.jid.host)
self.xmlstream.namespace = C.NS_CLIENT
self.xmlstream.sendHeader()
iq = xmlstream.IQ(self.xmlstream, 'set')
iq["to"] = self.jid.host
query_elt = iq.addElement(('jabber:iq:register', 'query'))
username_elt = query_elt.addElement('username')
username_elt.addContent(self.jid.user)
password_elt = query_elt.addElement('password')
password_elt.addContent(self.password)
if self.email is not None:
email_elt = query_elt.addElement('email')
email_elt.addContent(self.email)
d = iq.send(self.jid.host).addCallbacks(self.registrationCb, self.registrationEb)
d.chainDeferred(self.registered)
def registrationCb(self, answer):
log.debug(_(u"Registration answer: {}").format(answer.toXml()))
self.xmlstream.sendFooter()
def registrationEb(self, failure_):
log.info(_("Registration failure: {}").format(unicode(failure_.value)))
self.xmlstream.sendFooter()
raise failure_.value
class XEP_0077(object):
def __init__(self, host):
log.info(_("Plugin XEP_0077 initialization"))
self.host = host
self.triggers = {} # used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid
host.bridge.addMethod("inBandRegister", ".plugin", in_sign='ss', out_sign='s',
method=self._inBandRegister,
async=True)
def _regOk(self, answer, client, post_treat_cb):
def _regCb(self, answer, client, post_treat_cb):
"""Called after the first get IQ"""
try:
query_elt = answer.elements(NS_REG, 'query').next()
@ -68,7 +111,7 @@ class XEP_0077(object):
def submitForm(data, profile):
form_elt = xml_tools.XMLUIResultToElt(data)
iq_elt = compat.IQ(client.xmlstream, 'set')
iq_elt = client.IQ()
iq_elt['id'] = answer['id']
iq_elt['to'] = answer['from']
query_elt = iq_elt.addElement("query", NS_REG)
@ -82,7 +125,7 @@ class XEP_0077(object):
submit_reg_id = self.host.registerCallback(submitForm, with_data=True, one_shot=True)
return xml_tools.dataForm2XMLUI(form, submit_reg_id)
def _regErr(self, failure, client):
def _regEb(self, failure, client):
"""Called when something is wrong with registration"""
log.info(_("Registration failure: %s") % unicode(failure.value))
raise failure
@ -105,10 +148,26 @@ class XEP_0077(object):
def inBandRegister(self, to_jid, post_treat_cb=None, profile_key=C.PROF_KEY_NONE):
"""register to a target JID"""
client = self.host.getClient(profile_key)
log.debug(_(u"Asking registration for [%s]") % to_jid.full())
reg_request = IQ(client.xmlstream, 'get')
log.debug(_(u"Asking registration for {}").format(to_jid.full()))
reg_request = client.IQ(u'get')
reg_request["from"] = client.jid.full()
reg_request["to"] = to_jid.full()
reg_request.addElement('query', NS_REG)
d = reg_request.send(to_jid.full()).addCallbacks(self._regOk, self._regErr, callbackArgs=[client, post_treat_cb], errbackArgs=[client])
d = reg_request.send(to_jid.full()).addCallbacks(self._regCb, self._regEb, callbackArgs=[client, post_treat_cb], errbackArgs=[client])
return d
def registerNewAccount(self, client, jid_, password, email=None, host="127.0.0.1", port=C.XMPP_C2S_PORT):
"""register a new account on a XMPP server
@param jid_(jid.JID): request jid to register
@param password(unicode): password of the account
@param email(unicode): email of the account
@param host(unicode): host of the server to register to
@param port(int): port of the server to register to
"""
authenticator = RegisteringAuthenticator(jid_, password, email)
registered_d = authenticator.registered
serverRegistrer = xmlstream.XmlStreamFactory(authenticator)
connector = reactor.connectTCP(host, port, serverRegistrer)
serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect()
return registered_d