# HG changeset patch # User souliane # Date 1400194700 -7200 # Node ID 6e975c6b0faf23b5d0bfa1ca1bed8e489d4e5193 # Parent 35048cafb18d067f094a50696c6f1201ec64f13e core, memory, bridge, plugin misc_register_account: move registerNewAccount to a new plugin: - the bridge method has been removed, now a plugin takes care of it with XMLUI callback system - TODO: xmpp.RegisteringAuthenticator still needs to be fixed diff -r 35048cafb18d -r 6e975c6b0faf frontends/src/bridge/DBus.py --- a/frontends/src/bridge/DBus.py Fri May 16 00:53:09 2014 +0200 +++ b/frontends/src/bridge/DBus.py Fri May 16 00:58:20 2014 +0200 @@ -204,9 +204,6 @@ def paramsRegisterApp(self, xml, security_limit=-1, app=''): return self.db_core_iface.paramsRegisterApp(xml, security_limit, app) - def registerNewAccount(self, login, password, email, host, port=5222): - return unicode(self.db_core_iface.registerNewAccount(login, password, email, host, port)) - def saveParamsTemplate(self, filename): return self.db_core_iface.saveParamsTemplate(filename) diff -r 35048cafb18d -r 6e975c6b0faf src/bridge/DBus.py --- a/src/bridge/DBus.py Fri May 16 00:53:09 2014 +0200 +++ b/src/bridge/DBus.py Fri May 16 00:58:20 2014 +0200 @@ -404,12 +404,6 @@ return self._callback("paramsRegisterApp", unicode(xml), security_limit, unicode(app)) @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, - in_signature='ssssi', out_signature='s', - async_callbacks=None) - def registerNewAccount(self, login, password, email, host, port=5222): - return self._callback("registerNewAccount", unicode(login), unicode(password), unicode(email), unicode(host), port) - - @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, in_signature='s', out_signature='b', async_callbacks=None) def saveParamsTemplate(self, filename): diff -r 35048cafb18d -r 6e975c6b0faf src/bridge/bridge_constructor/bridge_template.ini --- a/src/bridge/bridge_constructor/bridge_template.ini Fri May 16 00:53:09 2014 +0200 +++ b/src/bridge/bridge_constructor/bridge_template.ini Fri May 16 00:58:20 2014 +0200 @@ -228,20 +228,6 @@ - ProfileUnknownError: the profile name is unknown - ConnectedProfileError: a connected profile would not be deleted -[registerNewAccount] -deprecated= -type=method -category=core -sig_in=ssssi -sig_out=s -param_4_default=5222 -doc=Register a new account on a given server -doc_param_0=login: login of the account -doc_param_1=password: password of the account -doc_param_2=email: email of the account -doc_param_3=host: host of the server to register to -doc_param_4=port: port of the server to register to - [connect] type=method category=core diff -r 35048cafb18d -r 6e975c6b0faf src/core/sat_main.py --- a/src/core/sat_main.py Fri May 16 00:53:09 2014 +0200 +++ b/src/core/sat_main.py Fri May 16 00:58:20 2014 +0200 @@ -20,7 +20,7 @@ from sat.core.i18n import _, languageSwitch from twisted.application import service from twisted.internet import defer -from twisted.words.protocols.jabber import jid, xmlstream +from twisted.words.protocols.jabber import jid from twisted.words.xish import domish from twisted.internet import reactor from wokkel.xmppim import RosterItem @@ -102,7 +102,6 @@ self.bridge.register("getEntityData", lambda _jid, keys, profile: self.memory.getEntityData(jid.JID(_jid), keys, profile)) self.bridge.register("asyncCreateProfile", self.memory.asyncCreateProfile) self.bridge.register("asyncDeleteProfile", self.memory.asyncDeleteProfile) - self.bridge.register("registerNewAccount", self.registerNewAccount) self.bridge.register("connect", self.connect) self.bridge.register("asyncConnect", self.asyncConnect) self.bridge.register("disconnect", self.disconnect) @@ -413,52 +412,6 @@ raise exceptions.ProfileKeyUnknownError return [self.profiles[profile]] - def registerNewAccount(self, login, password, email, server, port=5222, id_=None, profile_key=C.PROF_KEY_NONE): - """Connect to a server and create a new account using in-band registration""" - profile = self.memory.getProfileName(profile_key) - assert(profile) - - next_id = id_ or self.get_next_id() # the id is used to send server's answer - serverRegistrer = xmlstream.XmlStreamFactory(xmpp.RegisteringAuthenticator(self, server, login, password, email, next_id, profile)) - connector = reactor.connectTCP(server, port, serverRegistrer) - serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect() - - return next_id - - def registerNewAccountCB(self, data, profile): - # FIXME: to be removed/redone elsewhere - user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0] - server = self.memory.getParamA("Server", "Connection", profile_key=profile) - d = self.memory.asyncGetParamA("Password", "Connection", profile_key=profile) - - def gotPassword(password): - if not user or not password or not server: - raise exceptions.DataError(_("No user, password or server given, can't register new account.")) - - # FIXME: to be fixed with XMLUI dialogs once their implemented - confirm_id = sat_next_id() - self.__private_data[confirm_id] = (id, profile) - - self.askConfirmation( - confirm_id, "YES/NO", - {"message": _("Are you sure to register new account [%(user)s] to server %(server)s ?") % {'user': user, 'server': server, 'profile': profile}}, - self.regisConfirmCB, profile) - print "===============+++++++++++ REGISTER NEW ACCOUNT++++++++++++++============" - - d.addCallback(gotPassword) - - def regisConfirmCB(self, id, accepted, data, profile): - print _("register Confirmation CB ! (%s)") % str(accepted) - action_id, profile = self.__private_data[id] - del self.__private_data[id] - if accepted: - user = jid.parse(self.memory.getParamA("JabberID", "Connection", profile_key=profile))[0] - server = self.memory.getParamA("Server", "Connection", profile_key=profile) - d = self.memory.asyncGetParamA("Password", "Connection", profile_key=profile) - d.addCallback(lambda password: self.registerNewAccount(user, password, None, server, id=action_id)) - else: - self.actionResult(action_id, "SUPPRESS", {}, profile) - ## Client management ## def setParam(self, name, value, category, security_limit, profile_key): diff -r 35048cafb18d -r 6e975c6b0faf src/core/xmpp.py --- a/src/core/xmpp.py Fri May 16 00:53:09 2014 +0200 +++ b/src/core/xmpp.py Fri May 16 00:58:20 2014 +0200 @@ -17,7 +17,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from sat.core.i18n import _ +from sat.core.i18n import _, D_ from sat.core.constants import Const as C from twisted.internet import task, defer from twisted.words.protocols.jabber import jid, xmlstream @@ -412,20 +412,19 @@ class RegisteringAuthenticator(xmlstream.ConnectAuthenticator): - def __init__(self, host, jabber_host, user_login, user_pass, email, answer_id, profile): + def __init__(self, host, jabber_host, user_login, user_pass, email, deferred, profile): xmlstream.ConnectAuthenticator.__init__(self, jabber_host) self.host = host self.jabber_host = jabber_host self.user_login = user_login self.user_pass = user_pass self.user_email = email - self.answer_id = answer_id + self.deferred = deferred self.profile = profile - print _("Registration asked for"), user_login, user_pass, jabber_host + log.debug(_("Registration asked for %(user)s@%(host)s") % {'user': user_login, 'host': jabber_host}) def connectionMade(self): - print "connectionMade" - + log.debug(_("Connection made with %s" % self.jabber_host)) self.xmlstream.namespace = "jabber:client" self.xmlstream.sendHeader() @@ -439,27 +438,17 @@ if self.user_email: _email = query.addElement('email') _email.addContent(self.user_email) - iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure) + d = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure) + d.chainDeferred(self.deferred) def registrationAnswer(self, answer): - log.debug(_("registration answer: %s") % answer.toXml()) - answer_type = "SUCCESS" - answer_data = {"message": _("Registration successfull")} - self.host.bridge.actionResult(answer_type, self.answer_id, answer_data, self.profile) + log.debug(_("Registration answer: %s") % answer.toXml()) self.xmlstream.sendFooter() def registrationFailure(self, failure): log.info(_("Registration failure: %s") % str(failure.value)) - answer_type = "ERROR" - answer_data = {} - if failure.value.condition == 'conflict': - answer_data['reason'] = 'conflict' - answer_data = {"message": _("Username already exists, please choose an other one")} - else: - answer_data['reason'] = 'unknown' - answer_data = {"message": _("Registration failed (%s)") % str(failure.value.condition)} - self.host.bridge.actionResult(answer_type, self.answer_id, answer_data, self.profile) self.xmlstream.sendFooter() + raise failure.value class SatVersionHandler(generic.VersionHandler): diff -r 35048cafb18d -r 6e975c6b0faf src/memory/params.py --- a/src/memory/params.py Fri May 16 00:53:09 2014 +0200 +++ b/src/memory/params.py Fri May 16 00:58:20 2014 +0200 @@ -135,7 +135,6 @@ self.default_profile = None self.params = {} self.params_gen = {} - host.registerCallback(host.registerNewAccountCB, with_data=True, force_id="registerNewAccount") def asyncCreateProfile(self, profile): """Create a new profile diff -r 35048cafb18d -r 6e975c6b0faf src/plugins/plugin_misc_register_account.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/plugin_misc_register_account.py Fri May 16 00:58:20 2014 +0200 @@ -0,0 +1,121 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# SàT plugin for registering a new XMPP account +# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org) +# Copyright (C) 2013, 2014 Adrien Cossa (souliane@mailoo.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from sat.core.i18n import _, D_ +from sat.core.log import getLogger +log = getLogger(__name__) +from sat.core.constants import Const as C +from twisted.words.protocols.jabber import jid, xmlstream +from sat.core import xmpp +from sat.memory.memory import Sessions +from twisted.internet import reactor, defer +from sat.tools import xml_tools +from sat.tools.xml_tools import SAT_FORM_PREFIX, SAT_PARAM_SEPARATOR + + +PLUGIN_INFO = { + "name": "Register Account Plugin", + "import_name": "REGISTER-ACCOUNT", + "type": "MISC", + "protocols": [], + "dependencies": [], + "recommendations": [], + "main": "RegisterAccount", + "handler": "no", + "description": _(u"""Register XMPP account""") +} + + +class RegisterAccount(object): + + def __init__(self, host): + log.info(_(u"Plugin Register Account initialization")) + self.host = host + self._sessions = Sessions() + host.registerCallback(self.registerNewAccountCB, with_data=True, force_id="registerNewAccount") + self.__register_account_id = host.registerCallback(self._registerConfirmation, with_data=True) + + def registerNewAccountCB(self, data, profile): + """Called when the use click on the "New account" button.""" + session_data = {} + for param in ('JabberID', 'Password', 'Port', 'Server'): + try: + session_data[param] = data["%s%s%s%s" % (SAT_FORM_PREFIX, "Connection", SAT_PARAM_SEPARATOR, param)] + except KeyError: + if param == 'Port': + session_data[param] = 5222 + + for param in ('JabberID', 'Password', 'Server'): + if not session_data[param]: + form_ui = xml_tools.XMLUI("popup", title=D_("Missing values")) + form_ui.addText(D_("No user, password or server given: can't register new account.")) + return {'xmlui': form_ui.toXml()} + + user = jid.parse(session_data['JabberID'])[0] + session_id, dummy = self._sessions.newSession(session_data, profile) + form_ui = xml_tools.XMLUI("form", title=D_("Register new account"), submit_id=self.__register_account_id, session_id=session_id) + form_ui.addText(D_("Do you want to register a new XMPP account [%(user)s] on server %(server)s ?") % {'user': user, 'server': session_data['Server']}) + return {'xmlui': form_ui.toXml()} + + def _registerConfirmation(self, data, profile): + """Save the related parameters and proceed the registration.""" + session_data = self._sessions.profileGet(data['session_id'], profile) + + self.host.memory.setParam("JabberID", session_data["JabberID"], "Connection", profile_key=profile) + self.host.memory.setParam("Password", session_data["Password"], "Connection", profile_key=profile) + self.host.memory.setParam("Server", session_data["Server"], "Connection", profile_key=profile) + self.host.memory.setParam("Port", session_data["Port"], "Connection", profile_key=profile) + + user = jid.parse(session_data['JabberID'])[0] + return self._registerNewAccount(user, session_data["Password"], None, session_data["Server"], profile_key=profile) + + def _registerNewAccount(self, user, password, email, host, port=5222, profile_key=C.PROF_KEY_NONE): + """Connect to a server and create a new account using in-band registration. + @param user: login of the account + @param password: password of the account + @param email: email of the account + @param host: host of the server to register to + @param port: port of the server to register to + @param profile_key: %(doc_profile_key)s + """ + profile = self.host.memory.getProfileName(profile_key) + + d = defer.Deferred() + serverRegistrer = xmlstream.XmlStreamFactory(xmpp.RegisteringAuthenticator(self, host, user, password, email, d, profile)) + connector = reactor.connectTCP(host, port, serverRegistrer) + serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect() + + def cb(dummy): + xmlui = xml_tools.XMLUI("popup", title=D_("Confirmation")) + xmlui.addText(D_("Registration successful.")) + return ({'xmlui': xmlui.toXml()}) + + def eb(failure): + xmlui = xml_tools.XMLUI("popup", title=D_("Failure")) + xmlui.addText(D_("Registration failed: %s") % failure.getErrorMessage()) + try: + if failure.value.condition == 'conflict': + xmlui.addText(D_("Username already exists, please choose an other one.")) + except AttributeError: + pass + return ({'xmlui': xmlui.toXml()}) + + d.addCallbacks(cb, eb) + return d diff -r 35048cafb18d -r 6e975c6b0faf src/test/helpers.py --- a/src/test/helpers.py Fri May 16 00:53:09 2014 +0200 +++ b/src/test/helpers.py Fri May 16 00:58:20 2014 +0200 @@ -81,9 +81,6 @@ def registerCallback(self, callback, *args, **kwargs): pass - def registerNewAccountCB(self, data, profile): - pass - def sendMessage(self, to_s, msg, subject=None, mess_type='auto', extra={}, profile_key='@NONE@'): self.sendAndStoreMessage({"to": JID(to_s)})