plugin XEP-0384: use "max_items=1" for devices and bundles nodes:
- max_items = 1 is requested with publish-options when publishing the bundle or the devices list. If the constraint is failed, a warning will be shown, and the publication will be done without this option - fixed return values when devices list is badly formed
This commit is contained in:
parent
d1abda6ddb
commit
1faa5e82da
1 changed files with 46 additions and 27 deletions
|
|
@ -23,7 +23,7 @@ from sat.core import exceptions
|
|||
from twisted.internet import defer, reactor
|
||||
from twisted.words.xish import domish
|
||||
from twisted.words.protocols.jabber import jid
|
||||
from twisted.words.protocols.jabber import error
|
||||
from twisted.words.protocols.jabber import error as jabber_error
|
||||
from sat.memory import persistent
|
||||
from functools import partial
|
||||
from sat.tools import xml_tools
|
||||
|
|
@ -397,7 +397,11 @@ class OMEMO(object):
|
|||
host.trigger.add("sendMessageData", self._sendMessageDataTrigger)
|
||||
self.host.registerEncryptionPlugin(self, "OMEMO", NS_OMEMO, 100)
|
||||
pep = host.plugins['XEP-0163']
|
||||
pep.addPEPEvent("OMEMO_DEVICES", NS_OMEMO_DEVICES, self.onNewDevices)
|
||||
pep.addPEPEvent(
|
||||
"OMEMO_DEVICES", NS_OMEMO_DEVICES,
|
||||
lambda itemsEvent, profile: defer.ensureDeferred(
|
||||
self.onNewDevices(itemsEvent, profile))
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def trustUICb(self, xmlui_data, trust_data, expect_problems=None,
|
||||
|
|
@ -570,9 +574,12 @@ class OMEMO(object):
|
|||
# and we save it
|
||||
persistent_dict[KEY_DEVICE_ID] = device_id
|
||||
|
||||
log.debug(f"our OMEMO device id is {device_id}")
|
||||
|
||||
if device_id not in devices:
|
||||
log.debug(f"our device id ({device_id}) is not in the list, adding it")
|
||||
devices.add(device_id)
|
||||
yield self.setDevices(client, devices)
|
||||
yield defer.ensureDeferred(self.setDevices(client, devices))
|
||||
|
||||
all_jids = yield persistent_dict.get(KEY_ALL_JIDS, set())
|
||||
|
||||
|
|
@ -585,7 +592,9 @@ class OMEMO(object):
|
|||
if omemo_session.republish_bundle:
|
||||
log.info(_("Saving public bundle for this device ({device_id})").format(
|
||||
device_id=device_id))
|
||||
yield self.setBundle(client, omemo_session.public_bundle, device_id)
|
||||
yield defer.ensureDeferred(
|
||||
self.setBundle(client, omemo_session.public_bundle, device_id)
|
||||
)
|
||||
client._xep_0384_ready.callback(None)
|
||||
del client._xep_0384_ready
|
||||
|
||||
|
|
@ -608,7 +617,7 @@ class OMEMO(object):
|
|||
list_elt = next(items[0].elements(NS_OMEMO, 'list'))
|
||||
except StopIteration:
|
||||
log.warning(_("no list element found in OMEMO devices list"))
|
||||
return
|
||||
return devices
|
||||
for device_elt in list_elt.elements(NS_OMEMO, 'device'):
|
||||
try:
|
||||
device_id = int(device_elt['id'])
|
||||
|
|
@ -641,18 +650,23 @@ class OMEMO(object):
|
|||
devices = self.parseDevices(items)
|
||||
defer.returnValue(devices)
|
||||
|
||||
def setDevicesEb(self, failure_):
|
||||
log.warning(_("Can't set devices: {reason}").format(reason=failure_))
|
||||
|
||||
def setDevices(self, client, devices):
|
||||
async def setDevices(self, client, devices):
|
||||
log.debug(f"setting devices with {', '.join(devices)}")
|
||||
list_elt = domish.Element((NS_OMEMO, 'list'))
|
||||
for device in devices:
|
||||
device_elt = list_elt.addElement('device')
|
||||
device_elt['id'] = str(device)
|
||||
d = self._p.sendItem(
|
||||
client, None, NS_OMEMO_DEVICES, list_elt, item_id=self._p.ID_SINGLETON)
|
||||
d.addErrback(self.setDevicesEb)
|
||||
return d
|
||||
try:
|
||||
await self._p.sendItem(
|
||||
client, None, NS_OMEMO_DEVICES, list_elt,
|
||||
item_id=self._p.ID_SINGLETON,
|
||||
extra={
|
||||
self._p.EXTRA_PUBLISH_OPTIONS: {self._p.OPT_MAX_ITEMS: 1},
|
||||
self._p.EXTRA_ON_PRECOND_NOT_MET: "publish_without_options",
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(_("Can't set devices: {reason}").format(reason=e))
|
||||
|
||||
# bundles
|
||||
|
||||
|
|
@ -680,7 +694,7 @@ class OMEMO(object):
|
|||
.format(device_id=device_id))
|
||||
missing.add(device_id)
|
||||
continue
|
||||
except error.StanzaError as e:
|
||||
except jabber_error.StanzaError as e:
|
||||
log.warning(_("Can't get bundle for device {device_id}: {reason}")
|
||||
.format(device_id=device_id, reason=e))
|
||||
continue
|
||||
|
|
@ -737,10 +751,7 @@ class OMEMO(object):
|
|||
|
||||
defer.returnValue((bundles, missing))
|
||||
|
||||
def setBundleEb(self, failure_):
|
||||
log.warning(_("Can't set bundle: {reason}").format(reason=failure_))
|
||||
|
||||
def setBundle(self, client, bundle, device_id):
|
||||
async def setBundle(self, client, bundle, device_id):
|
||||
"""Set public bundle for this device.
|
||||
|
||||
@param bundle(ExtendedPublicBundle): bundle to publish
|
||||
|
|
@ -769,31 +780,37 @@ class OMEMO(object):
|
|||
preKeyPublic_elt['preKeyId'] = str(otpk['id'])
|
||||
|
||||
node = NS_OMEMO_BUNDLE.format(device_id=device_id)
|
||||
d = self._p.sendItem(client, None, node, bundle_elt, item_id=self._p.ID_SINGLETON)
|
||||
d.addErrback(self.setBundleEb)
|
||||
return d
|
||||
try:
|
||||
await self._p.sendItem(
|
||||
client, None, node, bundle_elt, item_id=self._p.ID_SINGLETON,
|
||||
extra={
|
||||
self._p.EXTRA_PUBLISH_OPTIONS: {self._p.OPT_MAX_ITEMS: 1},
|
||||
self._p.EXTRA_ON_PRECOND_NOT_MET: "publish_without_options",
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(_("Can't set bundle: {reason}").format(reason=e))
|
||||
|
||||
## PEP node events callbacks
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def onNewDevices(self, itemsEvent, profile):
|
||||
async def onNewDevices(self, itemsEvent, profile):
|
||||
client = self.host.getClient(profile)
|
||||
try:
|
||||
omemo_session = client._xep_0384_session
|
||||
except AttributeError:
|
||||
yield client._xep_0384_ready
|
||||
await client._xep_0384_ready
|
||||
omemo_session = client._xep_0384_session
|
||||
entity = itemsEvent.sender
|
||||
|
||||
devices = self.parseDevices(itemsEvent.items)
|
||||
omemo_session.newDeviceList(entity, devices)
|
||||
await omemo_session.newDeviceList(entity, devices)
|
||||
|
||||
if entity == client.jid.userhostJID():
|
||||
own_device = client._xep_0384_device_id
|
||||
if own_device not in devices:
|
||||
log.warning(_("Our own device is missing from devices list, fixing it"))
|
||||
devices.add(own_device)
|
||||
yield self.setDevices(client, devices)
|
||||
await self.setDevices(client, devices)
|
||||
|
||||
## triggers
|
||||
|
||||
|
|
@ -1098,7 +1115,9 @@ class OMEMO(object):
|
|||
# we don't wait for the Deferred (i.e. no yield) on purpose
|
||||
# there is no need to block the whole message workflow while
|
||||
# updating the bundle
|
||||
self.setBundle(client, omemo_session.public_bundle, device_id)
|
||||
defer.ensureDeferred(
|
||||
self.setBundle(client, omemo_session.public_bundle, device_id)
|
||||
)
|
||||
|
||||
message_elt.children.remove(encrypted_elt)
|
||||
if plaintext:
|
||||
|
|
|
|||
Loading…
Reference in a new issue