Handle log on and log off presence for legacy JID

Send presence "available"/"unavailable" to legacy JIDs according to presence sent to component JID

darcs-hash:20070612172042-86b55-3864aaf2a9113af4b880dc7282f0c307168e5f82.gz
This commit is contained in:
David Rousselie
2007-06-12 19:20:42 +02:00
parent 62ceb22a18
commit 0f62599951
4 changed files with 229 additions and 36 deletions

View File

@@ -52,7 +52,7 @@ from pyxmpp.jabber.dataforms import Form, Field, Option
import jcl import jcl
from jcl.jabber.error import FieldError from jcl.jabber.error import FieldError
from jcl.model import account from jcl.model import account
from jcl.model.account import Account from jcl.model.account import Account, LegacyJID
from jcl.lang import Lang from jcl.lang import Lang
VERSION = "0.1" VERSION = "0.1"
@@ -894,8 +894,9 @@ class AccountManager(object):
orderBy="user_jid"): orderBy="user_jid"):
if current_user_jid != _account.user_jid: if current_user_jid != _account.user_jid:
current_user_jid = _account.user_jid current_user_jid = _account.user_jid
result.extend(getattr(self, "_send_presence_" + result.extend(self._send_presence(self.component.jid,
presence + "_root")(_account.user_jid)) _account.user_jid,
presence))
result.extend(getattr(self, "_send_presence_" + result.extend(getattr(self, "_send_presence_" +
presence)(_account)) presence)(_account))
self.db_disconnect() self.db_disconnect()
@@ -917,14 +918,13 @@ class AccountManager(object):
return self.root_handle_presence(\ return self.root_handle_presence(\
from_jid, from_jid,
lambda _account: \ lambda _account: \
self._send_presence_available(_account, self._send_presence_available(_account,
show, show,
lang_class), lang_class),
lambda nb_accounts: \ lambda nb_accounts: \
self._send_presence_available_root(from_jid, self._send_root_presence(from_jid, show,
show, str(nb_accounts) +
str(nb_accounts) lang_class.message_status))
+ lang_class.message_status))
###### presence_unavailable handlers ###### ###### presence_unavailable handlers ######
def account_handle_presence_unavailable(self, name, from_jid): def account_handle_presence_unavailable(self, name, from_jid):
@@ -939,9 +939,9 @@ class AccountManager(object):
return self.root_handle_presence(\ return self.root_handle_presence(\
from_jid, from_jid,
lambda _account: \ lambda _account: \
self._send_presence_unavailable(_account), self._send_presence_unavailable(_account),
lambda nb_accounts: \ lambda nb_accounts: \
self._send_presence_unavailable_root(from_jid)) self._send_root_presence(from_jid))
###### presence_subscribe handlers ###### ###### presence_subscribe handlers ######
def account_handle_presence_subscribe(self, name, from_jid, stanza): def account_handle_presence_subscribe(self, name, from_jid, stanza):
@@ -1111,24 +1111,12 @@ class AccountManager(object):
"""Compose account jid from account name""" """Compose account jid from account name"""
return name + u"@" + unicode(self.component.jid) return name + u"@" + unicode(self.component.jid)
def _send_presence_probe_root(self, to_jid):
"""Send presence probe to account's user from root JID"""
return [Presence(from_jid=self.component.jid,
to_jid=to_jid,
stanza_type="probe")]
def _send_presence_probe(self, _account): def _send_presence_probe(self, _account):
"""Send presence probe to account's user""" """Send presence probe to account's user"""
return [Presence(from_jid=_account.jid, return [Presence(from_jid=_account.jid,
to_jid=_account.user_jid, to_jid=_account.user_jid,
stanza_type="probe")] stanza_type="probe")]
def _send_presence_unavailable_root(self, to_jid):
"""Send unavailable presence to account's user from root JID"""
return [Presence(from_jid=self.component.jid,
to_jid=to_jid,
stanza_type="unavailable")]
def _send_presence_unavailable(self, _account): def _send_presence_unavailable(self, _account):
"""Send unavailable presence to account's user""" """Send unavailable presence to account's user"""
_account.status = account.OFFLINE _account.status = account.OFFLINE
@@ -1136,14 +1124,24 @@ class AccountManager(object):
to_jid=_account.user_jid, to_jid=_account.user_jid,
stanza_type="unavailable")] stanza_type="unavailable")]
def _send_presence_available_root(self, to_jid, show, status_msg): def _send_root_presence(self, to_jid, show=None, status=None):
"""Send available presence to account's user from root JID""" result = self._send_presence(self.component.jid, to_jid,
return [Presence(from_jid=self.component.jid, "unavailable", show=show,
to_jid=to_jid, status=status)
status=status_msg, result.extend(self._send_root_presence_legacy(to_jid,
show=show, "unavailable",
stanza_type="available")] show=show,
status=status))
return result
def _send_presence(self, from_jid, to_jid, presence_type, status=None, show=None):
"""Send presence stanza"""
return [Presence(from_jid=from_jid,
to_jid=to_jid,
status=status,
show=show,
stanza_type=presence_type)]
def _send_presence_available(self, _account, show, lang_class): def _send_presence_available(self, _account, show, lang_class):
"""Send available presence to account's user and ask for password """Send available presence to account's user and ask for password
if necessary""" if necessary"""
@@ -1167,6 +1165,23 @@ class AccountManager(object):
result.extend(self.ask_password(_account, lang_class)) result.extend(self.ask_password(_account, lang_class))
return result return result
def _send_root_presence_legacy(self, to_jid, presence_type,
status=None, show=None):
"""Send presence from legacy JID"""
result = []
self.db_connect()
legacy_jids = LegacyJID.select(\
AND(LegacyJID.q.accountID == Account.q.id,
Account.q.user_jid == unicode(to_jid.bare())))
for legacy_jid in legacy_jids:
result.append(Presence(from_jid=legacy_jid.jid,
to_jid=to_jid,
show=show,
status=status,
stanza_type=presence_type))
self.db_disconnect()
return result
def ask_password(self, _account, lang_class): def ask_password(self, _account, lang_class):
"""Send a Jabber message to ask for account password """Send a Jabber message to ask for account password
""" """
@@ -1254,7 +1269,7 @@ class PasswordMessageHandler(Handler):
"""Handle password message""" """Handle password message"""
def __init__(self): def __init__(self):
"""andler constructor""" """handler constructor"""
self.password_regexp = re.compile("\[PASSWORD\]") self.password_regexp = re.compile("\[PASSWORD\]")
def filter(self, stanza, lang_class): def filter(self, stanza, lang_class):

