diff --git a/src/jcl/jabber/command.py b/src/jcl/jabber/command.py index 853c1ef..45575a2 100644 --- a/src/jcl/jabber/command.py +++ b/src/jcl/jabber/command.py @@ -516,7 +516,7 @@ class JCLCommandManager(CommandManager): result = [] for account_name in session_context["account_names"]: name, user_jid = self.get_name_and_jid(account_name) - result += self.account_manager.remove_account_from_name(user_jid, + result += self.account_manager.remove_account_from_name(JID(user_jid), name) command_node.setProp("status", STATUS_COMPLETED) return (None, result) @@ -944,10 +944,9 @@ class JCLCommandManager(CommandManager): motd = self.component.get_motd() if motd is not None: for user in users: + user.has_received_motd = False for _account in user.accounts: - if _account.status == account.OFFLINE: - user.has_received_motd = False - else: + if _account.status != account.OFFLINE: user.has_received_motd = True if user.has_received_motd: result.append(Message(from_jid=self.component.jid, diff --git a/src/jcl/jabber/component.py b/src/jcl/jabber/component.py index 075048f..b009d77 100644 --- a/src/jcl/jabber/component.py +++ b/src/jcl/jabber/component.py @@ -57,7 +57,8 @@ from jcl.jabber.command import CommandDiscoGetItemsHandler, \ from jcl.jabber.presence import AccountPresenceAvailableHandler, \ RootPresenceAvailableHandler, AccountPresenceUnavailableHandler, \ RootPresenceUnavailableHandler, AccountPresenceSubscribeHandler, \ - RootPresenceSubscribeHandler, AccountPresenceUnsubscribeHandler + RootPresenceSubscribeHandler, AccountPresenceUnsubscribeHandler, \ + RootPresenceUnsubscribeHandler from jcl.jabber.register import RootSetRegisterHandler, \ AccountSetRegisterHandler, AccountTypeSetRegisterHandler import jcl.model as model @@ -110,7 +111,8 @@ class JCLComponent(Component, object): self.msg_handlers = [] self.presence_subscribe_handlers = [[AccountPresenceSubscribeHandler(self), RootPresenceSubscribeHandler(self)]] - self.presence_unsubscribe_handlers = [[AccountPresenceUnsubscribeHandler(self)]] + self.presence_unsubscribe_handlers = [[AccountPresenceUnsubscribeHandler(self), + RootPresenceUnsubscribeHandler(self)]] self.presence_available_handlers = [[AccountPresenceAvailableHandler(self), RootPresenceAvailableHandler(self)]] self.presence_unavailable_handlers = [[AccountPresenceUnavailableHandler(self), @@ -448,7 +450,7 @@ class JCLComponent(Component, object): remove = info_query.xpath_eval("r:query/r:remove", {"r" : "jabber:iq:register"}) if remove: - result = self.account_manager.remove_all_accounts(unicode(from_jid.bare())) + result = self.account_manager.remove_all_accounts(from_jid) self.send_stanzas(result) return 1 @@ -720,16 +722,9 @@ class AccountManager(object): model.db_connect() result = [] for _account in account.get_accounts(user_jid): - self.__logger.debug("Deleting " + _account.name - + " for " + unicode(user_jid)) - # get_jid - result.append(Presence(from_jid=_account.jid, - to_jid=user_jid, - stanza_type="unsubscribe")) - result.append(Presence(from_jid=_account.jid, - to_jid=user_jid, - stanza_type="unsubscribed")) - _account.destroySelf() + result.extend(self.remove_account(_account, user_jid, False)) + user = account.get_user(unicode(user_jid.bare())) + user.destroySelf() result.append(Presence(from_jid=self.component.jid, to_jid=user_jid, stanza_type="unsubscribe")) @@ -746,7 +741,7 @@ class AccountManager(object): else: return [] - def remove_account(self, _account, user_jid): + def remove_account(self, _account, user_jid, remove_user=True): self.__logger.debug("Deleting account: " + str(_account)) result = [] model.db_connect() @@ -757,6 +752,12 @@ class AccountManager(object): to_jid=user_jid, stanza_type="unsubscribed")) _account.destroySelf() + if remove_user: + bare_user_jid = unicode(user_jid.bare()) + accounts_count = account.get_accounts_count(bare_user_jid) + if accounts_count == 0: + user = account.get_user(bare_user_jid) + user.destroySelf() model.db_disconnect() return result @@ -841,7 +842,10 @@ class AccountManager(object): bare_from_jid = unicode(from_jid.bare()) first_account = (account.get_accounts_count(bare_from_jid) == 0) model.db_connect() - _account = account_class(user=User(jid=unicode(bare_from_jid)), + user = account.get_user(bare_from_jid) + if user is None: + user = User(jid=bare_from_jid) + _account = account_class(user=user, name=account_name, jid=self.get_account_jid(account_name)) model.db_disconnect() diff --git a/src/jcl/jabber/presence.py b/src/jcl/jabber/presence.py index d0b699d..2686854 100644 --- a/src/jcl/jabber/presence.py +++ b/src/jcl/jabber/presence.py @@ -164,3 +164,14 @@ class AccountPresenceUnsubscribeHandler(Handler): from_jid = stanza.get_from() _account = data return self.component.account_manager.remove_account(_account, from_jid) + +class RootPresenceUnsubscribeHandler(Handler): + """""" + + filter = jabber.get_accounts_root_filter + + def handle(self, stanza, lang_class, data): + """Handle \"unsubscribe\" iq sent to account JID""" + from_jid = stanza.get_from() + _account = data + return self.component.account_manager.remove_all_accounts(from_jid) diff --git a/src/jcl/jabber/tests/component.py b/src/jcl/jabber/tests/component.py index 99e7d26..f20d21c 100644 --- a/src/jcl/jabber/tests/component.py +++ b/src/jcl/jabber/tests/component.py @@ -1352,15 +1352,15 @@ class JCLComponent_TestCase(JCLTestCase): self.comp.stream_class = MockStream self.comp.account_manager.account_classes = (ExampleAccount,) x_data = Form("submit") - x_data.add_field(name = "name", \ - value = "account1", \ - field_type = "text-single") - x_data.add_field(name = "login", \ - value = "mylogin", \ - field_type = "text-single") - iq_set = Iq(stanza_type = "set", \ - from_jid = "user1@test.com", \ - to_jid = "jcl.test.com") + x_data.add_field(name="name", + value="account1", + field_type="text-single") + x_data.add_field(name="login", + value="mylogin", + field_type="text-single") + iq_set = Iq(stanza_type="set", + from_jid="user1@test.com", + to_jid="jcl.test.com") query = iq_set.new_query("jabber:iq:register") x_data.as_xml(query) self.comp.handle_set_register(iq_set) @@ -1378,6 +1378,67 @@ class JCLComponent_TestCase(JCLTestCase): self.assertEquals(_account.test_int, 44) model.db_disconnect() + def test_handle_set_register_user_already_exists(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + self.comp.account_manager.account_classes = (ExampleAccount,) + x_data = Form("submit") + x_data.add_field(name="name", + value="account1", + field_type="text-single") + x_data.add_field(name="login", + value="mylogin1", + field_type="text-single") + iq_set = Iq(stanza_type="set", + from_jid="user1@test.com", + to_jid="jcl.test.com") + query = iq_set.new_query("jabber:iq:register") + x_data.as_xml(query) + self.comp.handle_set_register(iq_set) + + model.db_connect() + _account = account.get_account("user1@test.com", "account1") + self.assertNotEquals(_account, None) + self.assertEquals(_account.user.jid, "user1@test.com") + self.assertEquals(_account.name, "account1") + self.assertEquals(_account.jid, "account1@jcl.test.com") + self.assertEquals(_account.login, "mylogin1") + self.assertEquals(_account.password, None) + self.assertTrue(_account.store_password) + self.assertEquals(_account.test_enum, "choice2") + self.assertEquals(_account.test_int, 44) + model.db_disconnect() + + x_data = Form("submit") + x_data.add_field(name="name", + value="account2", + field_type="text-single") + x_data.add_field(name="login", + value="mylogin2", + field_type="text-single") + iq_set = Iq(stanza_type="set", + from_jid="user1@test.com", + to_jid="jcl.test.com") + query = iq_set.new_query("jabber:iq:register") + x_data.as_xml(query) + self.comp.handle_set_register(iq_set) + + model.db_connect() + _account = account.get_account("user1@test.com", "account2") + self.assertNotEquals(_account, None) + self.assertEquals(_account.user.jid, "user1@test.com") + self.assertEquals(_account.name, "account2") + self.assertEquals(_account.jid, "account2@jcl.test.com") + self.assertEquals(_account.login, "mylogin2") + self.assertEquals(_account.password, None) + self.assertTrue(_account.store_password) + self.assertEquals(_account.test_enum, "choice2") + self.assertEquals(_account.test_int, 44) + + users = account.get_all_users(filter=(User.q.jid == "user1@test.com")) + self.assertEquals(users.count(), 1) + model.db_disconnect() + def test_handle_set_register_new_name_mandatory(self): self.comp.stream = MockStream() self.comp.stream_class = MockStream @@ -1539,6 +1600,8 @@ class JCLComponent_TestCase(JCLTestCase): model.db_connect() self.assertEquals(account.get_accounts_count("user1@test.com"), 0) + self.assertEquals(account.get_all_users(filter=(User.q.jid == "user1@test.com")).count(), + 0) accounts = account.get_accounts("user2@test.com") i = 0 for _account in accounts: @@ -2369,6 +2432,111 @@ class JCLComponent_TestCase(JCLTestCase): 1) self.assertEquals(account.get_all_accounts_count(), 2) + self.assertEquals(account.get_all_users(filter=(User.q.jid == "user1@test.com")).count(), + 1) + model.db_disconnect() + + def test_handle_presence_unsubscribe_to_last_account(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = Account(user=user1, + name="account11", + jid="account11@jcl.test.com") + account2 = Account(user=User(jid="user2@test.com"), + name="account2", + jid="account2@jcl.test.com") + model.db_disconnect() + self.comp.handle_presence_unsubscribe(Presence(\ + stanza_type="unsubscribe", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com")) + presence_sent = self.comp.stream.sent + self.assertEqual(len(presence_sent), 2) + presence = presence_sent[0] + self.assertEqual(presence.get_from(), "account11@jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribe") + presence = presence_sent[1] + self.assertEqual(presence.get_from(), "account11@jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribed") + model.db_connect() + self.assertEquals(account.get_account("user1@test.com", "account11"), + None) + self.assertEquals(account.get_accounts_count("user1@test.com"), + 0) + self.assertEquals(account.get_all_accounts_count(), + 1) + self.assertEquals(account.get_all_users(filter=(User.q.jid == "user1@test.com")).count(), + 0) + model.db_disconnect() + + def test_handle_presence_unsubscribe_to_root(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = Account(user=user1, + name="account11", + jid="account11@jcl.test.com") + account12 = Account(user=user1, + name="account12", + jid="account12@jcl.test.com") + account2 = Account(user=User(jid="user2@test.com"), + name="account2", + jid="account2@jcl.test.com") + model.db_disconnect() + self.comp.handle_presence_unsubscribe(Presence(\ + stanza_type="unsubscribe", + from_jid="user1@test.com", + to_jid="jcl.test.com")) + presence_sent = self.comp.stream.sent + self.assertEqual(len(presence_sent), 6) + presence = presence_sent[0] + self.assertEqual(presence.get_from(), "account11@jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribe") + presence = presence_sent[1] + self.assertEqual(presence.get_from(), "account11@jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribed") + presence = presence_sent[2] + self.assertEqual(presence.get_from(), "account12@jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribe") + presence = presence_sent[3] + self.assertEqual(presence.get_from(), "account12@jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribed") + presence = presence_sent[4] + self.assertEqual(presence.get_from(), "jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribe") + presence = presence_sent[5] + self.assertEqual(presence.get_from(), "jcl.test.com") + self.assertEqual(presence.get_to(), "user1@test.com") + self.assertEqual(presence.xpath_eval("@type")[0].get_content(), + "unsubscribed") + model.db_connect() + self.assertEquals(account.get_account("user1@test.com", "account11"), + None) + self.assertEquals(account.get_account("user1@test.com", "account12"), + None) + self.assertEquals(account.get_accounts_count("user1@test.com"), + 0) + self.assertEquals(account.get_all_accounts_count(), + 1) + self.assertEquals(account.get_all_users(filter=(User.q.jid == "user1@test.com")).count(), + 0) model.db_disconnect() def test_handle_presence_unsubscribe_to_registered_handlers(self): diff --git a/src/jcl/lang.py b/src/jcl/lang.py index 5820cba..50a4171 100644 --- a/src/jcl/lang.py +++ b/src/jcl/lang.py @@ -308,17 +308,17 @@ class Lang: command_get_user_password = u"Récupérer le mot de passe d'un compte" command_get_user_password_1_description = \ - u"Remplir ce formulaire avec le(s) Jabber ID(s) utilisateur(s)" \ - u" pour rechercher le(s) compte(s) pour récupérer leur mot de passe" + u"Remplir ce formulaire avec le Jabber ID utilisateur" \ + u" pour rechercher le compte pour récupérer leur mot de passe" command_get_user_password_2_description = \ - u"Sélectionner le(s) compte(s) pour récupérer leur mot de passe" + u"Sélectionner le compte pour récupérer leur mot de passe" command_change_user_password = u"Changer le mot de passe d'un compte" command_change_user_password_1_description = \ - u"Remplir ce formulaire avec le(s) Jabber ID(s) utilisateur(s)" \ - u" pour rechercher le(s) compte(s) pour changer leur mot de passe" + u"Remplir ce formulaire avec le Jabber ID utilisateur" \ + u" pour rechercher le compte pour changer leur mot de passe" command_change_user_password_2_description = \ - u"Sélectionner le(s) compte(s) pour changer leur mot de passe" + u"Sélectionner le compte pour changer leur mot de passe" command_get_user_roster = u"Récupérer les comptes utilisateurs" command_get_user_roster_1_description = \ diff --git a/src/jcl/model/account.py b/src/jcl/model/account.py index 1be7311..90dbeaf 100644 --- a/src/jcl/model/account.py +++ b/src/jcl/model/account.py @@ -70,7 +70,6 @@ def get_user(bare_from_jid, user_class=User): result = None model.db_connect() users = user_class.select(User.q.jid == bare_from_jid) - model.db_disconnect() if users.count() > 0: result = users[0] return result