Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0077.py @ 2172:545a1261ac3b
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.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 08 Mar 2017 20:59:31 +0100 |
parents | 33c8c4973743 |
children | 75002ac33801 |
comparison
equal
deleted
inserted
replaced
2171:978011533892 | 2172:545a1261ac3b |
---|---|
21 from sat.core.constants import Const as C | 21 from sat.core.constants import Const as C |
22 from sat.core import exceptions | 22 from sat.core import exceptions |
23 from sat.core.log import getLogger | 23 from sat.core.log import getLogger |
24 log = getLogger(__name__) | 24 log = getLogger(__name__) |
25 from twisted.words.protocols.jabber import jid | 25 from twisted.words.protocols.jabber import jid |
26 from twisted.words.protocols.jabber.xmlstream import IQ | 26 from twisted.words.protocols.jabber import xmlstream |
27 from twisted.internet import defer, reactor | |
27 from sat.tools import xml_tools | 28 from sat.tools import xml_tools |
28 | 29 |
29 from wokkel import data_form, compat | 30 from wokkel import data_form |
30 | 31 |
31 NS_REG = 'jabber:iq:register' | 32 NS_REG = 'jabber:iq:register' |
32 | 33 |
33 PLUGIN_INFO = { | 34 PLUGIN_INFO = { |
34 C.PI_NAME: "XEP 0077 Plugin", | 35 C.PI_NAME: "XEP 0077 Plugin", |
38 C.PI_DEPENDENCIES: [], | 39 C.PI_DEPENDENCIES: [], |
39 C.PI_MAIN: "XEP_0077", | 40 C.PI_MAIN: "XEP_0077", |
40 C.PI_DESCRIPTION: _("""Implementation of in-band registration""") | 41 C.PI_DESCRIPTION: _("""Implementation of in-band registration""") |
41 } | 42 } |
42 | 43 |
44 # FIXME: this implementation is incomplete | |
45 | |
46 class RegisteringAuthenticator(xmlstream.ConnectAuthenticator): | |
47 # FIXME: request IQ is not send to check available fields, while XEP recommand to use it | |
48 # FIXME: doesn't handle data form or oob | |
49 | |
50 def __init__(self, jid_, password, email=None): | |
51 xmlstream.ConnectAuthenticator.__init__(self, jid_.host) | |
52 self.jid = jid_ | |
53 self.password = password | |
54 self.email = email | |
55 self.registered = defer.Deferred() | |
56 log.debug(_(u"Registration asked for {jid}").format( | |
57 jid = jid_)) | |
58 | |
59 def connectionMade(self): | |
60 log.debug(_(u"Connection made with {server}".format(server=self.jid.host))) | |
61 self.xmlstream.otherEntity = jid.JID(self.jid.host) | |
62 self.xmlstream.namespace = C.NS_CLIENT | |
63 self.xmlstream.sendHeader() | |
64 | |
65 iq = xmlstream.IQ(self.xmlstream, 'set') | |
66 iq["to"] = self.jid.host | |
67 query_elt = iq.addElement(('jabber:iq:register', 'query')) | |
68 username_elt = query_elt.addElement('username') | |
69 username_elt.addContent(self.jid.user) | |
70 password_elt = query_elt.addElement('password') | |
71 password_elt.addContent(self.password) | |
72 if self.email is not None: | |
73 email_elt = query_elt.addElement('email') | |
74 email_elt.addContent(self.email) | |
75 d = iq.send(self.jid.host).addCallbacks(self.registrationCb, self.registrationEb) | |
76 d.chainDeferred(self.registered) | |
77 | |
78 def registrationCb(self, answer): | |
79 log.debug(_(u"Registration answer: {}").format(answer.toXml())) | |
80 self.xmlstream.sendFooter() | |
81 | |
82 def registrationEb(self, failure_): | |
83 log.info(_("Registration failure: {}").format(unicode(failure_.value))) | |
84 self.xmlstream.sendFooter() | |
85 raise failure_.value | |
86 | |
43 | 87 |
44 class XEP_0077(object): | 88 class XEP_0077(object): |
45 | 89 |
46 def __init__(self, host): | 90 def __init__(self, host): |
47 log.info(_("Plugin XEP_0077 initialization")) | 91 log.info(_("Plugin XEP_0077 initialization")) |
48 self.host = host | 92 self.host = host |
49 self.triggers = {} # used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid | |
50 host.bridge.addMethod("inBandRegister", ".plugin", in_sign='ss', out_sign='s', | 93 host.bridge.addMethod("inBandRegister", ".plugin", in_sign='ss', out_sign='s', |
51 method=self._inBandRegister, | 94 method=self._inBandRegister, |
52 async=True) | 95 async=True) |
53 | 96 |
54 def _regOk(self, answer, client, post_treat_cb): | 97 def _regCb(self, answer, client, post_treat_cb): |
55 """Called after the first get IQ""" | 98 """Called after the first get IQ""" |
56 try: | 99 try: |
57 query_elt = answer.elements(NS_REG, 'query').next() | 100 query_elt = answer.elements(NS_REG, 'query').next() |
58 except StopIteration: | 101 except StopIteration: |
59 raise exceptions.DataError("Can't find expected query element") | 102 raise exceptions.DataError("Can't find expected query element") |
66 raise exceptions.DataError(_("This gateway can't be managed by SàT, sorry :(")) | 109 raise exceptions.DataError(_("This gateway can't be managed by SàT, sorry :(")) |
67 | 110 |
68 def submitForm(data, profile): | 111 def submitForm(data, profile): |
69 form_elt = xml_tools.XMLUIResultToElt(data) | 112 form_elt = xml_tools.XMLUIResultToElt(data) |
70 | 113 |
71 iq_elt = compat.IQ(client.xmlstream, 'set') | 114 iq_elt = client.IQ() |
72 iq_elt['id'] = answer['id'] | 115 iq_elt['id'] = answer['id'] |
73 iq_elt['to'] = answer['from'] | 116 iq_elt['to'] = answer['from'] |
74 query_elt = iq_elt.addElement("query", NS_REG) | 117 query_elt = iq_elt.addElement("query", NS_REG) |
75 query_elt.addChild(form_elt) | 118 query_elt.addChild(form_elt) |
76 d = iq_elt.send() | 119 d = iq_elt.send() |
80 | 123 |
81 form = data_form.Form.fromElement(x_elem) | 124 form = data_form.Form.fromElement(x_elem) |
82 submit_reg_id = self.host.registerCallback(submitForm, with_data=True, one_shot=True) | 125 submit_reg_id = self.host.registerCallback(submitForm, with_data=True, one_shot=True) |
83 return xml_tools.dataForm2XMLUI(form, submit_reg_id) | 126 return xml_tools.dataForm2XMLUI(form, submit_reg_id) |
84 | 127 |
85 def _regErr(self, failure, client): | 128 def _regEb(self, failure, client): |
86 """Called when something is wrong with registration""" | 129 """Called when something is wrong with registration""" |
87 log.info(_("Registration failure: %s") % unicode(failure.value)) | 130 log.info(_("Registration failure: %s") % unicode(failure.value)) |
88 raise failure | 131 raise failure |
89 | 132 |
90 def _regSuccess(self, answer, client, post_treat_cb): | 133 def _regSuccess(self, answer, client, post_treat_cb): |
103 return self.inBandRegister, jid.JID(to_jid_s, profile_key) | 146 return self.inBandRegister, jid.JID(to_jid_s, profile_key) |
104 | 147 |
105 def inBandRegister(self, to_jid, post_treat_cb=None, profile_key=C.PROF_KEY_NONE): | 148 def inBandRegister(self, to_jid, post_treat_cb=None, profile_key=C.PROF_KEY_NONE): |
106 """register to a target JID""" | 149 """register to a target JID""" |
107 client = self.host.getClient(profile_key) | 150 client = self.host.getClient(profile_key) |
108 log.debug(_(u"Asking registration for [%s]") % to_jid.full()) | 151 log.debug(_(u"Asking registration for {}").format(to_jid.full())) |
109 reg_request = IQ(client.xmlstream, 'get') | 152 reg_request = client.IQ(u'get') |
110 reg_request["from"] = client.jid.full() | 153 reg_request["from"] = client.jid.full() |
111 reg_request["to"] = to_jid.full() | 154 reg_request["to"] = to_jid.full() |
112 reg_request.addElement('query', NS_REG) | 155 reg_request.addElement('query', NS_REG) |
113 d = reg_request.send(to_jid.full()).addCallbacks(self._regOk, self._regErr, callbackArgs=[client, post_treat_cb], errbackArgs=[client]) | 156 d = reg_request.send(to_jid.full()).addCallbacks(self._regCb, self._regEb, callbackArgs=[client, post_treat_cb], errbackArgs=[client]) |
114 return d | 157 return d |
158 | |
159 def registerNewAccount(self, client, jid_, password, email=None, host="127.0.0.1", port=C.XMPP_C2S_PORT): | |
160 """register a new account on a XMPP server | |
161 | |
162 @param jid_(jid.JID): request jid to register | |
163 @param password(unicode): password of the account | |
164 @param email(unicode): email of the account | |
165 @param host(unicode): host of the server to register to | |
166 @param port(int): port of the server to register to | |
167 """ | |
168 authenticator = RegisteringAuthenticator(jid_, password, email) | |
169 registered_d = authenticator.registered | |
170 serverRegistrer = xmlstream.XmlStreamFactory(authenticator) | |
171 connector = reactor.connectTCP(host, port, serverRegistrer) | |
172 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect() | |
173 return registered_d |