View File

@@ -45,7 +45,7 @@ from jcl.jabber.component import JCLComponent, Handler, \
PasswordMessageHandler, DefaultSubscribeHandler, \ PasswordMessageHandler, DefaultSubscribeHandler, \
DefaultUnsubscribeHandler, DefaultPresenceHandler DefaultUnsubscribeHandler, DefaultPresenceHandler
from jcl.model import account from jcl.model import account
from jcl.model.account import Account from jcl.model.account import Account, LegacyJID
from jcl.lang import Lang from jcl.lang import Lang
from jcl.model.tests.account import ExampleAccount, Example2Account from jcl.model.tests.account import ExampleAccount, Example2Account
@@ -174,6 +174,7 @@ class JCLComponent_TestCase(unittest.TestCase):
'sqlite://' + DB_URL) 'sqlite://' + DB_URL)
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Account.createTable(ifNotExists = True) Account.createTable(ifNotExists = True)
LegacyJID.createTable(ifNotExists=True)
ExampleAccount.createTable(ifNotExists = True) ExampleAccount.createTable(ifNotExists = True)
Example2Account.createTable(ifNotExists = True) Example2Account.createTable(ifNotExists = True)
del account.hub.threadConnection del account.hub.threadConnection
@@ -184,6 +185,7 @@ class JCLComponent_TestCase(unittest.TestCase):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Example2Account.dropTable(ifExists = True) Example2Account.dropTable(ifExists = True)
ExampleAccount.dropTable(ifExists = True) ExampleAccount.dropTable(ifExists = True)
LegacyJID.dropTable(ifExists=True)
Account.dropTable(ifExists = True) Account.dropTable(ifExists = True)
del TheURIOpener.cachedURIs['sqlite://' + DB_URL] del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
account.hub.threadConnection.close() account.hub.threadConnection.close()
@@ -1474,6 +1476,88 @@ class JCLComponent_TestCase(unittest.TestCase):
and isinstance(presence, Presence)]), \ and isinstance(presence, Presence)]), \
1) 1)
def test_handle_presence_available_to_component_legacy_users(self):
self.comp.stream = MockStream()
self.comp.stream_class = MockStream
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = Account(user_jid="user1@test.com",
name="account11",
jid="account11@jcl.test.com")
account12 = Account(user_jid="user1@test.com",
name="account12",
jid="account12@jcl.test.com")
account2 = Account(user_jid="user2@test.com",
name="account2",
jid="account2@jcl.test.com")
legacy_jid111 = LegacyJID(legacy_address="u111@test.com",
jid="u111%test.com@jcl.test.com",
account=account11)
legacy_jid112 = LegacyJID(legacy_address="u112@test.com",
jid="u112%test.com@jcl.test.com",
account=account11)
legacy_jid121 = LegacyJID(legacy_address="u121@test.com",
jid="u121%test.com@jcl.test.com",
account=account12)
legacy_jid122 = LegacyJID(legacy_address="u122@test.com",
jid="u122%test.com@jcl.test.com",
account=account12)
legacy_jid21 = LegacyJID(legacy_address="u21@test.com",
jid="u21%test.com@jcl.test.com",
account=account2)
del account.hub.threadConnection
self.comp.handle_presence_available(Presence(\
stanza_type="available",
from_jid="user1@test.com",
to_jid="jcl.test.com"))
presence_sent = self.comp.stream.sent
self.assertEqual(len(presence_sent), 7)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_to_jid() == "user1@test.com"]),
7)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"account11@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"account12@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u111%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u112%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u121%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u122%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
def test_handle_presence_available_to_component_unknown_user(self): def test_handle_presence_available_to_component_unknown_user(self):
self.comp.stream = MockStream() self.comp.stream = MockStream()
self.comp.stream_class = MockStream self.comp.stream_class = MockStream
@@ -1705,6 +1789,88 @@ class JCLComponent_TestCase(unittest.TestCase):
== "unavailable"]), \ == "unavailable"]), \
1) 1)
def test_handle_presence_unavailable_to_component_legacy_users(self):
self.comp.stream = MockStream()
self.comp.stream_class = MockStream
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = Account(user_jid="user1@test.com",
name="account11",
jid="account11@jcl.test.com")
account12 = Account(user_jid="user1@test.com",
name="account12",
jid="account12@jcl.test.com")
account2 = Account(user_jid="user2@test.com",
name="account2",
jid="account2@jcl.test.com")
legacy_jid111 = LegacyJID(legacy_address="u111@test.com",
jid="u111%test.com@jcl.test.com",
account=account11)
legacy_jid112 = LegacyJID(legacy_address="u112@test.com",
jid="u112%test.com@jcl.test.com",
account=account11)
legacy_jid121 = LegacyJID(legacy_address="u121@test.com",
jid="u121%test.com@jcl.test.com",
account=account12)
legacy_jid122 = LegacyJID(legacy_address="u122@test.com",
jid="u122%test.com@jcl.test.com",
account=account12)
legacy_jid21 = LegacyJID(legacy_address="u21@test.com",
jid="u21%test.com@jcl.test.com",
account=account2)
del account.hub.threadConnection
self.comp.handle_presence_unavailable(Presence(\
stanza_type="unavailable",
from_jid="user1@test.com",
to_jid="jcl.test.com"))
presence_sent = self.comp.stream.sent
self.assertEqual(len(presence_sent), 7)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_to_jid() == "user1@test.com"]),
7)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"account11@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"account12@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u111%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u112%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u121%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
self.assertEqual(len([presence
for presence in presence_sent
if presence.get_from_jid() == \
"u122%test.com@jcl.test.com"
and isinstance(presence, Presence)]),
1)
def test_handle_presence_unavailable_to_component_unknown_user(self): def test_handle_presence_unavailable_to_component_unknown_user(self):
self.comp.stream = MockStream() self.comp.stream = MockStream()
self.comp.stream_class = MockStream self.comp.stream_class = MockStream

View File

@@ -35,7 +35,7 @@ from pyxmpp.message import Message
from jcl.jabber.component import JCLComponent from jcl.jabber.component import JCLComponent
from jcl.jabber.feeder import FeederComponent, Feeder, Sender, MessageSender, \ from jcl.jabber.feeder import FeederComponent, Feeder, Sender, MessageSender, \
HeadlineSender, FeederHandler HeadlineSender, FeederHandler
from jcl.model.account import Account from jcl.model.account import Account, LegacyJID
from jcl.model import account from jcl.model import account
from jcl.model.tests.account import ExampleAccount, Example2Account from jcl.model.tests.account import ExampleAccount, Example2Account
@@ -69,6 +69,7 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
'sqlite://' + DB_URL) 'sqlite://' + DB_URL)
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Account.createTable(ifNotExists = True) Account.createTable(ifNotExists = True)
LegacyJID.createTable(ifNotExists=True)
ExampleAccount.createTable(ifNotExists = True) ExampleAccount.createTable(ifNotExists = True)
Example2Account.createTable(ifNotExists = True) Example2Account.createTable(ifNotExists = True)
del account.hub.threadConnection del account.hub.threadConnection
@@ -76,6 +77,7 @@ class FeederComponent_TestCase(JCLComponent_TestCase):
def tearDown(self): def tearDown(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Account.dropTable(ifExists = True) Account.dropTable(ifExists = True)
LegacyJID.dropTable(ifExists=True)
ExampleAccount.dropTable(ifExists = True) ExampleAccount.dropTable(ifExists = True)
Example2Account.dropTable(ifExists = True) Example2Account.dropTable(ifExists = True)
del TheURIOpener.cachedURIs['sqlite://' + DB_URL] del TheURIOpener.cachedURIs['sqlite://' + DB_URL]

View File

@@ -27,8 +27,9 @@
__revision__ = "$Id: account.py,v 1.3 2005/09/18 20:24:07 dax Exp $" __revision__ = "$Id: account.py,v 1.3 2005/09/18 20:24:07 dax Exp $"
from sqlobject.inheritance import InheritableSQLObject from sqlobject.inheritance import InheritableSQLObject
from sqlobject.col import StringCol, EnumCol, IntCol, BoolCol from sqlobject.col import StringCol, EnumCol, IntCol, BoolCol, ForeignKey
from sqlobject.dbconnection import ConnectionHub from sqlobject.dbconnection import ConnectionHub
from sqlobject.joins import MultipleJoin
from jcl.lang import Lang from jcl.lang import Lang
from jcl.jabber.error import FieldError from jcl.jabber.error import FieldError
@@ -69,7 +70,8 @@ class Account(InheritableSQLObject):
## Not yet used first_check = BoolCol(default = True) ## Not yet used first_check = BoolCol(default = True)
__status = StringCol(default=OFFLINE, dbName="status") __status = StringCol(default=OFFLINE, dbName="status")
in_error = BoolCol(default=False) in_error = BoolCol(default=False)
legacy_jids = MultipleJoin('LegacyJID')
## Use these attributs to support volatile password ## Use these attributs to support volatile password
## login = StringCol(default = "") ## login = StringCol(default = "")
## password = StringCol(default = None) ## password = StringCol(default = None)
@@ -265,3 +267,11 @@ class PresenceAccount(Account):
return PresenceAccount.DO_NOTHING return PresenceAccount.DO_NOTHING
action = property(get_action) action = property(get_action)
class LegacyJID(InheritableSQLObject):
_connection = hub
legacy_address = StringCol()
jid = StringCol()
account = ForeignKey('Account')